From 666ef8fab536fb2fc9506c280c54dafd0a84758f Mon Sep 17 00:00:00 2001 From: Codewriter90x <28354595+Codewriter90x@users.noreply.github.com> Date: Wed, 19 Aug 2026 10:24:34 +0200 Subject: [PATCH 1/2] chore(ci): strengthen Unity and native release gates --- .github/pull_request_template.md | 11 ++++ .github/workflows/ci.yml | 48 ++++++++++++++ .github/workflows/codeql.yml | 23 ++++++- .github/workflows/source-release.yml | 13 ++++ docs/README.md | 1 + docs/development/unity-test-gate.md | 64 +++++++++++++++++++ docs/release/RELEASE_PROCESS.md | 12 +++- .../public-readiness-contract-tests.sh | 10 +++ 8 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 docs/development/unity-test-gate.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9666a84..76f6b0d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -21,3 +21,14 @@ Descrivi il comportamento modificato e il motivo. ## Evidenza manuale Indica sistema operativo, versione Unity, dispositivo di input e risultato. +Per modifiche Unity, registra separatamente i totali EditMode e PlayMode usando +il gate descritto in `docs/development/unity-test-gate.md`. Se il job automatico +e disattivato o non riceve i secret nelle PR da fork, questa evidenza e +obbligatoria prima del merge. + +- Commit testato: +- Unity Editor: +- Sistema/architettura: +- EditMode (passed/failed/skipped): +- PlayMode (passed/failed/skipped): +- Motivo di eventuali test non eseguiti: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89bb756..bc81a86 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,9 +71,57 @@ jobs: native-coremidi: runs-on: macos-15 + timeout-minutes: 15 steps: - uses: actions/checkout@v7 with: persist-credentials: false - name: Build and test the macOS arm64 CoreMIDI plug-in run: ./scripts/build-coremidi-plugin-macos-arm64.sh + + unity-tests: + name: Unity ${{ matrix.test-mode }} + if: >- + vars.UNITY_CI_ENABLED == 'true' && + (github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name == github.repository) + runs-on: ubuntu-latest + timeout-minutes: 45 + permissions: + contents: read + checks: write + strategy: + fail-fast: false + matrix: + test-mode: [editmode, playmode] + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + - uses: actions/setup-dotnet@v6 + with: + global-json-file: global.json + - name: Synchronize tested Core assembly into Unity + run: ./scripts/sync-core-to-unity.sh + - name: Run Unity tests + id: unity-tests + uses: game-ci/unity-test-runner@v4 + env: + UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + with: + projectPath: src/HitTheKit.Unity + unityVersion: 6000.5.6f1 + testMode: ${{ matrix.test-mode }} + artifactsPath: artifacts/unity-${{ matrix.test-mode }} + githubToken: ${{ secrets.GITHUB_TOKEN }} + checkName: Unity ${{ matrix.test-mode }} results + - name: Upload Unity test evidence + if: always() + uses: actions/upload-artifact@v7 + with: + name: unity-${{ matrix.test-mode }}-results + path: ${{ steps.unity-tests.outputs.artifactsPath }} + if-no-files-found: warn + retention-days: 14 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index bccdb4c..9100a08 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,7 +12,8 @@ permissions: security-events: write jobs: - analyze: + analyze-csharp: + name: Analyze C# runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -26,3 +27,23 @@ jobs: languages: csharp - uses: github/codeql-action/autobuild@v4 - uses: github/codeql-action/analyze@v4 + with: + category: /language:csharp + + analyze-cpp: + name: Analyze CoreMIDI C++ + runs-on: macos-15 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + - uses: github/codeql-action/init@v4 + with: + languages: c-cpp + build-mode: manual + - name: Build and test the native CoreMIDI plug-in under CodeQL + run: ./scripts/build-coremidi-plugin-macos-arm64.sh + - uses: github/codeql-action/analyze@v4 + with: + category: /language:c-cpp diff --git a/.github/workflows/source-release.yml b/.github/workflows/source-release.yml index 3fa2e7b..167d893 100644 --- a/.github/workflows/source-release.yml +++ b/.github/workflows/source-release.yml @@ -40,13 +40,26 @@ jobs: mkdir -p artifacts/source ./scripts/create-public-source-snapshot.sh "artifacts/source/HitTheKit-source-$RELEASE_VERSION.tar.gz" sha256sum "artifacts/source/HitTheKit-source-$RELEASE_VERSION.tar.gz" > artifacts/source/SHA256SUMS + - name: Verify source snapshot checksum + working-directory: artifacts/source + run: sha256sum --check SHA256SUMS - name: Attest source provenance + id: attest-source uses: actions/attest@v4 with: subject-path: artifacts/source/HitTheKit-source-${{ inputs.version }}.tar.gz + - name: Record source release evidence + run: | + { + printf 'repository=%s\n' "$GITHUB_REPOSITORY" + printf 'commit=%s\n' "$GITHUB_SHA" + printf 'version=%s\n' "$RELEASE_VERSION" + printf 'attestation-url=%s\n' '${{ steps.attest-source.outputs.attestation-url }}' + } > artifacts/source/RELEASE-EVIDENCE.txt - name: Upload source release evidence uses: actions/upload-artifact@v7 with: name: HitTheKit-source-${{ inputs.version }} path: artifacts/source if-no-files-found: error + retention-days: 30 diff --git a/docs/README.md b/docs/README.md index df90ee9..5fc5e9d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -52,6 +52,7 @@ without creating an unreviewed second source of truth. - [Portable MIDI capture](development/portable-midi-capture.md) - [CoreMIDI plug-in build](development/coremidi-plugin-build.md) - [CoreMIDI hardware smoke test](development/coremidi-hardware-smoke.md) +- [Unity EditMode/PlayMode gate](development/unity-test-gate.md) - [URP migration](development/urp-migration.md) ## Packaging and release diff --git a/docs/development/unity-test-gate.md b/docs/development/unity-test-gate.md new file mode 100644 index 0000000..2cd2a3d --- /dev/null +++ b/docs/development/unity-test-gate.md @@ -0,0 +1,64 @@ +# Unity EditMode/PlayMode gate + +Unity changes are not considered validated by the .NET suite alone. The exact +candidate commit must pass both Unity EditMode and PlayMode using Unity +`6000.5.6f1`. + +## Automated gate + +The `unity-tests` CI matrix contains independent `editmode` and `playmode` +jobs. It is deliberately controlled by the repository variable +`UNITY_CI_ENABLED`. + +Keep the variable set to `false` until these repository secrets contain valid +Unity Personal or Professional CI credentials: + +- `UNITY_LICENSE`; +- `UNITY_EMAIL`; +- `UNITY_PASSWORD`. + +After replacing the placeholder values, set `UNITY_CI_ENABLED=true` and run the +workflow manually or update a trusted branch. Confirm both jobs produce XML and +log artifacts before making them required branch checks. + +Repository secrets are unavailable to pull requests from forks by design. Do +not use `pull_request_target` to execute untrusted Unity project code with +secrets. A maintainer must run the manual gate on the fork commit instead. + +## Manual gate + +From a clean checkout on macOS with Unity Hub Editor `6000.5.6f1` installed: + +```sh +./scripts/sync-core-to-unity.sh + +UNITY_EDITOR=/Applications/Unity/Hub/Editor/6000.5.6f1/Unity.app/Contents/MacOS/Unity +PROJECT_PATH="$PWD/src/HitTheKit.Unity" +RESULT_ROOT="$PWD/artifacts/unity-tests" +mkdir -p "$RESULT_ROOT" + +"$UNITY_EDITOR" -batchmode -projectPath "$PROJECT_PATH" \ + -runTests -testPlatform EditMode \ + -testResults "$RESULT_ROOT/editmode-results.xml" \ + -logFile "$RESULT_ROOT/editmode.log" + +"$UNITY_EDITOR" -batchmode -projectPath "$PROJECT_PATH" \ + -runTests -testPlatform PlayMode \ + -testResults "$RESULT_ROOT/playmode-results.xml" \ + -logFile "$RESULT_ROOT/playmode.log" +``` + +Both commands must exit zero. Inspect the XML and logs rather than reporting +only the process exit status. Record the commit SHA, operating system, Editor +revision, architecture, totals, failures and skipped tests in the pull request. + +Documentation-only changes may state that Unity was not required. Runtime, +scene, prefab, package, ProjectSettings, UXML, USS and Editor-tool changes must +provide Unity evidence. + +## Activation boundary + +Never commit a Unity license file, account password or serial. Store credentials +only as encrypted repository or environment secrets. Placeholder secrets are +not valid credentials and the activation variable must remain `false` while +they are present. diff --git a/docs/release/RELEASE_PROCESS.md b/docs/release/RELEASE_PROCESS.md index e50da3e..c34c26d 100644 --- a/docs/release/RELEASE_PROCESS.md +++ b/docs/release/RELEASE_PROCESS.md @@ -32,6 +32,14 @@ release notes. Use Unity `6000.5.6f1` and the exact candidate commit: +The canonical local commands and the relationship between automated and manual +evidence are documented in +[`unity-test-gate.md`](../development/unity-test-gate.md). Automated Unity jobs +remain disabled until the repository variable `UNITY_CI_ENABLED` is explicitly +set to `true` after valid license secrets have been installed. Pull requests +from forks must provide maintainer-generated manual evidence because repository +secrets are intentionally unavailable to untrusted fork workflows. + 1. synchronize the core assembly; 2. build the current CoreMIDI plug-in on macOS; 3. run all Unity EditMode tests; @@ -97,9 +105,11 @@ The release record must include: In the public repository, dispatch `.github/workflows/source-release.yml` for the approved exact version to create an attested, rights-clean source snapshot. -Verify the downloaded artifact with: +The artifact contains the snapshot, `SHA256SUMS`, and +`RELEASE-EVIDENCE.txt`. Verify the downloaded artifact with: ```sh +shasum -a 256 -c SHA256SUMS gh attestation verify HitTheKit-source-0.5.0.tar.gz -R Codewriter90x/HitTheKit ``` diff --git a/tests/scripts/public-readiness-contract-tests.sh b/tests/scripts/public-readiness-contract-tests.sh index d5062d0..ad1e768 100755 --- a/tests/scripts/public-readiness-contract-tests.sh +++ b/tests/scripts/public-readiness-contract-tests.sh @@ -41,6 +41,7 @@ for path in \ docs/legal/ASSET_PROVENANCE.md \ docs/legal/ASSET_PROVENANCE.sha256 \ docs/development/windows-playtest-package.md \ + docs/development/unity-test-gate.md \ docs/release/PUBLIC_RELEASE_CHECKLIST.md \ docs/release/RELEASE_PROCESS.md \ scripts/package-game-windows-x64.sh \ @@ -51,6 +52,15 @@ for path in \ [ -s "$path" ] || fail "required public file is missing or empty: $path" done +grep -Fq "vars.UNITY_CI_ENABLED == 'true'" .github/workflows/ci.yml || \ + fail "Unity CI must stay behind the explicit activation variable" +grep -Fq 'test-mode: [editmode, playmode]' .github/workflows/ci.yml || \ + fail "Unity CI must define both EditMode and PlayMode" +grep -Fq 'languages: c-cpp' .github/workflows/codeql.yml || \ + fail "CodeQL must analyze the native C++ boundary" +grep -Fq 'Verify source snapshot checksum' .github/workflows/source-release.yml || \ + fail "source release workflow must verify its checksum manifest" + case "$PUBLICATION_STATE" in private-preparation) for path in \ From 2ea9b0b6ed68bbbebcff0c022ea7a6a51ab70d77 Mon Sep 17 00:00:00 2001 From: Codewriter90x <28354595+Codewriter90x@users.noreply.github.com> Date: Wed, 19 Aug 2026 10:30:30 +0200 Subject: [PATCH 2/2] fix(ci): preserve required CodeQL check --- .github/workflows/codeql.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9100a08..d538817 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -12,8 +12,7 @@ permissions: security-events: write jobs: - analyze-csharp: - name: Analyze C# + analyze: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7