Skip to content

ci: release safety on main — draft-first promote + per-name asset verification #34

ci: release safety on main — draft-first promote + per-name asset verification

ci: release safety on main — draft-first promote + per-name asset verification #34

Workflow file for this run

name: CI
on:
push:
branches: [main, dev]
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: fmt
run: cargo fmt --all --check
- name: clippy
run: cargo clippy --all-targets -- -D warnings
- name: build
run: cargo build --locked --verbose
# Includes tests/openapi_conformance.rs, the SHAPE gate: it loads the committed openapi.json
# and checks every serde type in src/client.rs against its schema (field set, required vs
# nullable, round trip, endpoint wiring). The spec-drift job below only compares a version
# STRING, so this is the check that fails when a struct drifts from the spec in the same
# commit. Keep `cargo test` in this workflow: it is the only thing running that gate.
- name: test
run: cargo test --locked --verbose
integration:
# BIDIRECTIONAL TESTING (matches how the plugin repos test themselves against busbar): download
# the latest RELEASED busbar, boot it, and drive EVERY busbar-admin command against it, asserting
# real effects. Catches client drift a `cargo build` never would — a renamed field, a changed
# status code, a broken auth header. (busbar core's own dev-gate runs the SAME scripts/
# integration.sh against the freshly-built engine, the reverse direction.)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build busbar-admin
run: cargo build --release --locked
- name: Download the latest released busbar (linux x86_64)
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
gh release download --repo GetBusbar/busbar \
--pattern 'busbar-x86_64-unknown-linux-gnu.tar.gz' --dir /tmp/busbar-dl
tar -xzf /tmp/busbar-dl/busbar-x86_64-unknown-linux-gnu.tar.gz -C /tmp/busbar-dl
chmod +x /tmp/busbar-dl/busbar
/tmp/busbar-dl/busbar --version
- name: Drive every command against the real gateway
run: scripts/integration.sh /tmp/busbar-dl/busbar target/release/busbar-admin
spec-drift:
# The admin client is hand-rolled against openapi.json (committed at the repo root).
# This job answers "is the committed spec CURRENT?" only. Whether src/client.rs still MATCHES
# that spec is a separate question, answered by tests/openapi_conformance.rs in the build job.
# Fail when the latest busbar release ships a NEWER spec version than the one committed,
# so drift is visible instead of silent. Degrades to a warning if the GitHub API is
# unavailable or rate-limited (keeps the check non-flaky).
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: compare committed spec version to the latest busbar release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -u
committed=$(jq -r .info.version openapi.json)
echo "committed spec version: $committed"
resp=$(curl -sS --max-time 30 \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/GetBusbar/busbar/releases/latest) || {
echo "::warning::could not reach the GitHub API to check the latest busbar release; skipping spec-drift check"
exit 0
}
latest=$(echo "$resp" | jq -r '.tag_name // empty' | sed 's/^v//')
if [ -z "$latest" ]; then
echo "::warning::GitHub API returned no usable release tag (rate-limited?); skipping spec-drift check"
echo "$resp" | head -c 500
exit 0
fi
echo "latest busbar release: $latest"
if [ "$committed" != "$latest" ]; then
echo "::error::committed openapi.json is v$committed but the latest busbar release is v$latest — refresh the spec and re-audit src/client.rs"
exit 1
fi
echo "spec is current (v$committed)"