Skip to content

release: v0.0.5 — resilient install: pre-build the MCP binary #5

release: v0.0.5 — resilient install: pre-build the MCP binary

release: v0.0.5 — resilient install: pre-build the MCP binary #5

Workflow file for this run

name: Release binaries
# Triggered when the maintainer pushes a tag matching v*. Builds the
# ai-architect-mcp binary for three platforms Cortex's installer
# fast-path knows how to consume (macos-aarch64, linux-x86_64,
# linux-aarch64), tarballs each, computes a SHA256 companion, and
# attaches everything to the GitHub Release.
#
# macos-x86_64 is intentionally omitted — Apple-silicon dominance
# in 2026 + macos-13 runner deprecation makes the cost/value ratio
# poor. Add back when GitHub provides a native x86_64 runner that
# isn't end-of-lifed, or cross-compile from macos-latest.
#
# Asset naming convention (Cortex installer contract):
# ai-architect-mcp-{os}-{arch}.tar.gz
# ai-architect-mcp-{os}-{arch}.tar.gz.sha256
# where {os} ∈ {macos, linux}, {arch} ∈ {x86_64, aarch64}.
# The tar archive root must contain ``ai-architect-mcp`` (no nested dir).
on:
push:
tags:
- "v*"
permissions:
contents: write # required to upload release assets
jobs:
# Pre-create the release exactly once before the matrix fans out.
# Without this, every matrix job races to "create or upload"; the
# second writer hits HTTP 422 ``already_exists`` finalizing, *and*
# GitHub silently produces a second untagged-draft release that
# collects whichever assets the failing job uploaded — they never
# appear on the published release. Observed on v0.0.4: macOS assets
# landed on a draft while linux assets landed on the published
# release, leaving Cortex's installer with no darwin asset.
create_release:
name: create release (${{ github.ref_name }})
runs-on: ubuntu-latest
steps:
- uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
generate_release_notes: true
build:
name: build (${{ matrix.target_tag }})
needs: create_release
strategy:
fail-fast: false
matrix:
include:
- target_tag: macos-aarch64
rust_target: aarch64-apple-darwin
runner: macos-latest
- target_tag: linux-x86_64
rust_target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
- target_tag: linux-aarch64
rust_target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm # native ARM runner — no cross
runs-on: ${{ matrix.runner }}
# zstd-sys + lbug both statically link libzstd, producing duplicate
# symbols on Linux (rust-lld is strict; macOS ld64 silently dedupes).
# ZSTD_SYS_USE_PKG_CONFIG=1 makes zstd-sys link the system libzstd
# dynamically, eliminating the conflict. Harmless on macOS where
# zstd-sys ignores it (no pkg-config installed by default).
env:
ZSTD_SYS_USE_PKG_CONFIG: "1"
steps:
- uses: actions/checkout@v4
- name: Install Linux build deps
if: startsWith(matrix.runner, 'ubuntu')
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends \
libzstd-dev pkg-config cmake
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rust_target }}
- name: Cache cargo registry + target
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ matrix.target_tag }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ matrix.target_tag }}-cargo-
- name: Build
run: cargo build --release --bin ai-architect-mcp --target ${{ matrix.rust_target }}
- name: Strip binary (best-effort)
run: |
BIN=target/${{ matrix.rust_target }}/release/ai-architect-mcp
# GNU strip on Linux, llvm-strip on macOS — both ignore unknown.
strip "$BIN" 2>/dev/null || true
ls -la "$BIN"
- name: Package tarball + sha256
run: |
ASSET="ai-architect-mcp-${{ matrix.target_tag }}.tar.gz"
BIN=target/${{ matrix.rust_target }}/release/ai-architect-mcp
STAGING=$(mktemp -d)
cp "$BIN" "$STAGING/ai-architect-mcp"
tar -C "$STAGING" -czf "$ASSET" ai-architect-mcp
# shasum is present on every macOS + Linux GitHub runner.
shasum -a 256 "$ASSET" | tee "$ASSET.sha256"
ls -la "$ASSET" "$ASSET.sha256"
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
# Release was pre-created by the create_release job; we only
# upload here. tag_name pins the upload to that release so
# softprops never tries to create a sibling draft.
tag_name: ${{ github.ref_name }}
files: |
ai-architect-mcp-${{ matrix.target_tag }}.tar.gz
ai-architect-mcp-${{ matrix.target_tag }}.tar.gz.sha256
fail_on_unmatched_files: true