chore: expose repair commit before verification #10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: write | |
| concurrency: | |
| # Release tags never cancel; ordinary CI is cancellable per ref. | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # PR + main branch: lint/typecheck (native-free) and the test suite. | |
| # These never run on tags — a tag is cut from an already-green main. | |
| # --------------------------------------------------------------------------- | |
| check: | |
| if: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: "24" | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }} | |
| - run: bun install --frozen-lockfile | |
| - name: Lint and type check (native-free) | |
| run: bun run ci:check:full | |
| # --------------------------------------------------------------------------- | |
| # PR + main branch: sharded full test suite. Unlike dev CI (changed-path | |
| # affected), Main CI runs the COMPLETE task union via CI_FORCE_FULL. Long-tail | |
| # tasks are sub-split (coding-agent tests 16-way, rust-test 4 nextest | |
| # partitions) so no single shard dominates wall-time. The `test` aggregate job | |
| # keeps the stable branch-protection status name. | |
| # --------------------------------------------------------------------------- | |
| main_plan: | |
| if: ${{ !startsWith(github.ref, 'refs/tags/v') }} | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 10 | |
| env: | |
| CI_FORCE_FULL: "1" | |
| CI_CODING_AGENT_TEST_SHARDS: "16" | |
| CI_RUST_TEST_PARTITIONS: "4" | |
| outputs: | |
| matrix: ${{ steps.plan.outputs.matrix }} | |
| has_tasks: ${{ steps.plan.outputs.has_tasks }} | |
| has_native: ${{ steps.plan.outputs.has_native }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Compute full Main CI task matrix | |
| id: plan | |
| run: bun scripts/ci-dev-affected.ts --matrix-json | |
| main_native: | |
| if: ${{ !startsWith(github.ref, 'refs/tags/v') && needs.main_plan.outputs.has_native == 'true' }} | |
| needs: [main_plan] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: "24" | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }} | |
| - run: bun install --frozen-lockfile | |
| - name: Build native addon (linux-x64 baseline + modern) | |
| env: | |
| TARGET_PLATFORM: linux | |
| TARGET_ARCH: x64 | |
| TARGET_VARIANTS: baseline modern | |
| run: bun run ci:build:native | |
| - name: Verify required native addon variants | |
| run: | | |
| test -f packages/natives/native/pi_natives.linux-x64-baseline.node | |
| test -f packages/natives/native/pi_natives.linux-x64-modern.node | |
| - name: Upload native addon(s) | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: main-native-${{ github.run_id }} | |
| path: | | |
| packages/natives/native/pi_natives.linux-x64-baseline.node | |
| packages/natives/native/pi_natives.linux-x64-modern.node | |
| if-no-files-found: error | |
| retention-days: 1 | |
| overwrite: true | |
| main_shards: | |
| name: test-shard / ${{ matrix.key }} | |
| if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') && needs.main_plan.outputs.has_tasks == 'true' && needs.main_native.result != 'failure' && needs.main_native.result != 'cancelled' }} | |
| needs: [main_plan, main_native] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: ${{ matrix.rust && 90 || 60 }} | |
| strategy: | |
| fail-fast: false | |
| max-parallel: 16 | |
| matrix: ${{ fromJSON(needs.main_plan.outputs.matrix) }} | |
| env: | |
| CI_FORCE_FULL: "1" | |
| CI_CODING_AGENT_TEST_SHARDS: "16" | |
| CI_RUST_TEST_PARTITIONS: "4" | |
| AFFECTED_TASK_KEY: ${{ matrix.key }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: "24" | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - uses: dtolnay/rust-toolchain@5b842231ba77f5c045dba54ac5560fed2db780e2 # nightly | |
| if: ${{ matrix.rust }} | |
| with: | |
| toolchain: nightly-2026-04-29 | |
| - uses: taiki-e/install-action@56545b37b57562edd73171cb6c62cc509db4c34e # v2 | |
| if: ${{ matrix.nextest }} | |
| with: | |
| tool: nextest@0.9.137 | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| if: ${{ matrix.rust }} | |
| with: | |
| shared-key: main-rust-linux-x64 | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| cache-workspace-crates: true | |
| - name: Cache bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }} | |
| - run: bun install --frozen-lockfile | |
| - name: Download native addon(s) | |
| if: ${{ matrix.native }} | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: main-native-${{ github.run_id }} | |
| path: packages/natives/native | |
| - name: Run task shard | |
| env: | |
| GITHUB_ACTIONS: "" | |
| run: bun scripts/ci-dev-affected.ts --task="$AFFECTED_TASK_KEY" | |
| # Branch protection must keep requiring this stable aggregate status. | |
| test: | |
| if: ${{ always() && !startsWith(github.ref, 'refs/tags/v') }} | |
| needs: [main_plan, main_native, main_shards] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Fail closed unless every shard succeeded | |
| run: | | |
| plan='${{ needs.main_plan.result }}' | |
| native='${{ needs.main_native.result }}' | |
| shards='${{ needs.main_shards.result }}' | |
| echo "main_plan=$plan main_native=$native main_shards=$shards" | |
| test "$plan" = success | |
| case "$native" in success|skipped) ;; *) echo "native gate failed"; exit 1;; esac | |
| test "$shards" = success | |
| # --------------------------------------------------------------------------- | |
| # Tag (vX.Y.Z) only: build native addons for every published platform, | |
| # build the standalone binaries, then publish to npm and cut the GitHub | |
| # Release. Self-contained — no dependency on a separate main CI run. | |
| # --------------------------------------------------------------------------- | |
| native: | |
| if: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| timeout-minutes: 90 | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { os: ubuntu-22.04, platform: linux, arch: x64, variant: baseline, rust_checks: true } | |
| - { os: ubuntu-22.04, platform: linux, arch: x64, variant: modern } | |
| - { os: ubuntu-22.04, platform: linux, arch: arm64, target: aarch64-unknown-linux-gnu } | |
| - { os: macos-14, platform: darwin, arch: arm64 } | |
| - { os: macos-15-intel, platform: darwin, arch: x64, variant: baseline } | |
| - { os: windows-latest, platform: win32, arch: x64, variant: baseline } | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: ./.github/actions/build-native | |
| with: | |
| hash: ${{ github.sha }} | |
| platform: ${{ matrix.platform }} | |
| arch: ${{ matrix.arch }} | |
| variant: ${{ matrix.variant }} | |
| target: ${{ matrix.target }} | |
| rust_checks: ${{ matrix.rust_checks && 'true' || 'false' }} | |
| save_cache: "true" | |
| binaries: | |
| if: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| needs: [native] | |
| timeout-minutes: 60 | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { os: ubuntu-22.04, platform: linux, arch: x64, target_id: linux-x64, binary_path: packages/coding-agent/binaries/gjc-linux-x64 } | |
| - { os: ubuntu-24.04-arm, platform: linux, arch: arm64, target_id: linux-arm64, binary_path: packages/coding-agent/binaries/gjc-linux-arm64 } | |
| - { os: macos-14, platform: darwin, arch: arm64, target_id: darwin-arm64, binary_path: packages/coding-agent/binaries/gjc-darwin-arm64 } | |
| - { os: macos-15-intel, platform: darwin, arch: x64, target_id: darwin-x64, binary_path: packages/coding-agent/binaries/gjc-darwin-x64 } | |
| - { os: windows-latest, platform: win32, arch: x64, target_id: win32-x64, binary_path: packages/coding-agent/binaries/gjc-windows-x64.exe } | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: "24" | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }} | |
| - run: bun install --frozen-lockfile | |
| - name: Download native addon(s) | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| pattern: pi-natives-${{ matrix.platform }}-${{ matrix.arch }}* | |
| path: packages/natives/native | |
| merge-multiple: true | |
| - name: Build release binary | |
| env: | |
| RELEASE_TARGETS: ${{ matrix.target_id }} | |
| run: bun run ci:release:build-binaries | |
| - name: Smoke release binary | |
| if: runner.os != 'Windows' | |
| run: | | |
| runtime_dir="$(mktemp -d)" | |
| HOME="$runtime_dir/home" XDG_DATA_HOME="$runtime_dir/xdg" "${{ matrix.binary_path }}" --version | |
| HOME="$runtime_dir/home" XDG_DATA_HOME="$runtime_dir/xdg" "${{ matrix.binary_path }}" --smoke-test | |
| - name: Smoke release binary (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| $runtimeDir = Join-Path $env:TEMP ("gjc-runtime-" + [System.Guid]::NewGuid().ToString("N")) | |
| New-Item -ItemType Directory -Force -Path $runtimeDir | Out-Null | |
| $env:HOME = Join-Path $runtimeDir "home" | |
| $env:XDG_DATA_HOME = Join-Path $runtimeDir "xdg" | |
| & "${{ matrix.binary_path }}" --version | |
| & "${{ matrix.binary_path }}" --smoke-test | |
| - name: Upload release binary artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: gjc-binary-${{ matrix.target_id }} | |
| path: ${{ matrix.binary_path }} | |
| publish: | |
| if: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
| needs: [native, binaries] | |
| timeout-minutes: 45 | |
| runs-on: ubuntu-22.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: "24" | |
| - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version: "1.3.14" | |
| - name: Cache bun dependencies | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: bun-1.3.14-${{ runner.os }}-${{ hashFiles('**/bun.lock') }} | |
| - run: bun install --frozen-lockfile | |
| - name: Download all native addons | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| pattern: pi-natives-* | |
| path: packages/natives/native | |
| merge-multiple: true | |
| - name: Publish packages to npm | |
| env: | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| evidence_dir="$RUNNER_TEMP/release-evidence" | |
| mkdir -p "$evidence_dir" | |
| bun scripts/ci-release-publish.ts --prepare-evidence --evidence-dir "$evidence_dir" | |
| npm_config="$(mktemp "$RUNNER_TEMP/npmrc.XXXXXX")" | |
| trap 'rm -f "$npm_config"' EXIT | |
| printf "//registry.npmjs.org/:_authToken=%s\n" "$NPM_TOKEN" > "$npm_config" | |
| NPM_CONFIG_USERCONFIG="$npm_config" NODE_AUTH_TOKEN="$NPM_TOKEN" \ | |
| bun scripts/ci-release-publish.ts --publish-from-evidence \ | |
| --evidence-dir "$evidence_dir" \ | |
| --release-serialization-key gajae-production-release | |
| - name: Download release binaries | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| pattern: gjc-binary-* | |
| path: release-binaries | |
| merge-multiple: true | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: true | |
| files: release-binaries/gjc-* |