Repository navigation
feat(desktop): open sessions in dedicated windows #19051
Workflow file for this run
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
| # Licensed to the Apache Software Foundation (ASF) under one | |
| # or more contributor license agreements. See the NOTICE file | |
| # distributed with this work for additional information | |
| # regarding copyright ownership. The ASF licenses this file | |
| # to you under the Apache License, Version 2.0 (the | |
| # "License"); you may not use this file except in compliance | |
| # with the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, | |
| # software distributed under the License is distributed on an | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| # KIND, either express or implied. See the License for the | |
| # specific language governing permissions and limitations | |
| # under the License. | |
| name: CI | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| # A group holds at most one pending run, and a third entering cancels the queued | |
| # second even with cancel-in-progress off, so every main commit needs its own key. | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| permissions: | |
| contents: read # Checkout only; every write-capable action declares its own scope. | |
| jobs: | |
| # One job, not three. A runner slot is scarcer than a minute on shared | |
| # infrastructure, and splitting planning from validation made every pull | |
| # request queue for a runner three times to reach one verdict. Planning is | |
| # the first step; every later step gates on its outputs, so a | |
| # documentation-only change costs one short allocation rather than two. | |
| # | |
| # The name is `test` because that is the required context in `.asf.yaml`. | |
| # Renaming it would leave that check unreported on every open pull request | |
| # until the rename merged, and nothing could merge while it was unreported. | |
| test: | |
| # Pinned, not `ubuntu-latest`. The two resolve to the same image, but only | |
| # the alias makes this required context wait at the tail, and the steps | |
| # below already assume this image. `ci-workflow-policy.test.mjs` holds the | |
| # rule for every lane. | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false # Do not leave the checkout token in git config. | |
| - id: comparison | |
| name: Resolve checked-out comparison | |
| env: | |
| CI_EVENT_NAME: ${{ github.event_name }} | |
| PUSH_BASE_SHA: ${{ github.event.before }} | |
| PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| # Every diff-based gate must compare the same checked-out tree. | |
| # PR event bases can predate the main parent of the actual merge. | |
| BASE_SHA="" | |
| HEAD_SHA="$(git rev-parse --verify HEAD)" | |
| if [[ "$CI_EVENT_NAME" == "pull_request" ]]; then | |
| MERGED_HEAD_SHA="$(git rev-parse --verify 'HEAD^2')" | |
| if [[ -z "$PR_HEAD_SHA" || "$MERGED_HEAD_SHA" != "$PR_HEAD_SHA" ]]; then | |
| echo "CI comparison requires the merge of the requested PR head" >&2 | |
| exit 1 | |
| fi | |
| BASE_SHA="$(git rev-parse --verify 'HEAD^1')" | |
| elif [[ "$CI_EVENT_NAME" == "push" && ! "$PUSH_BASE_SHA" =~ ^0+$ ]]; then | |
| BASE_SHA="$PUSH_BASE_SHA" | |
| fi | |
| printf 'base=%s\nhead=%s\n' "$BASE_SHA" "$HEAD_SHA" >> "$GITHUB_OUTPUT" | |
| - id: plan | |
| name: Select affected test surfaces | |
| env: | |
| BASE_SHA: ${{ steps.comparison.outputs.base }} | |
| HEAD_SHA: ${{ steps.comparison.outputs.head }} | |
| run: | | |
| # Dispatches, initial pushes and unavailable history select every surface. | |
| if [[ -z "$BASE_SHA" ]] || ! git cat-file -e "${BASE_SHA}^{commit}"; then | |
| node scripts/ci-test-plan.mjs --full >> "$GITHUB_OUTPUT" | |
| else | |
| node scripts/ci-test-plan.mjs --base "$BASE_SHA" --head "$HEAD_SHA" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Test CI planner | |
| run: >- | |
| node --test --test-concurrency=1 scripts/ci-test-plan.test.mjs | |
| scripts/ci-workflow-policy.test.mjs scripts/verify-windows-harness.test.mjs | |
| scripts/run-workspace-tests-parallel.test.mjs | |
| scripts/install-electron-with-retry.test.mjs | |
| # Pure Node like the planner test, and the labelling workflow imports this | |
| # module directly, so a tier or exclusion change is caught here rather | |
| # than by mislabelling live pull requests. | |
| - name: Test PR effort classification | |
| run: node --test --test-concurrency=1 scripts/pr-effort.test.mjs | |
| # The scheduled lifecycle workflow imports this pure policy module. Keep | |
| # its time boundaries and exemptions deterministic before it can write. | |
| - name: Test issue and PR lifecycle policy | |
| run: node --test --test-concurrency=1 scripts/issue-pr-lifecycle.test.mjs | |
| # Same shape and the same needs: a regenerate-and-diff contract that runs | |
| # on Node alone, so it belongs beside the planner test rather than behind | |
| # an install. | |
| - name: Check Windows test inventory | |
| run: npm run windows:inventory | |
| # Deliberately here and not in the e2e job: that job is conditional, and a | |
| # tier this guard only checks when the tier already ran is a guard that | |
| # grows back (#4761). Pure Node, no build -- it reads the spec sources. | |
| - name: Check Electron e2e budget | |
| run: npm run check:e2e-budget | |
| # Runs on the PR merge result: after a sibling protocol change lands on | |
| # main with the same epoch text, the silently merged tree still carries | |
| # the current base parent's epoch and this fails instead of shipping two | |
| # incompatible protocols under one number (#3313). | |
| - name: Guard the protocol compatibility epoch | |
| if: github.event_name == 'pull_request' | |
| env: | |
| BASE_SHA: ${{ steps.comparison.outputs.base }} | |
| run: node scripts/protocol-epoch-check.mjs --base "$BASE_SHA" | |
| - name: Test the epoch guard | |
| run: node --test --test-concurrency=1 scripts/protocol-epoch-check.test.mjs | |
| - name: Test Storybook audit contracts | |
| run: node --test scripts/ax-tree-audit.test.mjs scripts/storybook-visual-smoke.test.mjs scripts/storybook-visual-diff.test.mjs | |
| - name: Test Computer Use script contracts | |
| run: node --test scripts/computer-use/lab-root.test.mjs | |
| - name: Test script entrypoint contracts | |
| run: node --test scripts/script-entrypoints.test.mjs | |
| - name: Test repository-only plugin examples | |
| run: node --test scripts/plugins/codex-app-server-executor/test/plugin.test.mjs | |
| # The packaged Windows lane drives the updater through this wiring. It | |
| # is a few lines, so it is asserted here on every change rather than by | |
| # naming its module in that lane's 25-minute path filter. | |
| - name: Test the packaged update feed wiring | |
| run: node --test --test-concurrency=1 scripts/update-test-feed-wiring.test.mjs | |
| # Install-free like its neighbours: the gate reads one source file and | |
| # compares it to a hand-edited inventory, so a hook that silently widens | |
| # its scope to the whole tree fails here rather than in a profile (#4109). | |
| - name: Check the hooks scoped to the whole shell | |
| run: npm run check:app-shell-hooks | |
| - name: Test the app-shell hook gate | |
| run: node --test --test-concurrency=1 scripts/check-app-shell-hooks.test.mjs | |
| - name: Verify ASF npm preflight policy | |
| run: npm run check:asf-npm | |
| # The source-header gate has to see every file that lands, not only the | |
| # files an affected surface selects, so it runs unconditionally beside | |
| # the other install-free checks. | |
| - name: Check ASF source headers | |
| run: npm run check:asf-headers | |
| # Every tracked input can change the source archive, including docs and images. | |
| - name: Verify repository source archive | |
| run: node scripts/asf-source-release.mjs create --revision HEAD --version "$(node -p 'require("./package.json").version')" | |
| # Locale hygiene ratchet (node built-ins only, so it runs install-free): a new UI locale must only ever mean a new | |
| # UiCatalog key, so locale-literal branches, silent locale defaults, | |
| # and payload sniffing may shrink but never grow. | |
| - name: Check locale hygiene | |
| if: steps.plan.outputs.code == 'true' | |
| env: | |
| BASE_SHA: ${{ steps.comparison.outputs.base }} | |
| run: | | |
| node --test scripts/check-locale-hygiene.test.mjs | |
| if [[ -n "$BASE_SHA" ]]; then | |
| npm run check:locale-hygiene -- --base "$BASE_SHA" | |
| else | |
| npm run check:locale-hygiene | |
| fi | |
| # Everything below this line may need an installed toolchain, so each | |
| # step names the selections it belongs to. `setup-node` itself is | |
| # unconditional: it costs seconds on a runner the job is already holding, | |
| # and gating it needed a twelve-term disjunction over every other | |
| # selection that a new lane had to remember to join (#4475). | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - name: Select the release npm toolchain | |
| if: steps.plan.outputs.cli_package == 'true' | |
| run: npm install --global --no-audit --no-fund "$(node -p 'require("./package.json").packageManager')" | |
| - name: Restore Electron artifact cache | |
| if: steps.plan.outputs.code == 'true' | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/electron | |
| key: electron-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| restore-keys: electron-${{ runner.os }}- | |
| - name: Install Linux runtime dependencies | |
| if: steps.plan.outputs.runtime_sandbox == 'true' || steps.plan.outputs.state_root_compat == 'true' | |
| run: sudo apt-get update && sudo apt-get install -y ripgrep bubblewrap | |
| # Ubuntu 24.04 hosted runners gate unprivileged user namespaces through | |
| # AppArmor, which otherwise makes bwrap fail while configuring loopback. | |
| - name: Enable bubblewrap user namespaces | |
| if: steps.plan.outputs.runtime_sandbox == 'true' || steps.plan.outputs.state_root_compat == 'true' | |
| run: | | |
| if [[ -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]]; then | |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 | |
| fi | |
| if [[ -e /proc/sys/kernel/unprivileged_userns_clone ]]; then | |
| sudo sysctl -w kernel.unprivileged_userns_clone=1 | |
| fi | |
| - name: Install dependencies | |
| if: steps.plan.outputs.code == 'true' || steps.plan.outputs.astryx_surface == 'true' || steps.plan.outputs.asf_source == 'true' || steps.plan.outputs.cli_package == 'true' || steps.plan.outputs.release_contract == 'true' | |
| run: npm ci | |
| - name: Check localized TUI copy boundaries | |
| if: steps.plan.outputs.code == 'true' | |
| run: | | |
| npm run check:tui-copy | |
| node --test scripts/check-tui-copy.test.mjs | |
| - name: Test staged Biome hook | |
| if: steps.plan.outputs.code == 'true' | |
| run: node --test scripts/biome-staged-check.test.mjs | |
| # The header audit above remains install-free. The complete source gate | |
| # also exercises generation and therefore runs after its pinned formatter | |
| # dependency is installed, matching the source-candidate workflow. | |
| - name: Verify ASF source release mechanics | |
| if: steps.plan.outputs.asf_source == 'true' | |
| run: npm run check:asf-source | |
| - name: Lint | |
| if: steps.plan.outputs.code == 'true' | |
| run: npm run lint | |
| - name: Check formatting | |
| if: steps.plan.outputs.code == 'true' | |
| run: npm run format:check | |
| # Parsed dependency rules and an exact legacy-debt ledger keep the | |
| # renderer root from absorbing new feature or Desktop ownership while | |
| # the existing AppShell is migrated behind stable boundaries. | |
| - name: Check renderer architecture | |
| if: steps.plan.outputs.code == 'true' | |
| env: | |
| BASE_SHA: ${{ steps.comparison.outputs.base }} | |
| run: | | |
| if [[ -n "$BASE_SHA" ]]; then | |
| npm run check:renderer-architecture -- --base "$BASE_SHA" --strict-base | |
| else | |
| npm run check:renderer-architecture | |
| fi | |
| # This generated artifact describes the whole renderer/UI tree, so every | |
| # code-validation run checks it even when the triggering diff is outside | |
| # an Astryx surface. Keep it before Build so stale output is reported | |
| # directly instead of being hidden behind an earlier compilation failure. | |
| - name: Astryx surface inventory | |
| if: steps.plan.outputs.code == 'true' || steps.plan.outputs.astryx_surface == 'true' | |
| run: | | |
| npm run astryx:surface-inventory | |
| npm run astryx:surface-inventory:test | |
| - name: Build | |
| if: steps.plan.outputs.code == 'true' || steps.plan.outputs.cli_package == 'true' || steps.plan.outputs.release_contract == 'true' | |
| run: npm run build | |
| # The DeepSeek Harness toolchain is built outside the npm workspace, then | |
| # admitted solely by this digest. Rebuild its pinned linux/amd64 tree in | |
| # hosted CI whenever an input or its identity changes, so a typo or a | |
| # machine-specific tree cannot be committed as an accepted fingerprint. | |
| - name: Verify DeepSeek Harness toolchain fingerprint | |
| if: steps.plan.outputs.deepseek_harness_toolchain == 'true' | |
| run: | | |
| toolchain_root="$RUNNER_TEMP/maka-deepseek-harness-toolchain" | |
| actual="$(node scripts/prepare-deepseek-harness-toolchain.mjs --out "$toolchain_root" | tail -n 1)" | |
| expected="$(node --input-type=module -e 'import { TOOLCHAIN_IDENTITIES } from "./packages/eval/dist/toolchain-verification.js"; console.log(TOOLCHAIN_IDENTITIES["deepseek-harness"].fingerprint);')" | |
| test "$actual" = "$expected" | |
| (cd "$toolchain_root" && sha256sum --check --quiet checksums.sha256) | |
| - name: Release contracts | |
| if: steps.plan.outputs.release_contract == 'true' | |
| run: npm run check:release | |
| - name: Typecheck | |
| if: steps.plan.outputs.code == 'true' | |
| run: npm run typecheck | |
| # Two drift contracts over the shipped app-icon artwork, sitting beside | |
| # the theme drift check for the same reason: the committed bytes are a | |
| # build output that nothing else re-derives, so without this a change to | |
| # the generator, to the `APP_ICONS` catalog, or to the packaged-resource | |
| # list can go green while the artwork it names no longer matches. Those | |
| # are the inputs it selects on; regenerating the artwork costs about a | |
| # minute, and every other code change used to pay it. | |
| - name: App icon artwork drift | |
| if: steps.plan.outputs.app_icons == 'true' | |
| run: node --test scripts/verify-packaged-app-icons.test.mjs scripts/generate-app-icons.test.mjs | |
| - name: Astryx theme drift | |
| if: steps.plan.outputs.code == 'true' | |
| run: npm run astryx:theme -- --check | |
| - name: Knip (apps/desktop) | |
| if: steps.plan.outputs.code == 'true' | |
| run: npx knip --workspace apps/desktop | |
| - name: Knip (packages/ui) | |
| if: steps.plan.outputs.code == 'true' | |
| run: npx knip --workspace packages/ui | |
| - name: Linux sandbox smoke | |
| if: steps.plan.outputs.runtime_sandbox == 'true' | |
| env: | |
| MAKA_REQUIRE_LINUX_SANDBOX_SMOKE: '1' | |
| run: npm exec -w @maka/runtime -- node --test dist/__tests__/linux-sandbox-smoke.test.js | |
| - name: Run affected standard workspace tests | |
| if: steps.plan.outputs.standard_workspaces != '' | |
| env: | |
| STORAGE_STRESS: ${{ steps.plan.outputs.storage_stress }} | |
| WORKSPACES: ${{ steps.plan.outputs.standard_workspaces }} | |
| run: | | |
| if [[ "$STORAGE_STRESS" == "true" ]]; then | |
| export MAKA_STORAGE_STRESS=1 | |
| fi | |
| node scripts/run-workspace-tests-parallel.mjs --concurrency=3 --workspaces="$WORKSPACES" | |
| - name: Run live Eval egress proxy test | |
| if: contains(steps.plan.outputs.standard_workspaces, 'packages/eval') | |
| env: | |
| MAKA_EVAL_EGRESS_PROXY_TEST: '1' | |
| run: | | |
| docker pull python:3.12-slim | |
| docker build \ | |
| --tag maka-eval-egress-proxy:12.2.3 \ | |
| --file packages/eval/harbor/egress-proxy/Dockerfile \ | |
| packages/eval/harbor | |
| npm --workspace @maka/eval run test:egress-proxy:live | |
| - name: Run Runtime Host tests | |
| if: steps.plan.outputs.runtime_host == 'true' | |
| run: npm --workspace @maka/runtime-host run test:dist | |
| # A published predecessor writes the durable state; the workspace built | |
| # above reads it. Release packaging is deliberately not in front of this: | |
| # it takes minutes and changes nothing about whether these decoders can | |
| # read that state. The release lanes still qualify exact tarballs. | |
| - id: forward-roll-baseline | |
| name: Resolve the published forward-roll baseline | |
| if: steps.plan.outputs.state_root_compat == 'true' | |
| run: node scripts/release-cli-publication.mjs resolve-nightly-predecessor "$GITHUB_OUTPUT" | |
| - name: Download the forward-roll baseline | |
| if: steps.plan.outputs.state_root_compat == 'true' | |
| env: | |
| SOURCE_URL: ${{ steps.forward-roll-baseline.outputs.tarball_url }} | |
| SOURCE_INTEGRITY: ${{ steps.forward-roll-baseline.outputs.integrity }} | |
| run: | | |
| set -euo pipefail | |
| source_path="$RUNNER_TEMP/forward-roll-source.tgz" | |
| curl --fail --location --max-filesize 67108864 --proto '=https' --tlsv1.2 \ | |
| --retry 3 --retry-connrefused --retry-delay 2 "$SOURCE_URL" --output "$source_path" | |
| node - "$source_path" "$SOURCE_INTEGRITY" <<'NODE' | |
| const { createHash } = require('node:crypto'); | |
| const { readFileSync } = require('node:fs'); | |
| const bytes = readFileSync(process.argv[2]); | |
| const actual = `sha512-${createHash('sha512').update(bytes).digest('base64')}`; | |
| if (actual !== process.argv[3]) throw new Error('Forward-roll baseline integrity mismatch'); | |
| NODE | |
| { | |
| echo "FORWARD_ROLL_SOURCE=$source_path" | |
| echo "FORWARD_ROLL_SOURCE_SHA256=$(sha256sum "$source_path" | cut -d ' ' -f 1)" | |
| } >> "$GITHUB_ENV" | |
| - name: Qualify durable state against the published baseline | |
| if: steps.plan.outputs.state_root_compat == 'true' | |
| env: | |
| MAKA_QUALIFICATION_BWRAP_USE_SUDO: '1' | |
| run: | | |
| set -o pipefail | |
| npm run --silent release:cli:qualify-state-root -- \ | |
| --source "$FORWARD_ROLL_SOURCE" \ | |
| --source-sha256 "$FORWARD_ROLL_SOURCE_SHA256" \ | |
| --target-workspace "$PWD" \ | |
| | tee "$RUNNER_TEMP/durable-state-report.json" | |
| - name: Ensure xvfb | |
| if: steps.plan.outputs.e2e == 'true' | |
| run: | | |
| command -v Xvfb >/dev/null 2>&1 && command -v xdpyinfo >/dev/null 2>&1 && exit 0 | |
| sudo apt-get update && sudo apt-get install -y xvfb x11-utils | |
| # One X server per worker: a server has one input focus, one pointer and | |
| # one stacking order, and this tier is the set of tests that assert those. | |
| - name: Desktop e2e | |
| if: steps.plan.outputs.e2e == 'true' | |
| run: node scripts/run-desktop-e2e-parallel.mjs --workers 3 | |
| # Playwright keeps a trace, a video and a screenshot for every failed | |
| # test. Without this they die with the runner, and an e2e flake can only | |
| # be diagnosed by reproducing it. | |
| - name: Upload Desktop e2e results | |
| if: failure() && steps.plan.outputs.e2e == 'true' | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: desktop-e2e-results | |
| path: apps/desktop/e2e/test-results/ | |
| if-no-files-found: ignore | |
| retention-days: 7 | |
| - name: Browser WebContentsView semantic smoke | |
| if: steps.plan.outputs.e2e == 'true' | |
| # Hosted Linux runners cannot configure Electron's SUID helper. This | |
| # smoke loads only its loopback fixture; production stays sandboxed. | |
| run: xvfb-run -a npm exec --workspace @maka/desktop -- electron --no-sandbox scripts/browser-observe-act-smoke.mjs | |
| - name: WorkHub native browser presentation smoke | |
| if: steps.plan.outputs.e2e == 'true' | |
| run: xvfb-run -a -s "-screen 0 1920x1080x24" npm exec --workspace @maka/desktop -- electron --no-sandbox scripts/workhub-browser-presentation-smoke.mjs | |
| - name: Browser load failure and retry smoke | |
| if: steps.plan.outputs.e2e == 'true' | |
| # Like the browser smoke above, this uses only a loopback fixture. | |
| run: xvfb-run -a npm exec --workspace @maka/desktop -- electron --no-sandbox scripts/browser-load-failure-smoke.mjs | |
| - name: Alignment audit | |
| if: steps.plan.outputs.e2e == 'true' | |
| run: xvfb-run -a node scripts/audit-alignment.mjs | |
| # The smoke only launches headless; the full Chrome build was downloaded | |
| # and never opened. The headed consumer (perf/storybook.mjs) self-installs. | |
| - name: Install Playwright Chromium | |
| if: steps.plan.outputs.storybook == 'true' | |
| run: npx playwright install --with-deps --only-shell chromium | |
| - name: Build Storybook | |
| if: steps.plan.outputs.storybook == 'true' | |
| run: npm --workspace @maka/desktop run build-storybook | |
| - name: Storybook smoke | |
| if: steps.plan.outputs.storybook == 'true' | |
| run: npm --workspace @maka/desktop run smoke:storybook | |
| - name: Transcript geometry invariants | |
| if: steps.plan.outputs.storybook == 'true' | |
| env: | |
| GEOMETRY_REPETITIONS: '1' | |
| run: xvfb-run -a node scripts/perf/geometry-ablation.mjs --assert-stable | |
| - name: Update stable Rust for CLI packaging | |
| 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@94c31af3204a9f15ab40b35ad084410b905bbc73 # 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@94c31af3204a9f15ab40b35ad084410b905bbc73 # v2 | |
| with: | |
| tool: cargo-deny@0.20.2 | |
| - name: Build CLI release candidate | |
| 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: | | |
| set -o pipefail | |
| kache report --format github | tee -a "$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 |