diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53b88315a6..1f92486daa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -285,9 +285,38 @@ jobs: if: steps.plan.outputs.cli_package == 'true' run: rustup update stable --no-self-update + - id: cli-rustc + name: Resolve CLI Rust cache version + if: steps.plan.outputs.cli_package == 'true' + shell: bash + run: | + echo "version=$(rustc --version | cut -d ' ' -f 2)" >> "$GITHUB_OUTPUT" + echo "revision=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + { + echo "KACHE_CACHE_DIR=${{ runner.temp }}/kache-cli-package" + echo "KACHE_RUNTIME_DIR=${{ runner.temp }}/kache-cli-package-runtime" + echo "RUSTC_WRAPPER=kache" + } >> "$GITHUB_ENV" + + - name: Install Kache for CLI packaging + if: steps.plan.outputs.cli_package == 'true' + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 + with: + tool: kache@0.16.0 + + - id: cli-kache-cache + name: Restore CLI Rust build cache + if: steps.plan.outputs.cli_package == 'true' + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache-cli-package + key: kache-runtime-host-peer-cli-package-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.cli-rustc.outputs.version }}-${{ steps.cli-rustc.outputs.revision }} + restore-keys: | + kache-runtime-host-peer-cli-package-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.cli-rustc.outputs.version }}- + - name: Install cargo-deny for CLI packaging if: steps.plan.outputs.cli_package == 'true' - uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2 + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 with: tool: cargo-deny@0.20.2 @@ -295,6 +324,18 @@ jobs: if: steps.plan.outputs.cli_package == 'true' run: npm run release:cli:pack -- --allow-dirty + - name: Report CLI Rust build cache + if: steps.plan.outputs.cli_package == 'true' + shell: bash + run: kache report --format github >> "$GITHUB_STEP_SUMMARY" + + - name: Save CLI Rust build cache + if: steps.plan.outputs.cli_package == 'true' && github.ref_name == github.event.repository.default_branch + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache-cli-package + key: ${{ steps.cli-kache-cache.outputs.cache-primary-key }} + - name: Validate installed CLI release candidate if: steps.plan.outputs.cli_package == 'true' run: npm run release:cli:smoke -- packages/cli/release/*.tgz diff --git a/.github/workflows/cli-package-validation.yml b/.github/workflows/cli-package-validation.yml index 68b36e7f30..800a39fafe 100644 --- a/.github/workflows/cli-package-validation.yml +++ b/.github/workflows/cli-package-validation.yml @@ -97,6 +97,29 @@ jobs: persist-credentials: false - name: Update stable Rust run: rustup update stable --no-self-update + - id: rustc + name: Resolve Rust cache version + shell: bash + run: | + echo "version=$(rustc --version | cut -d ' ' -f 2)" >> "$GITHUB_OUTPUT" + echo "revision=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + { + echo "KACHE_CACHE_DIR=${{ runner.temp }}/kache" + echo "KACHE_RUNTIME_DIR=${{ runner.temp }}/kache-runtime" + echo "RUSTC_WRAPPER=kache" + } >> "$GITHUB_ENV" + - name: Install Kache + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 + with: + tool: kache@0.16.0 + - id: kache-cache + name: Restore Rust build cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: kache-runtime-host-peer-release-${{ matrix.target }}-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}-${{ steps.rustc.outputs.revision }} + restore-keys: | + kache-runtime-host-peer-release-${{ matrix.target }}-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}- - name: Install the Linux baseline linker if: startsWith(matrix.target, 'linux-') uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 @@ -104,7 +127,7 @@ jobs: version: 0.16.0 - name: Install cargo-zigbuild if: startsWith(matrix.target, 'linux-') - uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2 + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 with: tool: cargo-zigbuild@0.23.2 - name: Build the release addon @@ -112,6 +135,15 @@ jobs: MAKA_RUNTIME_HOST_PEER_CARGO_SUBCOMMAND: ${{ matrix.rust_target && 'zigbuild' || '' }} MAKA_RUNTIME_HOST_PEER_CARGO_TARGET: ${{ matrix.rust_target }} run: node native/runtime-host-peer/build.mjs + - name: Report Rust build cache + shell: bash + run: kache report --format github >> "$GITHUB_STEP_SUMMARY" + - name: Save Rust build cache + if: github.ref_name == github.event.repository.default_branch + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: ${{ steps.kache-cache.outputs.cache-primary-key }} - name: Enforce the Linux glibc baseline if: startsWith(matrix.target, 'linux-') run: | @@ -160,7 +192,7 @@ jobs: - name: Select the release npm toolchain run: npm install --global --no-audit --no-fund "$(node -p 'require("./package.json").packageManager')" - name: Install cargo-deny - uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2 + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 with: tool: cargo-deny@0.20.2 - name: Download direct-peer addons diff --git a/.github/workflows/gitoxide-helper-admission.yml b/.github/workflows/gitoxide-helper-admission.yml index 5c86602d93..5d16b4dab1 100644 --- a/.github/workflows/gitoxide-helper-admission.yml +++ b/.github/workflows/gitoxide-helper-admission.yml @@ -68,12 +68,44 @@ jobs: with: node-version: 24.18.1 cache: npm + - id: rustc + name: Resolve Rust cache version + shell: bash + run: | + echo "version=$(rustc --version | cut -d ' ' -f 2)" >> "$GITHUB_OUTPUT" + echo "revision=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + { + echo "KACHE_CACHE_DIR=${{ runner.temp }}/kache" + echo "KACHE_RUNTIME_DIR=${{ runner.temp }}/kache-runtime" + echo "RUSTC_WRAPPER=kache" + } >> "$GITHUB_ENV" + - name: Install Kache + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 + with: + tool: kache@0.16.0 + - id: kache-cache + name: Restore Rust build cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: kache-gitoxide-helper-test-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}-${{ steps.rustc.outputs.revision }} + restore-keys: | + kache-gitoxide-helper-test-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}- - name: Check Rust formatting working-directory: native/gitoxide-helper run: cargo fmt --check - name: Test the short-lived Gitoxide helper working-directory: native/gitoxide-helper run: cargo test --locked + - name: Report Rust build cache + shell: bash + run: kache report --format github >> "$GITHUB_STEP_SUMMARY" + - name: Save Rust build cache + if: github.ref_name == github.event.repository.default_branch + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: ${{ steps.kache-cache.outputs.cache-primary-key }} - name: Install JavaScript dependencies without packaging hooks run: npm ci --ignore-scripts - name: Build the helper invocation owner diff --git a/.github/workflows/runtime-host-peer-admission.yml b/.github/workflows/runtime-host-peer-admission.yml index ed7e116e54..1a6036ba4e 100644 --- a/.github/workflows/runtime-host-peer-admission.yml +++ b/.github/workflows/runtime-host-peer-admission.yml @@ -64,6 +64,29 @@ jobs: node-version: 24.18.1 - name: Update stable Rust run: rustup update stable --no-self-update + - id: rustc + name: Resolve Rust cache version + shell: bash + run: | + echo "version=$(rustc --version | cut -d ' ' -f 2)" >> "$GITHUB_OUTPUT" + echo "revision=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + { + echo "KACHE_CACHE_DIR=${{ runner.temp }}/kache" + echo "KACHE_RUNTIME_DIR=${{ runner.temp }}/kache-runtime" + echo "RUSTC_WRAPPER=kache" + } >> "$GITHUB_ENV" + - name: Install Kache + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 + with: + tool: kache@0.16.0 + - id: kache-cache + name: Restore Rust build cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: kache-runtime-host-peer-quality-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}-${{ steps.rustc.outputs.revision }} + restore-keys: | + kache-runtime-host-peer-quality-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}- - name: Check Rust formatting working-directory: native/runtime-host-peer run: cargo fmt --check @@ -71,7 +94,7 @@ jobs: working-directory: native/runtime-host-peer run: cargo clippy --locked --all-targets -- -D warnings - name: Install cargo-deny - uses: taiki-e/install-action@fcf5432d9f50d67e37ee6e29bdb7a224ff67b4a7 # v2 + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 with: tool: cargo-deny@0.20.2 - name: Check Cargo dependency inventory @@ -83,3 +106,12 @@ jobs: - name: Test the native peer working-directory: native/runtime-host-peer run: cargo test --locked + - name: Report Rust build cache + shell: bash + run: kache report --format github >> "$GITHUB_STEP_SUMMARY" + - name: Save Rust build cache + if: github.ref_name == github.event.repository.default_branch + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: ${{ steps.kache-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/windows-sandbox-w0.yml b/.github/workflows/windows-sandbox-w0.yml index fc854df250..d20131f0cc 100644 --- a/.github/workflows/windows-sandbox-w0.yml +++ b/.github/workflows/windows-sandbox-w0.yml @@ -57,6 +57,29 @@ jobs: with: node-version: '24' cache: npm + - id: rustc + name: Resolve Rust cache version + shell: bash + run: | + echo "version=$(rustc --version | cut -d ' ' -f 2)" >> "$GITHUB_OUTPUT" + echo "revision=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" + { + echo "KACHE_CACHE_DIR=${{ runner.temp }}/kache" + echo "KACHE_RUNTIME_DIR=${{ runner.temp }}/kache-runtime" + echo "RUSTC_WRAPPER=kache" + } >> "$GITHUB_ENV" + - name: Install Kache + uses: taiki-e/install-action@1ed6d7be6168f6c9046541087ff549b6bc581fdf # v2 + with: + tool: kache@0.16.0 + - id: kache-cache + name: Restore Rust build cache + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: kache-windows-sandbox-launcher-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}-${{ steps.rustc.outputs.revision }} + restore-keys: | + kache-windows-sandbox-launcher-v0.16.0-${{ runner.os }}-${{ runner.arch }}-rust-${{ steps.rustc.outputs.version }}- - name: Record atomic launcher capability shell: pwsh run: ./experiments/windows-sandbox/atomic-launch-capability.ps1 @@ -69,6 +92,15 @@ jobs: - name: Verify launcher protocol and broker authorization working-directory: experiments/windows-sandbox/launcher run: cargo test --locked + - name: Report Rust build cache + shell: bash + run: kache report --format github >> "$GITHUB_STEP_SUMMARY" + - name: Save Rust build cache + if: github.ref_name == github.event.repository.default_branch + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/kache + key: ${{ steps.kache-cache.outputs.cache-primary-key }} - name: Verify secure broker pipe shell: pwsh run: ./experiments/windows-sandbox/broker-pipe-smoke.ps1 diff --git a/scripts/ci-test-plan.test.mjs b/scripts/ci-test-plan.test.mjs index a657ab3450..bc1a23c938 100644 --- a/scripts/ci-test-plan.test.mjs +++ b/scripts/ci-test-plan.test.mjs @@ -352,6 +352,35 @@ test('core CI validates affected installed CLI packages on its existing runner', assert.match(workflow, /run: npm run release:cli:smoke/u); }); +test('Rust build caches publish immutable source generations only from the default branch', () => { + const workflows = readdirSync(WORKFLOW_DIR) + .filter((name) => name.endsWith('.yml')) + .map((name) => [name, readWorkflow(name)]) + .filter(([, workflow]) => workflow.includes('tool: kache@0.16.0')); + + assert.equal(workflows.length, 5); + for (const [name, workflow] of workflows) { + assert.match(workflow, /echo "revision=\$\(git rev-parse HEAD\)"/u, name); + const primaryKeys = [...workflow.matchAll(/^\s+key: (kache-[^\n]+)$/gmu)].map(([, key]) => key); + assert.ok(primaryKeys.length > 0, name); + const restoreKeys = [...workflow.matchAll(/^\s+(kache-[^\n]+-)$/gmu)].map(([, key]) => key); + assert.equal(restoreKeys.length, primaryKeys.length, name); + primaryKeys.forEach((key) => { + assert.match(key, /\$\{\{ steps\.[^.]+\.outputs\.revision \}\}$/u, name); + assert.ok( + restoreKeys.includes(key.replace(/\$\{\{ steps\.[^.]+\.outputs\.revision \}\}$/u, '')), + name, + ); + }); + assert.match( + workflow, + /name: Save [^\n]*Rust build cache\n\s+if: [^\n]*github\.event\.repository\.default_branch/u, + name, + ); + assert.doesNotMatch(workflow, /kache report [^\n]*--since/u, name); + } +}); + test('release contracts run against built CLI outputs', () => { const workflow = readWorkflow('ci.yml'); const buildIndex = workflow.indexOf(' - name: Build\n');