vestige/.github/workflows/release.yml
Sam Valladares f08f1f9fe0 fix(ci): add the cross-compile target to the pinned toolchain
The rust-toolchain.toml pin added in the previous commit broke the Intel Mac
release build: dtolnay/rust-toolchain@stable installs the target for stable,
but cargo then runs the pinned 1.97.1, which has no x86_64-apple-darwin std,
so the build failed with 'can't find crate for core'.

Add an explicit 'rustup target add' step after the toolchain install in both
ci.yml and release.yml. It runs in the repo, so it targets the pinned
toolchain. release.yml needed it too: without this the real release build
would have failed at tag time on Windows and Intel Mac.

Verified locally: reproduced the missing target on the pinned toolchain,
applied the fix, then cargo check -p vestige-mcp --target x86_64-apple-darwin
with the full Intel Mac release feature set exits 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-26 01:09:25 +08:00

190 lines
7.2 KiB
YAML

name: Release
on:
release:
types: [created]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to build (e.g., v2.0.0)'
required: true
permissions:
contents: write
env:
CARGO_TERM_COLOR: always
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
archive: tar.gz
cargo_flags: ""
needs_onnxruntime: false
- target: x86_64-pc-windows-msvc
os: windows-latest
archive: zip
# vector-search (usearch HNSW index) is REQUIRED. Without it the
# storage layer's #[cfg(feature = "vector-search")] paths compile
# out, so embeddings are never persisted or queried: the binary
# reports "Embedding Service: Not Ready", 0% coverage, consolidate
# generates 0 embeddings, and no model download is ever attempted.
# usearch builds cleanly on MSVC because vestige-core pins it with
# features=["fp16lib"] (see crates/vestige-core/Cargo.toml).
cargo_flags: "--no-default-features --features embeddings,ort-download,vector-search,cloud-sync,connectors"
needs_onnxruntime: false
# Intel Mac uses the ort-dynamic feature to runtime-link against a
# system libonnxruntime (Homebrew), sidestepping the missing
# x86_64-apple-darwin prebuilts in ort-sys 2.0.0-rc.11. Binary
# consumers must `brew install onnxruntime` before running — see
# INSTALL-INTEL-MAC.md bundled in the tarball.
- target: x86_64-apple-darwin
os: macos-latest
archive: tar.gz
cargo_flags: "--no-default-features --features ort-dynamic,vector-search,cloud-sync,connectors"
- target: aarch64-apple-darwin
os: macos-latest
archive: tar.gz
cargo_flags: ""
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && github.sha || github.event.inputs.tag || github.ref }}
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
# rust-toolchain.toml pins the toolchain, so cargo runs the pinned version
# rather than the stable one the action installed. Add the cross-compile
# target to the pinned toolchain too, or the build fails with
# "can't find crate for `core`".
- name: Add target to the pinned toolchain
run: rustup target add ${{ matrix.target }}
- name: Validate release version
shell: bash
env:
RELEASE_TAG: ${{ github.event.inputs.tag || github.ref_name }}
run: |
node <<'NODE'
const { execFileSync } = require('node:child_process');
const tag = process.env.RELEASE_TAG || '';
const expected = tag.replace(/^refs\/tags\//, '').replace(/^v/, '');
if (!expected) {
throw new Error('Release tag is empty');
}
const packageFiles = [
'package.json',
'apps/dashboard/package.json',
'packages/vestige-init/package.json',
'packages/vestige-mcp-npm/package.json'
];
for (const file of packageFiles) {
const actual = require(`./${file}`).version;
if (actual !== expected) {
throw new Error(`${file} version ${actual} does not match ${tag}`);
}
}
const metadata = JSON.parse(execFileSync('cargo', [
'metadata',
'--format-version',
'1',
'--locked',
'--no-deps'
], { encoding: 'utf8' }));
for (const name of ['vestige-core', 'vestige-mcp']) {
const pkg = metadata.packages.find((candidate) => candidate.name === name);
if (!pkg) throw new Error(`Missing Cargo package ${name}`);
if (pkg.version !== expected) {
throw new Error(`${name} version ${pkg.version} does not match ${tag}`);
}
}
NODE
- name: Build embedded dashboard
shell: bash
env:
RELEASE_TAG: ${{ github.event.inputs.tag || github.ref_name }}
run: |
pnpm install --frozen-lockfile
pnpm --filter @vestige/dashboard check
pnpm --filter @vestige/dashboard test
pnpm --filter @vestige/dashboard build
node <<'NODE'
const fs = require('node:fs');
const tag = process.env.RELEASE_TAG || '';
const expected = tag.replace(/^refs\/tags\//, '').replace(/^v/, '');
const versionFile = 'apps/dashboard/build/_app/version.json';
const version = JSON.parse(fs.readFileSync(versionFile, 'utf8')).version;
if (version !== expected) {
throw new Error(`${versionFile} version ${version} does not match ${tag}`);
}
for (const file of ['apps/dashboard/build/index.html', versionFile]) {
if (!fs.existsSync(file)) {
throw new Error(`Dashboard build did not produce ${file}`);
}
}
NODE
- name: Build
run: cargo build --locked --package vestige-mcp --release --target ${{ matrix.target }} ${{ matrix.cargo_flags }}
- name: Package (Unix)
if: matrix.os != 'windows-latest'
run: |
cp docs/INSTALL-INTEL-MAC.md target/${{ matrix.target }}/release/ 2>/dev/null || true
cd target/${{ matrix.target }}/release
if [ "${{ matrix.target }}" = "x86_64-apple-darwin" ]; then
tar -czf ../../../vestige-mcp-${{ matrix.target }}.tar.gz vestige-mcp vestige vestige-restore INSTALL-INTEL-MAC.md
else
tar -czf ../../../vestige-mcp-${{ matrix.target }}.tar.gz vestige-mcp vestige vestige-restore
fi
- name: Package (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
cd target/${{ matrix.target }}/release
Compress-Archive -Path vestige-mcp.exe,vestige.exe,vestige-restore.exe -DestinationPath ../../../vestige-mcp-${{ matrix.target }}.zip
- name: Generate checksum
shell: bash
run: |
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 vestige-mcp-${{ matrix.target }}.${{ matrix.archive }} > vestige-mcp-${{ matrix.target }}.${{ matrix.archive }}.sha256
else
sha256sum vestige-mcp-${{ matrix.target }}.${{ matrix.archive }} > vestige-mcp-${{ matrix.target }}.${{ matrix.archive }}.sha256
fi
- name: Upload to Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
files: |
vestige-mcp-${{ matrix.target }}.${{ matrix.archive }}
vestige-mcp-${{ matrix.target }}.${{ matrix.archive }}.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}