Skip to content

fix(ci): unblock workspace tests + clippy + doc-coverage for v0.6.0 l… #142

fix(ci): unblock workspace tests + clippy + doc-coverage for v0.6.0 l…

fix(ci): unblock workspace tests + clippy + doc-coverage for v0.6.0 l… #142

Workflow file for this run

# .github/workflows/release.yml
#
# On git tag v* — build release binaries for all tier-1 targets and
# upload them to a GitHub Release as tar.gz archives.
#
# File naming convention: cobrust-v{version}-{target_triple}-{cpu_level}.tar.gz
# Binary inside archive: cobrust (or cobrust.exe on Windows)
#
# ADR-0046 tier-1 platform contract (must build, must appear in release notes):
# - aarch64-apple-darwin macOS arm64 (Apple Silicon)
# - aarch64-unknown-linux-gnu Linux arm64 (cross-compiled via `cross`)
# - x86_64-unknown-linux-gnu Linux x86_64 (glibc dynamic)
# - x86_64-unknown-linux-musl Linux x86_64 STATIC (musl libc, no glibc)
# Promoted: Phase K Strand #5 (2026-05-19, ADR-0046 §Amendment)
# Runs on Alpine, distroless, minimal containers
#
# ADR-0065 Tier 3 CPU-level matrix (Phase O wave-1): 9 wheel variants per tag
# x86_64-unknown-linux-gnu: v1 (baseline) | v3 (haswell / AVX2+FMA) | v4 (skylake-avx512)
# x86_64-unknown-linux-musl: v1 (static baseline) | v3 (static AVX2)
# aarch64-unknown-linux-gnu: neon (all ARMv8-A) | sve (Graviton3 / Altra, experimental)
# aarch64-apple-darwin: m1 (Apple M1/M2 base) | m2 (Apple M2 Pro+ / M3+)
#
# Tier-2 (best-effort, may fail without blocking release): (none currently)
# Queued (documented as cargo install --git path, not built):
# - x86_64-apple-darwin macOS x86_64 Intel
# - x86_64-pc-windows-msvc Windows x86_64 MSVC — DEFERRED to ADR-0058b followup
# (Gate 8 audit ae2316f1c51dbd6be: musl > MSVC priority)
name: Release
on:
push:
tags:
- "v*"
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
jobs:
# -------------------------------------------------------------------------
# Build tier-1 targets — ADR-0065 Tier 3 CPU-level matrix (Phase O wave-1)
# 9 wheel variants: each matrix entry has cpu_level + rustflags_extra.
# asset_suffix drives the archive name per ADR-0065 §3.2 naming convention.
# -------------------------------------------------------------------------
build-tier1:
name: Build ${{ matrix.target }} [${{ matrix.cpu_level }}]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
include:
# ---- x86_64-unknown-linux-gnu: v1 / v3 / v4 ----------------------
# v1: baseline, runs on all x86-64 hardware (ADR-0046 existing triple)
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
use_cross: false
install_musl_tools: false
cpu_level: v1
rustflags_extra: "-C target-cpu=x86-64"
asset_suffix: x86_64-unknown-linux-gnu-v1
# v3: Haswell+; AVX2 + FMA (ADR-0065 §3.1)
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
use_cross: false
install_musl_tools: false
cpu_level: v3
rustflags_extra: "-C target-cpu=haswell"
asset_suffix: x86_64-unknown-linux-gnu-v3
# v4: Skylake-AVX512; data-centre / HPC (ADR-0065 §3.1)
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
use_cross: false
install_musl_tools: false
cpu_level: v4
rustflags_extra: "-C target-cpu=skylake-avx512"
asset_suffix: x86_64-unknown-linux-gnu-v4
# ---- x86_64-unknown-linux-musl: v1 / v3 --------------------------
# v1: static baseline, Alpine / distroless / minimal containers
# ADR-0046 §Amendment: promoted to tier-1 Phase K Strand #5 (2026-05-19)
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
use_cross: false
install_musl_tools: true
cpu_level: v1
rustflags_extra: "-C target-cpu=x86-64"
asset_suffix: x86_64-unknown-linux-musl-v1
# v3: static AVX2 musl (ADR-0065 §3.1)
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
use_cross: false
install_musl_tools: true
cpu_level: v3
rustflags_extra: "-C target-cpu=haswell"
asset_suffix: x86_64-unknown-linux-musl-v3
# ---- aarch64-unknown-linux-gnu: neon / sve ------------------------
# neon: mandatory ARMv8-A NEON; all AArch64 Linux (cross-compiled)
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
use_cross: true
install_musl_tools: false
cpu_level: neon
rustflags_extra: ""
asset_suffix: aarch64-unknown-linux-gnu-neon
# sve: Neoverse-V1 (Graviton3 / Ampere Altra); experimental per ADR-0065 §6.5
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
use_cross: true
install_musl_tools: false
cpu_level: sve
rustflags_extra: "-C target-cpu=neoverse-v1"
asset_suffix: aarch64-unknown-linux-gnu-sve
# ---- aarch64-apple-darwin: m1 / m2 --------------------------------
# m1: Apple M1 / M2 base (ADR-0065 §3.1)
- target: aarch64-apple-darwin
os: macos-latest
use_cross: false
install_musl_tools: false
cpu_level: m1
rustflags_extra: "-C target-cpu=apple-m1"
asset_suffix: aarch64-apple-darwin-m1
# m2: Apple M2 Pro+ / M3+ (ADR-0065 §3.1)
- target: aarch64-apple-darwin
os: macos-latest
use_cross: false
install_musl_tools: false
cpu_level: m2
rustflags_extra: "-C target-cpu=apple-m2"
asset_suffix: aarch64-apple-darwin-m2
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: dtolnay/rust-toolchain@stable # stable 2025-01
with:
toolchain: 1.94.1
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2 # v2.7.8
with:
key: ${{ matrix.target }}-${{ matrix.cpu_level }}
- name: Install musl-tools (Linux musl static build)
if: matrix.install_musl_tools
run: sudo apt-get update -qq && sudo apt-get install -y musl-tools
- name: Install cross (Linux arm64)
if: matrix.use_cross
run: cargo install cross --git https://github.com/cross-rs/cross
- name: Build release binary (cross)
if: matrix.use_cross
env:
# CARGO_TARGET_*_RUSTFLAGS only applies to target compilation,
# NOT to build scripts (which run on the host CPU). This prevents
# SIGILL when build.rs is compiled with AVX-512 flags on runners
# that lack AVX-512 support (e.g. ubuntu-latest for v4 wheel).
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS: "-D warnings ${{ matrix.rustflags_extra }}"
run: |
# ADR-0068 v0.6.0: cobrust-lsp + cobrust-dap are now lib-only
# crates; the standalone binaries come from -shim crates.
# ADR-0069 v0.6.0: same release.yml builds the prebuilt
# libcobrust_stdlib.a (via cobrust-cli build.rs invoking
# cobrust-stdlib's staticlib target).
cross build --release --locked -p cobrust-cli -p cobrust-lsp-shim -p cobrust-dap-shim --target ${{ matrix.target }}
- name: Build release binary (native)
if: ${{ !matrix.use_cross }}
env:
# CARGO_TARGET_*_RUSTFLAGS only applies to target compilation,
# NOT to build scripts (which run on the host CPU). This prevents
# SIGILL when build.rs is compiled with AVX-512 flags on runners
# that lack AVX-512 support (e.g. ubuntu-latest for v4 wheel).
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS: "-D warnings ${{ matrix.rustflags_extra }}"
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-D warnings ${{ matrix.rustflags_extra }}"
CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS: "-D warnings ${{ matrix.rustflags_extra }}"
run: |
# ADR-0068 v0.6.0: see cross build above for rationale.
cargo build --release --locked -p cobrust-cli -p cobrust-lsp-shim -p cobrust-dap-shim --target ${{ matrix.target }}
- name: Package tar.gz (ADR-0069 FHS layout)
shell: bash
run: |
set -euo pipefail
VERSION="${GITHUB_REF_NAME#v}"
# ADR-0065 §3.2 naming: cobrust-<version>-<triple>-<cpu_level>.tar.gz
ARCHIVE="cobrust-v${VERSION}-${{ matrix.asset_suffix }}.tar.gz"
RELEASE_DIR="target/${{ matrix.target }}/release"
# ADR-0069 §4.1 wheel-layout: bin/, lib/cobrust/, share/cobrust/runtime/
STAGE="cobrust-v${VERSION}"
rm -rf "$STAGE"
mkdir -p "$STAGE/bin" "$STAGE/lib/cobrust" "$STAGE/share/cobrust/runtime"
cp "${RELEASE_DIR}/cobrust" "$STAGE/bin/cobrust"
cp "${RELEASE_DIR}/cobrust-lsp" "$STAGE/bin/cobrust-lsp"
cp "${RELEASE_DIR}/cobrust-dap" "$STAGE/bin/cobrust-dap"
# libcobrust_stdlib.a is built by cobrust-cli's build.rs invoking
# the cobrust-stdlib staticlib target — locate it via the OUT_DIR
# bake artifact under target/<triple>/release/build/cobrust-cli-*/out/
STDLIB_ARCHIVE=$(find "target/${{ matrix.target }}/release/build" -path "*/cobrust-cli-*/out/cobrust-stdlib-build/release/libcobrust_stdlib.a" -print -quit)
if [[ -z "${STDLIB_ARCHIVE}" || ! -f "${STDLIB_ARCHIVE}" ]]; then
echo "::error::cannot locate libcobrust_stdlib.a built by cobrust-cli build.rs"
find "target/${{ matrix.target }}/release/build" -name "libcobrust_stdlib.a" -print 2>/dev/null || true
exit 1
fi
cp "${STDLIB_ARCHIVE}" "$STAGE/lib/cobrust/libcobrust_stdlib.a"
cp crates/cobrust-cli/runtime/cobrust_main.c "$STAGE/share/cobrust/runtime/"
cp crates/cobrust-cli/runtime/cpu_features.c "$STAGE/share/cobrust/runtime/"
# Tar the single top-level directory (ADR-0069 §4.1 self-contained tree).
tar czf "${ARCHIVE}" "$STAGE"
echo "ARCHIVE=${ARCHIVE}" >> "$GITHUB_ENV"
echo "STAGE_DIR=${STAGE}" >> "$GITHUB_ENV"
echo "Packaged tree:"
(cd "$STAGE" && find . -maxdepth 4 | sort)
# ADR-0069 §4.3 + F46 §3 — post-package smoke gate. Extract the
# tarball at the same path users would (relative to a clean dir),
# write a one-line .cb source, run `cobrust run` on it, assert
# stdout matches "smoke". Failure fails the job BEFORE artifact
# upload, so broken wheels never reach the GH Release.
#
# Native-only: cross-compiled tarballs cannot execute their own
# binary on the build host. Cross-compile correctness is verified
# post-publish by user-side install tests.
- name: Post-package smoke gate (ADR-0069 §4.3 + F46 §3)
if: ${{ !matrix.use_cross }}
shell: bash
run: |
set -euo pipefail
SMOKE_DIR="$(mktemp -d)"
cp "${ARCHIVE}" "${SMOKE_DIR}/"
cd "${SMOKE_DIR}"
tar xzf "${ARCHIVE}"
ls -R "${STAGE_DIR}"
cat > t.cb <<'EOF_CB'
fn main() -> i64:
print("smoke")
return 0
EOF_CB
"${STAGE_DIR}/bin/cobrust" run t.cb 2>&1 | tee out.txt
if ! grep -q "^smoke$" out.txt; then
echo "::error::post-package smoke gate FAILED: 'smoke' not in stdout"
echo "stdout was:"
cat out.txt
exit 1
fi
echo "post-package smoke gate PASS"
- name: Upload artifact
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: cobrust-${{ matrix.asset_suffix }}
path: ${{ env.ARCHIVE }}
retention-days: 1
# -------------------------------------------------------------------------
# Build best-effort targets (non-blocking)
# NOTE: x86_64-pc-windows-msvc removed from this matrix in Phase K Strand #5.
# Windows MSVC is now classified as "queued" pending ADR-0058b (stable runner
# + test-suite parity + packaging convention decision).
#
# Job intentionally OMITTED: GitHub Actions rejects `matrix.include: []` with
# "matrix must define at least one vector" at workflow-validation time —
# this fires BEFORE `if: false` job-skip evaluation, so a no-op skeleton
# cannot be retained. Re-add the entire `build-best-effort:` job (with at
# least one matrix entry) when the next tier-2 target lands.
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# Create GitHub Release and upload all artifacts
# -------------------------------------------------------------------------
release:
name: Publish GitHub Release
runs-on: ubuntu-latest
needs: [build-tier1]
# Run after best-effort too when available; but don't gate on it.
permissions:
contents: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Download all artifacts
uses: actions/download-artifact@v4 # v4.1.8
with:
path: dist/
merge-multiple: true
- name: List artifacts
run: ls -lh dist/
# W4 (ADR-0065 §7.4): generate SHA256SUMS file for all wheel archives so
# the registry-gen index builder can populate WheelEntry.sha256.
# `sha256sum` output format: "<hex> <filename>" (two spaces, GNU coreutils).
- name: Generate SHA256SUMS
run: |
cd dist/
sha256sum cobrust-v*.tar.gz > SHA256SUMS
echo "SHA256SUMS contents:"
cat SHA256SUMS
- name: Create GitHub Release
uses: softprops/action-gh-release@v2 # v2.2.1
with:
tag_name: ${{ github.ref_name }}
name: "Cobrust ${{ github.ref_name }}"
body: |
## Installation
v0.6.0 adopts the FHS-ish `bin/lib/share` wheel layout per
ADR-0069. Tarballs extract to a single self-contained
`cobrust-${{ github.ref_name }}/` directory.
### Option A — cargo install (requires Rust toolchain)
```bash
cargo install --git https://github.com/Cobrust-lang/cobrust cobrust-cli
```
### Option B — prebuilt wheel (no Rust needed; v0.6.0 layout)
Pick the tarball for your platform + CPU level, extract to a
stable location, and symlink the `cobrust` binary into your
`$PATH`. The runtime + stdlib live in `lib/` + `share/`
siblings; do NOT move the binary out of its `bin/` directory.
```bash
# macOS Apple Silicon M1 (tier-1)
curl -L https://github.com/Cobrust-lang/cobrust/releases/download/${{ github.ref_name }}/cobrust-${{ github.ref_name }}-aarch64-apple-darwin-m1.tar.gz | tar xz -C $HOME/.local/
ln -sf $HOME/.local/cobrust-${{ github.ref_name }}/bin/cobrust $HOME/.local/bin/cobrust
# Linux x86_64 — glibc baseline (tier-1)
curl -L https://github.com/Cobrust-lang/cobrust/releases/download/${{ github.ref_name }}/cobrust-${{ github.ref_name }}-x86_64-unknown-linux-gnu-v1.tar.gz | tar xz -C $HOME/.local/
ln -sf $HOME/.local/cobrust-${{ github.ref_name }}/bin/cobrust $HOME/.local/bin/cobrust
# Linux x86_64 — static musl (Alpine / distroless / minimal containers)
curl -L https://github.com/Cobrust-lang/cobrust/releases/download/${{ github.ref_name }}/cobrust-${{ github.ref_name }}-x86_64-unknown-linux-musl-v1.tar.gz | tar xz -C $HOME/.local/
ln -sf $HOME/.local/cobrust-${{ github.ref_name }}/bin/cobrust $HOME/.local/bin/cobrust
```
Each wheel tarball bundles:
- `bin/cobrust` — main driver (also exposes `cobrust lsp` + `cobrust dap` subcommands per ADR-0068)
- `bin/cobrust-lsp` + `bin/cobrust-dap` — transitional shim binaries (deleted at v0.7.0; extension v0.1.x compat)
- `lib/cobrust/libcobrust_stdlib.a` — prebuilt static stdlib archive
- `share/cobrust/runtime/{cobrust_main.c,cpu_features.c}` — runtime C entrypoint + CPU feature helpers
### Option C — Alpine / distroless container (musl static binary)
```dockerfile
FROM alpine:latest
RUN apk add --no-cache curl tar
RUN curl -L https://github.com/Cobrust-lang/cobrust/releases/download/${{ github.ref_name }}/cobrust-${{ github.ref_name }}-x86_64-unknown-linux-musl-v1.tar.gz | tar xz -C /opt/ \
&& ln -s /opt/cobrust-${{ github.ref_name }}/bin/cobrust /usr/local/bin/cobrust
```
### Quick start
```bash
cobrust new hello && cd hello && cobrust run src/main.cb
# → hello, world
```
See [Getting Started](https://github.com/Cobrust-lang/cobrust/blob/main/docs/human/en/getting-started.md) for the full guide.
### Breaking change from v0.5.x
Users who manually `cp cobrust /usr/local/bin/` from a flat
v0.5.x tarball MUST re-install via the new `tar xz` →
`ln -s` flow above. Per F46: the v0.5.x flat-binary wheel
was unusable for `cobrust run` regardless because the
runtime + stdlib were not bundled (binary baked the GH
Actions runner workspace path). v0.6.0 fixes both sides.
files: |
dist/*.tar.gz
dist/SHA256SUMS
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}