Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .claude/rules/coding-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# JEngine Coding Patterns

## Async Patterns

Use `UniTask` for async operations, not `System.Threading.Tasks.Task`:
```csharp
public async UniTask<bool> LoadAssetAsync() { }
```

## Thread Safety

For properties accessed across callbacks:
```csharp
private static volatile bool _flag;
public static bool Flag => _flag;
```

## Encryption Architecture

JEngine supports three encryption algorithms:
- **XOR** (`EncryptionOption.Xor`) - Fast, simple
- **AES** (`EncryptionOption.Aes`) - Moderate security
- **ChaCha20** (`EncryptionOption.ChaCha20`) - High security

Each has implementations for bundles and manifests in `Runtime/Encrypt/`.

### Adding New Encryption

1. Create config class in `Runtime/Encrypt/Config/`
2. Implement bundle encryption in `Runtime/Encrypt/Bundle/`
3. Implement manifest encryption in `Runtime/Encrypt/Manifest/`
4. Add to `EncryptionOption` enum
5. Update `EncryptionMapping` class

## ScriptableObject Configuration

Use `ScriptableObject` for runtime configuration:
```csharp
public abstract class ConfigBase<T> : ScriptableObject where T : ConfigBase<T>
{
public static T Instance { get; }
}
```

## Editor Scripts

- Use `[InitializeOnLoad]` for editor initialization
- Handle Unity domain reloads properly (state resets on recompile)
- Use `SessionState` or `EditorPrefs` for persistent editor state
- Clean up resources in `EditorApplication.quitting`
73 changes: 73 additions & 0 deletions .claude/rules/commit-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Commit Message Format

All commits should follow the Conventional Commits specification to enable automatic changelog generation.

## Format

```
<type>(<scope>): <subject>

<body>

<footer>
```

## Types

- `feat:` - New feature (appears in changelog as "Feature")
- `fix:` - Bug fix (appears in changelog as "Fixed")
- `docs:` - Documentation only changes (not in changelog)
- `style:` - Code style/formatting changes (not in changelog)
- `refactor:` - Code refactoring (not in changelog)
- `test:` - Test changes (not in changelog)
- `chore:` - Build/config changes (not in changelog)
- `BREAKING CHANGE:` - Breaking changes (in footer, triggers major version bump)

## Scopes

- `core` - Changes to JEngine.Core package
- `util` - Changes to JEngine.Util package
- `ui` - Changes to JEngine.UI package
- `ci` - Changes to CI/CD workflows
- `docs` - Changes to documentation

## Examples

```bash
feat(core): add ChaCha20 encryption support
fix(util): resolve JAction memory leak on cancellation
docs: update installation guide for Unity 2022.3
refactor(core): simplify bootstrap initialization
test(util): add coverage for JAction edge cases
chore(ci): update GameCI Unity version to 2022.3.55f1
```

## Breaking Changes

For breaking changes, include `BREAKING CHANGE:` in the footer:

```bash
feat(core)!: redesign encryption API

BREAKING CHANGE: EncryptionManager.Encrypt() now requires EncryptionConfig parameter
```

## Guidelines

- Keep subject line under 72 characters
- Use imperative mood ("add" not "added" or "adds")
- Don't capitalize first letter of subject
- Don't end subject with a period
- Separate subject from body with blank line
- Wrap body at 72 characters
- Use body to explain what and why (not how)

## Developer Certificate of Origin (DCO)

All commits must be signed off using `--signoff` (or `-s`) flag:

```bash
git commit -s -m "feat(core): add new feature"
```

This adds a `Signed-off-by` line certifying you have the right to submit the code under the project's license.
38 changes: 38 additions & 0 deletions .claude/rules/package-creation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Creating New JEngine Packages

When creating a new JEngine package:

1. **Version**: Start at `0.0.0` (not `1.0.0`)
2. **Naming**: Use `com.jasonxudeveloper.jengine.<name>` format
3. **Location**: `Packages/com.jasonxudeveloper.jengine.<name>/`

## Required Files

- `package.json` - Package manifest with version `0.0.0`
- `Runtime/<Name>.asmdef` - Assembly definition
- `README.md` - Package documentation (optional)

## Example package.json

```json
{
"name": "com.jasonxudeveloper.jengine.<name>",
"version": "0.0.0",
"displayName": "JEngine.<Name>",
"description": "Description here.",
"license": "MIT",
"unity": "2022.3",
"author": {
"name": "Jason Xu",
"email": "[email protected]",
"url": "https://github.com/JasonXuDeveloper"
},
"dependencies": {}
}
```

## CI Updates Required

1. Add package path to `.github/workflows/pr-tests.yml`
2. Add release support to `.github/workflows/release.yml`
3. Add new scope to commit message conventions
4 changes: 3 additions & 1 deletion .github/instructions/code-review.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ For state accessed across Unity callbacks:
### 5. Namespace Compliance
- Runtime: `JEngine.Core.*`
- Editor: `JEngine.Core.Editor.*`
- No namespace = flag for review
- UI package: `JEngine.UI`
- Hot update: `HotUpdate.Code`
- **Exception**: `Assets/Scripts/` may contain user-level code without namespace (intentional for user customization)

## Common Issues to Flag

Expand Down
2 changes: 2 additions & 0 deletions .github/instructions/jengine.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ JEngine is a Unity hot update framework using HybridCLR for runtime C# execution
### Namespaces
- Runtime code: `JEngine.Core` or `JEngine.Core.*`
- Editor code: `JEngine.Core.Editor` or `JEngine.Core.Editor.*`
- UI package: `JEngine.UI`
- Hot update code: `HotUpdate.Code`
- **Exception**: `Assets/Scripts/` may contain user-level code without namespace (for user customization)

### Async/Await
Always use `UniTask` instead of `Task`:
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/pr-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
src:
- 'UnityProject/Packages/com.jasonxudeveloper.jengine.core/**'
- 'UnityProject/Packages/com.jasonxudeveloper.jengine.util/**'
- 'UnityProject/Packages/com.jasonxudeveloper.jengine.ui/**'
- 'UnityProject/Assets/Tests/**'
- '.github/workflows/unity-tests.yml'
- '.github/workflows/pr-tests.yml'
Expand Down Expand Up @@ -105,7 +106,17 @@ jobs:
files: coverage/**/TestCoverageResults*.xml
flags: util
name: jengine-util
fail_ci_if_error: false
fail_ci_if_error: true
verbose: true

- name: Upload coverage to Codecov (ui package)
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/**/TestCoverageResults*.xml
flags: ui
name: jengine-ui
fail_ci_if_error: true
verbose: true

comment-results:
Expand Down
86 changes: 78 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ on:
description: 'New Util version (e.g., 1.0.1)'
required: false
type: string
release_ui:
description: 'Release JEngine.UI?'
required: true
type: boolean
default: false
ui_version:
description: 'New UI version (e.g., 1.0.0)'
required: false
type: string
manual_changelog:
description: 'Manual changelog entries (optional)'
required: false
Expand All @@ -37,6 +46,7 @@ jobs:
outputs:
core_version: ${{ steps.validate.outputs.core_version }}
util_version: ${{ steps.validate.outputs.util_version }}
ui_version: ${{ steps.validate.outputs.ui_version }}
release_tag: ${{ steps.validate.outputs.release_tag }}
create_github_release: ${{ steps.validate.outputs.create_github_release }}

Expand All @@ -48,7 +58,7 @@ jobs:
id: validate
run: |
# Check at least one package is selected
if [ "${{ inputs.release_core }}" != "true" ] && [ "${{ inputs.release_util }}" != "true" ]; then
if [ "${{ inputs.release_core }}" != "true" ] && [ "${{ inputs.release_util }}" != "true" ] && [ "${{ inputs.release_ui }}" != "true" ]; then
echo "Error: At least one package must be selected for release"
exit 1
fi
Expand All @@ -65,9 +75,11 @@ jobs:
# Get current versions from package.json
CURRENT_CORE_VERSION=$(jq -r '.version' UnityProject/Packages/com.jasonxudeveloper.jengine.core/package.json)
CURRENT_UTIL_VERSION=$(jq -r '.version' UnityProject/Packages/com.jasonxudeveloper.jengine.util/package.json)
CURRENT_UI_VERSION=$(jq -r '.version' UnityProject/Packages/com.jasonxudeveloper.jengine.ui/package.json)

echo "Current Core version: $CURRENT_CORE_VERSION"
echo "Current Util version: $CURRENT_UTIL_VERSION"
echo "Current UI version: $CURRENT_UI_VERSION"

# Validate Core version if releasing
if [ "${{ inputs.release_core }}" == "true" ]; then
Expand Down Expand Up @@ -106,6 +118,24 @@ jobs:
echo "util_version=$CURRENT_UTIL_VERSION" >> $GITHUB_OUTPUT
fi

# Validate UI version if releasing
if [ "${{ inputs.release_ui }}" == "true" ]; then
if [ -z "${{ inputs.ui_version }}" ]; then
echo "Error: UI version is required when releasing UI package"
exit 1
fi
validate_version "${{ inputs.ui_version }}"

if [ "${{ inputs.ui_version }}" == "$CURRENT_UI_VERSION" ]; then
echo "Error: New UI version must be different from current version"
exit 1
fi

echo "ui_version=${{ inputs.ui_version }}" >> $GITHUB_OUTPUT
else
echo "ui_version=$CURRENT_UI_VERSION" >> $GITHUB_OUTPUT
fi

# Release tag always follows Core version
# GitHub releases are only created when Core is released
if [ "${{ inputs.release_core }}" == "true" ]; then
Expand Down Expand Up @@ -276,13 +306,36 @@ jobs:
# Build changelog
CHANGELOG=""

# Add package release info (always show both versions for clarity)
if [ "${{ inputs.release_core }}" == "true" ] && [ "${{ inputs.release_util }}" == "true" ]; then
CHANGELOG="${CHANGELOG}**Released**: JEngine.Core v${{ needs.validate.outputs.core_version }}, JEngine.Util v${{ needs.validate.outputs.util_version }}\n\n"
elif [ "${{ inputs.release_core }}" == "true" ]; then
CHANGELOG="${CHANGELOG}**Released**: JEngine.Core v${{ needs.validate.outputs.core_version }} (Util remains v${{ needs.validate.outputs.util_version }})\n\n"
# Add package release info
RELEASED_PACKAGES=""
UNCHANGED_PACKAGES=""

if [ "${{ inputs.release_core }}" == "true" ]; then
RELEASED_PACKAGES="${RELEASED_PACKAGES}JEngine.Core v${{ needs.validate.outputs.core_version }}, "
else
CHANGELOG="${CHANGELOG}**Released**: JEngine.Util v${{ needs.validate.outputs.util_version }} (Core remains v${{ needs.validate.outputs.core_version }})\n\n"
UNCHANGED_PACKAGES="${UNCHANGED_PACKAGES}Core v${{ needs.validate.outputs.core_version }}, "
fi

if [ "${{ inputs.release_util }}" == "true" ]; then
RELEASED_PACKAGES="${RELEASED_PACKAGES}JEngine.Util v${{ needs.validate.outputs.util_version }}, "
else
UNCHANGED_PACKAGES="${UNCHANGED_PACKAGES}Util v${{ needs.validate.outputs.util_version }}, "
fi

if [ "${{ inputs.release_ui }}" == "true" ]; then
RELEASED_PACKAGES="${RELEASED_PACKAGES}JEngine.UI v${{ needs.validate.outputs.ui_version }}, "
else
UNCHANGED_PACKAGES="${UNCHANGED_PACKAGES}UI v${{ needs.validate.outputs.ui_version }}, "
fi

# Remove trailing comma and space
RELEASED_PACKAGES=$(echo "$RELEASED_PACKAGES" | sed 's/, $//')
UNCHANGED_PACKAGES=$(echo "$UNCHANGED_PACKAGES" | sed 's/, $//')

if [ -n "$UNCHANGED_PACKAGES" ]; then
CHANGELOG="${CHANGELOG}**Released**: ${RELEASED_PACKAGES} (${UNCHANGED_PACKAGES} unchanged)\n\n"
else
CHANGELOG="${CHANGELOG}**Released**: ${RELEASED_PACKAGES}\n\n"
fi

if [ -n "$BREAKING" ]; then
Expand Down Expand Up @@ -341,6 +394,14 @@ jobs:
mv /tmp/package.json UnityProject/Packages/com.jasonxudeveloper.jengine.util/package.json
echo "βœ… Updated Util package.json to v${{ needs.validate.outputs.util_version }}"

- name: Update UI package.json
if: inputs.release_ui == true
run: |
jq '.version = "${{ needs.validate.outputs.ui_version }}"' \
UnityProject/Packages/com.jasonxudeveloper.jengine.ui/package.json > /tmp/package.json
mv /tmp/package.json UnityProject/Packages/com.jasonxudeveloper.jengine.ui/package.json
echo "βœ… Updated UI package.json to v${{ needs.validate.outputs.ui_version }}"

# Update README files (only when releasing Core)
- name: Update README.md
if: inputs.release_core == true
Expand Down Expand Up @@ -554,13 +615,17 @@ jobs:
echo "βœ… **JEngine.Util**: v${{ needs.validate.outputs.util_version }}" >> $GITHUB_STEP_SUMMARY
fi

if [ "${{ inputs.release_ui }}" == "true" ]; then
echo "βœ… **JEngine.UI**: v${{ needs.validate.outputs.ui_version }}" >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "🏷️ **Git Tag**: ${{ needs.validate.outputs.release_tag }}" >> $GITHUB_STEP_SUMMARY

if [ "${{ needs.validate.outputs.create_github_release }}" == "true" ]; then
echo "πŸ“‹ **GitHub Release**: Will be created" >> $GITHUB_STEP_SUMMARY
else
echo "ℹ️ **GitHub Release**: Not created (Util-only update)" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ **GitHub Release**: Not created (non-Core update)" >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
Expand Down Expand Up @@ -605,6 +670,7 @@ jobs:
```bash
openupm add com.jasonxudeveloper.jengine.core
openupm add com.jasonxudeveloper.jengine.util
openupm add com.jasonxudeveloper.jengine.ui # Optional: UI utilities
```

## πŸ“– Documentation
Expand Down Expand Up @@ -637,6 +703,10 @@ jobs:
echo "βœ… **JEngine.Util**: v${{ needs.validate.outputs.util_version }}" >> $GITHUB_STEP_SUMMARY
fi

if [ "${{ inputs.release_ui }}" == "true" ]; then
echo "βœ… **JEngine.UI**: v${{ needs.validate.outputs.ui_version }}" >> $GITHUB_STEP_SUMMARY
fi

echo "" >> $GITHUB_STEP_SUMMARY
echo "**OpenUPM will automatically detect and build the packages within 10-15 minutes.**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
Expand Down
Loading