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 cargo_flags: "" 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" - target: aarch64-apple-darwin os: macos-latest archive: tar.gz cargo_flags: "" steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ 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 }} - 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 run: | pnpm install --frozen-lockfile pnpm --filter @vestige/dashboard check pnpm --filter @vestige/dashboard test pnpm --filter @vestige/dashboard build if [ -n "$(git status --porcelain -- apps/dashboard/build)" ]; then git status --short -- apps/dashboard/build exit 1 fi - 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 }}