ci: restructured workflow pipelines and introduced bazel cache actions
- Updated bazel cache key generation with v2 schema version and streamlined remote cache usage. - Added native-inputs composite action to centralize change detection and artifact caching. - Added a scheduled workflow to warm the hosted bazel disk cache. - Split the rust validation job and integrated prebuilt native addon caching into the CI pipeline.
This commit is contained in:
@@ -1,24 +1,20 @@
|
||||
name: "Compose bazel cache config"
|
||||
description: >
|
||||
Selects the CI cache backend and emits a bazelrc fragment. A shell probe
|
||||
exposes the backend through step outputs before any action condition uses it.
|
||||
exposes the backend through step outputs before any action condition
|
||||
uses it.
|
||||
|
||||
omp-kata jobs use the cluster remote cache. An exporting main job first
|
||||
performs an exact GitHub cache lookup without downloading the archive. A
|
||||
genuine miss switches that job to a local disk cache for one build. The
|
||||
workflow saves that populated cache explicitly after the build.
|
||||
|
||||
GitHub-hosted jobs restore the exported disk cache and never contact the
|
||||
cluster. Build callers can save a new exact-key archive after a miss.
|
||||
omp-kata jobs use the cluster remote cache. GitHub-hosted jobs use an
|
||||
actions/cache-backed disk cache seeded by the bazel-cache-warm workflow
|
||||
on the same runner image — cross-host action keys never hit, so the disk
|
||||
cache is hosted-only and its key carries a schema version (v2; v1 was
|
||||
poisoned by a kata-produced export that silently missed every action).
|
||||
Consumers save a new exact-key archive after a miss.
|
||||
|
||||
inputs:
|
||||
scope:
|
||||
description: Disk-cache key discriminator shared by compatible consumers
|
||||
required: true
|
||||
export:
|
||||
description: Prepare a portable disk cache after an exact lookup miss
|
||||
required: false
|
||||
default: "false"
|
||||
|
||||
outputs:
|
||||
rc:
|
||||
@@ -27,9 +23,6 @@ outputs:
|
||||
cache-key:
|
||||
description: Exact GitHub cache key for a later explicit save
|
||||
value: ${{ steps.backend.outputs.cache-key }}
|
||||
export-needed:
|
||||
description: Whether the remote exporter switched to a portable disk cache
|
||||
value: ${{ steps.compose.outputs.export-needed }}
|
||||
save-needed:
|
||||
description: Whether a disk-cache build can save a new exact-key archive
|
||||
value: ${{ steps.compose.outputs.save-needed }}
|
||||
@@ -44,7 +37,7 @@ runs:
|
||||
id: backend
|
||||
shell: bash
|
||||
env:
|
||||
CACHE_KEY: bazel-disk-${{ inputs.scope }}-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.Bazel.lock', 'MODULE.bazel', 'rust-toolchain.toml') }}
|
||||
CACHE_KEY: bazel-disk-v2-${{ inputs.scope }}-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.Bazel.lock', 'MODULE.bazel', 'MODULE.bazel.lock', 'rust-toolchain.toml', '.bazelrc', '.bazelversion', 'bazel/**') }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
remote=false
|
||||
@@ -68,32 +61,17 @@ runs:
|
||||
path: ~/.cache/omp-bazel-disk
|
||||
key: ${{ steps.backend.outputs.cache-key }}
|
||||
restore-keys: |
|
||||
bazel-disk-${{ inputs.scope }}-${{ runner.os }}-${{ runner.arch }}-
|
||||
|
||||
- name: Look up bazel disk cache export
|
||||
if: steps.backend.outputs.remote == 'true' && inputs.export == 'true'
|
||||
id: export
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ~/.cache/omp-bazel-disk
|
||||
key: ${{ steps.backend.outputs.cache-key }}
|
||||
lookup-only: true
|
||||
bazel-disk-v2-${{ inputs.scope }}-${{ runner.os }}-${{ runner.arch }}-
|
||||
|
||||
- name: Compose cache config
|
||||
id: compose
|
||||
shell: bash
|
||||
env:
|
||||
REMOTE: ${{ steps.backend.outputs.remote }}
|
||||
EXPORT_REQUESTED: ${{ inputs.export }}
|
||||
EXPORT_HIT: ${{ steps.export.outputs.cache-hit }}
|
||||
RESTORE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
export_needed=false
|
||||
if [ "$REMOTE" = "true" ] && [ "$EXPORT_REQUESTED" = "true" ] && [ "$EXPORT_HIT" != "true" ]; then
|
||||
export_needed=true
|
||||
fi
|
||||
save_needed=$export_needed
|
||||
save_needed=false
|
||||
if [ "$REMOTE" != "true" ] && [ "$RESTORE_HIT" != "true" ]; then
|
||||
save_needed=true
|
||||
fi
|
||||
@@ -107,26 +85,16 @@ runs:
|
||||
echo "common --config=ci"
|
||||
echo "common --repository_cache=/opt/bazel-repo-cache"
|
||||
echo "common --repo_env=OMP_XWIN_CACHE_DIR=/opt/bazel-repo-cache/xwin"
|
||||
} > "$rc"
|
||||
|
||||
if [ "$export_needed" = "true" ]; then
|
||||
# Do not combine remote and disk caches. Remote hits do not
|
||||
# materialize a portable disk cache for hosted runners.
|
||||
mkdir -p "$HOME/.cache/omp-bazel-disk"
|
||||
echo "common --disk_cache=$HOME/.cache/omp-bazel-disk" >> "$rc"
|
||||
else
|
||||
raw_auth="${BAZEL_REMOTE_USER}:${BAZEL_REMOTE_PASSWORD}"
|
||||
auth="$(printf %s "$raw_auth" | base64 | tr -d '\n')"
|
||||
echo "::add-mask::$raw_auth"
|
||||
echo "::add-mask::$auth"
|
||||
{
|
||||
echo "common --config=cache-rw"
|
||||
echo "common --remote_cache=grpcs://bazel-remote.bazel-cache.svc.cluster.local:9092"
|
||||
echo "common --tls_certificate=infra/bazel-remote/ca.crt"
|
||||
echo "common --remote_header='authorization=Basic ${auth}'"
|
||||
echo "common --remote_download_toplevel"
|
||||
} >> "$rc"
|
||||
fi
|
||||
echo "common --config=cache-rw"
|
||||
echo "common --remote_cache=grpcs://bazel-remote.bazel-cache.svc.cluster.local:9092"
|
||||
echo "common --tls_certificate=infra/bazel-remote/ca.crt"
|
||||
echo "common --remote_header='authorization=Basic ${auth}'"
|
||||
echo "common --remote_download_toplevel"
|
||||
} > "$rc"
|
||||
else
|
||||
mkdir -p "$HOME/.cache/omp-bazel-disk" "$HOME/.cache/omp-bazel-repo"
|
||||
{
|
||||
@@ -138,6 +106,5 @@ runs:
|
||||
|
||||
{
|
||||
echo "rc=$rc"
|
||||
echo "export-needed=$export_needed"
|
||||
echo "save-needed=$save_needed"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
name: "Native inputs: change detection + artifact cache key"
|
||||
description: >
|
||||
Single source of truth for what counts as a native-affecting change.
|
||||
|
||||
`rust` gates Rust validation (tests, clippy, rustfmt); `cache-key`
|
||||
addresses the prebuilt Linux x64 addon pair published by trusted main
|
||||
builds. The detector pathspec and the hashed file set MUST cover the same
|
||||
inputs — drift means a native change could ship without validation or be
|
||||
tested against stale addons. The key embeds a schema version, OS, arch,
|
||||
target pair, and build profile so a future target/profile change can
|
||||
never resolve valid-but-wrong .node files under the same source hash.
|
||||
|
||||
outputs:
|
||||
rust:
|
||||
description: Whether the event touches native inputs (always true off pull_request)
|
||||
value: ${{ steps.changes.outputs.rust }}
|
||||
source-hash:
|
||||
description: 16-hex fingerprint over every native build input
|
||||
value: ${{ steps.hash.outputs.source-hash }}
|
||||
cache-key:
|
||||
description: Exact actions/cache key for the prebuilt Linux x64 addon pair
|
||||
value: ${{ steps.hash.outputs.cache-key }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Detect native-affecting changes
|
||||
id: changes
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "${{ github.event_name }}" != "pull_request" ]; then
|
||||
echo "rust=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
if gh pr diff ${{ github.event.pull_request.number }} --name-only \
|
||||
| grep -qE '^(crates/|bazel/|Cargo\.(toml|lock)|Cargo\.Bazel\.lock|MODULE\.bazel(\.lock)?|BUILD\.bazel|\.bazelrc|\.bazelignore|\.bazelversion|rust-toolchain\.toml|rustfmt\.toml|scripts/bazel-natives\.ts|\.github/actions/(bazel-cache|bazel-natives|native-artifacts|native-inputs)/|\.github/workflows/ci\.yml)'; then
|
||||
echo "rust=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "No native-affecting changes; skipping Rust validation."
|
||||
echo "rust=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Content-addresses the addon bytes. `git ls-files` covers path +
|
||||
# content + mode of every tracked input; a listed path that disappears
|
||||
# fails the step loudly instead of silently narrowing the key.
|
||||
- name: Compute native source hash
|
||||
id: hash
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
source_hash=$(git ls-files -z -- \
|
||||
crates bazel \
|
||||
Cargo.toml Cargo.lock Cargo.Bazel.lock \
|
||||
MODULE.bazel MODULE.bazel.lock BUILD.bazel \
|
||||
.bazelrc .bazelignore .bazelversion \
|
||||
rust-toolchain.toml rustfmt.toml \
|
||||
scripts/bazel-natives.ts \
|
||||
.github/actions/bazel-cache .github/actions/bazel-natives \
|
||||
.github/actions/native-artifacts .github/actions/native-inputs \
|
||||
.github/workflows/ci.yml \
|
||||
| sort -z \
|
||||
| xargs -0 sha256sum \
|
||||
| sha256sum \
|
||||
| cut -c1-16)
|
||||
{
|
||||
echo "source-hash=$source_hash"
|
||||
echo "cache-key=native-addons-v1-linux-x64-baseline+modern-opt-$source_hash"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
echo "Native source hash: $source_hash"
|
||||
@@ -0,0 +1,43 @@
|
||||
name: Warm bazel disk cache
|
||||
|
||||
# GitHub-hosted PR runners cannot use the cluster remote cache and only see
|
||||
# actions/cache entries created on the default branch. Bazel action keys do
|
||||
# not transfer across runner environments (a kata-produced disk cache misses
|
||||
# every action on ubuntu-22.04), so seed the disk cache from the same image
|
||||
# PR jobs run on. A warm run restores the exact-key archive, builds
|
||||
# incrementally, and saves nothing; a lockfile/config change misses, rebuilds,
|
||||
# and saves the new key.
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "23 */6 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: bazel-cache-warm
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
warm:
|
||||
name: Seed hosted bazel disk cache
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: cache
|
||||
uses: ./.github/actions/bazel-cache
|
||||
with:
|
||||
scope: linux
|
||||
- name: Build native addons
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ "$(ulimit -Sn)" != unlimited ] && [ "$(ulimit -Sn)" -lt 65536 ]; then ulimit -Sn 65536 || true; fi
|
||||
bazelisk --bazelrc="${{ steps.cache.outputs.rc }}" build //:natives-linux-x64-baseline //:natives-linux-x64-modern
|
||||
- name: Save bazel disk cache
|
||||
if: steps.cache.outputs.save-needed == 'true'
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ~/.cache/omp-bazel-disk
|
||||
key: ${{ steps.cache.outputs.cache-key }}
|
||||
+176
-53
@@ -118,44 +118,26 @@ jobs:
|
||||
- name: Build collab web
|
||||
run: bun run collab:web:build
|
||||
|
||||
# One Bazel job validates Rust changes and builds native addons for every
|
||||
# downstream job. Main builds all Linux-hosted targets. Pull requests build
|
||||
# only the Linux x64 pair required by tests.
|
||||
rust:
|
||||
# Rust validation (tests, clippy, rustfmt) and native addon production are
|
||||
# separate jobs: TS test shards wait only on the addons, and on
|
||||
# native-changing PRs validation no longer delays artifact production.
|
||||
rust_validate:
|
||||
name: Validate Rust workspace (bazel)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# TS-only PRs skip Rust validation. They still materialize the Linux
|
||||
# x64 addons once from the main-exported disk cache.
|
||||
- name: Detect Rust-affecting changes
|
||||
id: changes
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" != "pull_request" ]; then
|
||||
echo "rust=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
if gh pr diff ${{ github.event.pull_request.number }} --name-only \
|
||||
| grep -qE '^(crates/|Cargo\.(toml|lock)|Cargo\.Bazel\.lock|MODULE\.bazel|BUILD\.bazel|\.bazelrc|\.bazelversion|bazel/|rust-toolchain\.toml|rustfmt\.toml|scripts/bazel-natives|\.github/actions/bazel-|\.github/workflows/ci\.yml)'; then
|
||||
echo "rust=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "No Rust-affecting changes; skipping validation."
|
||||
echo "rust=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- if: steps.changes.outputs.rust == 'true'
|
||||
- id: inputs
|
||||
uses: ./.github/actions/native-inputs
|
||||
# TS-only PRs skip Rust validation entirely.
|
||||
- if: steps.inputs.outputs.rust == 'true'
|
||||
uses: ./.github/actions/bun-install
|
||||
- id: cache
|
||||
if: steps.inputs.outputs.rust == 'true'
|
||||
uses: ./.github/actions/bazel-cache
|
||||
with:
|
||||
scope: linux
|
||||
# Main pushes export the disk cache PRs restore (once per
|
||||
# lockfile change; no-op otherwise).
|
||||
export: ${{ github.event_name != 'pull_request' }}
|
||||
- name: Rust tests
|
||||
if: steps.changes.outputs.rust == 'true'
|
||||
if: steps.inputs.outputs.rust == 'true'
|
||||
# The ulimit guard runs in the step that launches the bazel server
|
||||
# (limits are per-process and the server persists across steps).
|
||||
run: |
|
||||
@@ -166,35 +148,175 @@ jobs:
|
||||
# `[lints] workspace = true` get the workspace policy, the vendored
|
||||
# brush fork is exempt (same as run-rs-task.ts's cargo excludes).
|
||||
- name: Clippy (workspace lint policy on opted-in crates)
|
||||
if: steps.changes.outputs.rust == 'true'
|
||||
if: steps.inputs.outputs.rust == 'true'
|
||||
run: |
|
||||
bazelisk query "kind('rust_library|rust_shared_library', //crates/pi-ast/... + //crates/pi-iso/... + //crates/pi-natives/... + //crates/pi-shell/... + //crates/pi-walker/...)" \
|
||||
| xargs bazelisk --bazelrc="${{ steps.cache.outputs.rc }}" build --config=clippy-strict --
|
||||
- name: Clippy (default lints elsewhere)
|
||||
if: steps.changes.outputs.rust == 'true'
|
||||
if: steps.inputs.outputs.rust == 'true'
|
||||
run: |
|
||||
bazelisk query "kind('rust_library|rust_shared_library', //crates/... - (//crates/pi-ast/... + //crates/pi-iso/... + //crates/pi-natives/... + //crates/pi-shell/... + //crates/pi-walker/...) - //crates/vendor/brush-core/... - //crates/vendor/brush-builtins/...)" \
|
||||
| xargs bazelisk --bazelrc="${{ steps.cache.outputs.rc }}" build --config=clippy --
|
||||
- name: Rustfmt
|
||||
if: steps.changes.outputs.rust == 'true'
|
||||
if: steps.inputs.outputs.rust == 'true'
|
||||
run: bazelisk --bazelrc="${{ steps.cache.outputs.rc }}" build --config=rustfmt //crates/...
|
||||
|
||||
# Builds the native addons every downstream job installs. TS-only PRs
|
||||
# restore the prebuilt Linux x64 pair published by trusted main builds
|
||||
# (exact content-addressed key, smoke-loaded before use) and skip Bazel
|
||||
# entirely; anything else builds with bazel. Main builds all Linux-hosted
|
||||
# targets, pull requests only the x64 pair tests require.
|
||||
native_addons:
|
||||
name: Build native addons (bazel)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: inputs
|
||||
uses: ./.github/actions/native-inputs
|
||||
# Trusted fast path. Exact-key restores only — a prefix fallback
|
||||
# could resolve valid-but-wrong .node files under a changed
|
||||
# target/profile (the key embeds schema + os/arch + target pair +
|
||||
# build profile + input hash; see native-inputs action).
|
||||
- name: Restore prebuilt native addons
|
||||
id: prebuilt
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ~/.cache/omp-native-addons
|
||||
key: ${{ steps.inputs.outputs.cache-key }}
|
||||
- name: Stage cached addons
|
||||
if: steps.prebuilt.outputs.cache-hit == 'true'
|
||||
shell: bash
|
||||
# Canonical filenames come from the target map in
|
||||
# scripts/bazel-natives.ts; staging reproduces the bazel-bin
|
||||
# layout the artifact upload below globs.
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p bazel-bin/natives-linux-x64-baseline bazel-bin/natives-linux-x64-modern
|
||||
cp ~/.cache/omp-native-addons/pi_natives.linux-x64-baseline.node bazel-bin/natives-linux-x64-baseline/
|
||||
cp ~/.cache/omp-native-addons/pi_natives.linux-x64-modern.node bazel-bin/natives-linux-x64-modern/
|
||||
# A poisoned cache entry must not ship: load both addons before
|
||||
# trusting them. Failure falls back to a full build (loudly) rather
|
||||
# than failing the PR.
|
||||
- name: Smoke cached addons
|
||||
id: smoke
|
||||
if: steps.prebuilt.outputs.cache-hit == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -uo pipefail
|
||||
# NOTE: `bun -e 'require("./x.node")'` swallows dlopen failures
|
||||
# (exit 0 on a bogus addon); a script file enforces them in
|
||||
# both bun and node. Verified against a corrupt .node fixture.
|
||||
cat > "$RUNNER_TEMP/smoke-addons.js" <<'EOF'
|
||||
for (const f of process.argv.slice(2)) {
|
||||
const m = require(f);
|
||||
if (!m || Object.keys(m).length === 0) {
|
||||
console.error(`addon failed to load: ${f}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
loader=node
|
||||
if command -v bun >/dev/null 2>&1; then loader=bun; fi
|
||||
if "$loader" "$RUNNER_TEMP/smoke-addons.js" \
|
||||
"$PWD/bazel-bin/natives-linux-x64-baseline/pi_natives.linux-x64-baseline.node" \
|
||||
"$PWD/bazel-bin/natives-linux-x64-modern/pi_natives.linux-x64-modern.node"; then
|
||||
echo "ok=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "::warning::cached native addons failed to load; falling back to a full bazel build"
|
||||
rm -rf bazel-bin
|
||||
echo "ok=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Decide build path
|
||||
id: decide
|
||||
shell: bash
|
||||
env:
|
||||
HIT: ${{ steps.prebuilt.outputs.cache-hit }}
|
||||
SMOKE: ${{ steps.smoke.outputs.ok }}
|
||||
run: |
|
||||
if [ "$HIT" = "true" ] && [ "$SMOKE" = "true" ]; then
|
||||
echo "Prebuilt addons restored and verified; skipping bazel."
|
||||
echo "needed=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "needed=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- id: cache
|
||||
if: steps.decide.outputs.needed == 'true'
|
||||
uses: ./.github/actions/bazel-cache
|
||||
with:
|
||||
scope: linux
|
||||
- name: Build native addons once
|
||||
if: steps.decide.outputs.needed == 'true'
|
||||
env:
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
set -eo pipefail
|
||||
if [ "$(ulimit -Sn)" != unlimited ] && [ "$(ulimit -Sn)" -lt 65536 ]; then ulimit -Sn 65536 || true; fi
|
||||
targets=(//:natives-linux-x64-baseline //:natives-linux-x64-modern)
|
||||
if [ "$EVENT_NAME" != "pull_request" ]; then
|
||||
targets=(//:natives-linux-all)
|
||||
fi
|
||||
bazelisk --bazelrc="${{ steps.cache.outputs.rc }}" build "${targets[@]}"
|
||||
bazelisk --bazelrc="${{ steps.cache.outputs.rc }}" build "${targets[@]}" 2>&1 | tee "$RUNNER_TEMP/bazel-build.log"
|
||||
# Cache-hit visibility: a supposedly warm build that executes
|
||||
# thousands of actions is the failure mode that made CI slow — make
|
||||
# it visible in the run summary instead of discovering it weeks in.
|
||||
- name: Report bazel cache stats
|
||||
if: steps.decide.outputs.needed == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
summary=$(grep -E "INFO: [0-9]+ processes:" "$RUNNER_TEMP/bazel-build.log" | tail -1 || true)
|
||||
echo "::notice title=Bazel build summary::${summary:-no process summary found}"
|
||||
- name: Save Bazel disk cache
|
||||
if: steps.cache.outputs.save-needed == 'true'
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ~/.cache/omp-bazel-disk
|
||||
key: ${{ steps.cache.outputs.cache-key }}
|
||||
# Producer side of the fast path: trusted main builds publish the
|
||||
# x64 pair under the content-addressed key. Smoke-load before save —
|
||||
# an exact-key archive is never overwritten, so bad bytes would
|
||||
# poison every TS-only PR until manual eviction.
|
||||
- name: Stage built addons for cache
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p ~/.cache/omp-native-addons
|
||||
cp bazel-bin/natives-linux-x64-baseline/pi_natives.linux-x64-baseline.node \
|
||||
bazel-bin/natives-linux-x64-modern/pi_natives.linux-x64-modern.node \
|
||||
~/.cache/omp-native-addons/
|
||||
- name: Smoke addons before caching
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd ~/.cache/omp-native-addons
|
||||
cat > "$RUNNER_TEMP/smoke-addons.js" <<'EOF'
|
||||
for (const f of process.argv.slice(2)) {
|
||||
const m = require(f);
|
||||
if (!m || Object.keys(m).length === 0) {
|
||||
console.error(`addon failed to load: ${f}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
EOF
|
||||
bun "$RUNNER_TEMP/smoke-addons.js" \
|
||||
"$PWD/pi_natives.linux-x64-baseline.node" \
|
||||
"$PWD/pi_natives.linux-x64-modern.node"
|
||||
- name: Look up native addon cache
|
||||
id: addon-cache
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ~/.cache/omp-native-addons
|
||||
key: ${{ steps.inputs.outputs.cache-key }}
|
||||
lookup-only: true
|
||||
- name: Save native addon cache
|
||||
if: github.event_name != 'pull_request' && steps.addon-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
||||
with:
|
||||
path: ~/.cache/omp-native-addons
|
||||
key: ${{ steps.inputs.outputs.cache-key }}
|
||||
- name: Upload native addon artifacts
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
@@ -206,8 +328,8 @@ jobs:
|
||||
test_workspace:
|
||||
name: Test TS workspace fast
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -224,8 +346,8 @@ jobs:
|
||||
test_coding_agent_singleton:
|
||||
name: Test coding-agent singleton/global-state (TS)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -242,8 +364,8 @@ jobs:
|
||||
test_ts_native:
|
||||
name: Test TS native/integration packages
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -260,8 +382,8 @@ jobs:
|
||||
test_coding_agent_ui:
|
||||
name: Test coding-agent UI/TUI (TS)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -278,8 +400,8 @@ jobs:
|
||||
test_coding_agent_runtime:
|
||||
name: Test coding-agent runtime/session (TS)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -298,8 +420,8 @@ jobs:
|
||||
test_coding_agent_native:
|
||||
name: Test coding-agent native/unit (TS)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -316,8 +438,8 @@ jobs:
|
||||
test_smoke:
|
||||
name: Test CLI smoke (TS)
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -332,8 +454,8 @@ jobs:
|
||||
install_methods:
|
||||
name: Install method smoke tests
|
||||
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'omp-kata' }}
|
||||
needs: [rust]
|
||||
if: ${{ !cancelled() && needs.rust.result == 'success' }}
|
||||
needs: [native_addons]
|
||||
if: ${{ !cancelled() && needs.native_addons.result == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup-system-deps
|
||||
@@ -349,7 +471,8 @@ jobs:
|
||||
release_binary:
|
||||
name: "Release binary: ${{ matrix.target_id }}"
|
||||
if: ${{ needs.release_metadata.outputs.is-release == 'true' && !cancelled() &&
|
||||
needs.rust.result == 'success' &&
|
||||
needs.rust_validate.result == 'success' &&
|
||||
needs.native_addons.result == 'success' &&
|
||||
needs.test_workspace.result == 'success' &&
|
||||
needs.test_coding_agent_singleton.result == 'success' &&
|
||||
needs.test_ts_native.result == 'success' &&
|
||||
@@ -358,7 +481,7 @@ jobs:
|
||||
needs.test_coding_agent_native.result == 'success' &&
|
||||
needs.test_smoke.result == 'success' && needs.check.result == 'success' &&
|
||||
needs.install_methods.result == 'success' }}
|
||||
needs: [release_metadata, check, rust, test_workspace, test_coding_agent_singleton, test_ts_native, test_coding_agent_ui, test_coding_agent_runtime, test_coding_agent_native, test_smoke, install_methods]
|
||||
needs: [release_metadata, check, rust_validate, native_addons, test_workspace, test_coding_agent_singleton, test_ts_native, test_coding_agent_ui, test_coding_agent_runtime, test_coding_agent_native, test_smoke, install_methods]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -447,7 +570,7 @@ jobs:
|
||||
path: ~/.bun/install/cache
|
||||
key: bun-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
|
||||
- run: bun install --frozen-lockfile
|
||||
# Linux and Windows addons come from the Rust job. Darwin runners
|
||||
# Linux and Windows addons come from the native_addons job. Darwin runners
|
||||
# build only their own architecture because cross-hosted artifacts do
|
||||
# not exist for macOS.
|
||||
- name: Install prebuilt native addon(s)
|
||||
@@ -621,7 +744,7 @@ jobs:
|
||||
key: bun-${{ runner.os }}-${{ hashFiles('**/bun.lock') }}
|
||||
- run: bun install --frozen-lockfile
|
||||
# The prepack executes workspace code which loads the Linux x64
|
||||
# addon, so install the Rust job's artifact before publishing.
|
||||
# addon, so install the native_addons job's artifact before publishing.
|
||||
- name: Install prebuilt native addons
|
||||
uses: ./.github/actions/native-artifacts
|
||||
with:
|
||||
|
||||
Reference in New Issue
Block a user