Skip to content

release: v0.3.1 - #49

Merged
brettdavies merged 3 commits into
mainfrom
release/v0.3.1
May 4, 2026
Merged

release: v0.3.1#49
brettdavies merged 3 commits into
mainfrom
release/v0.3.1

Conversation

@brettdavies

@brettdavies brettdavies commented May 4, 2026

Copy link
Copy Markdown
Owner

Summary

Releases v0.3.1, an artifact-set release: ships x86_64-unknown-linux-musl and aarch64-unknown-linux-musl static
binaries on every release. No source change versus v0.3.0: the binary is identical; only the artifact set is wider.

Consolidates one dev commit:

Triple-diff verification before opening: A is exactly the 6 expected ship-surface files; B contains only release-prep
files (Cargo.toml, Cargo.lock, CHANGELOG.md) plus the always-divergent completions/; no guarded engineering-doc paths
leaked.

Changelog

Added

  • Ship x86_64- and aarch64-unknown-linux-musl static binaries on every release. Statically linked against musl libc,
    so they run on Alpine and other musl-libc-host distros without glibc, and on every glibc distro too.

Documentation

  • Document the cliff.toml chore-skip footgun and the "CHANGELOG is generated, never hand-written" rule in
    RELEASES.md under Releasing dev to main.
  • Update the release-pipeline target table from 5 → 7 targets, naming the two musl rows and the two opt-in inputs
    (linux_musl_required, linux_musl_verify_alpine).

Type of Change

  • feat: New feature (non-breaking change which adds functionality)

Related Issues/Stories

Testing

  • Manual testing completed
  • All tests passing

Test Summary:

End-to-end musl validation completed pre-merge in the throwaway spike/musl-build workflow:

  • cross build --release --locked --target x86_64-unknown-linux-musl: green, statically linked
  • cross build --release --locked --target aarch64-unknown-linux-musl: green, statically linked
  • file target/.../release/anc matched statically linked for both arches
  • x86_64 host smoke test (anc --version): anc 0.3.0
  • Belt-and-suspenders: docker run --rm --pull always -v ".../release:/musl-bin:ro" alpine:latest /musl-bin/anc --version: anc 0.3.0

The release pipeline (now 7 targets) re-runs all of the above on the v0.3.1 tag push, so the binaries shipped to the
GitHub Release will be the freshly-built ones, not the spike's.

Files Modified

Modified:

  • .github/workflows/release.yml: passes the two new shared-workflow inputs.
  • Cargo.toml: version 0.3.0 → 0.3.1.
  • Cargo.lock: cargo update -p agentnative regen.
  • CHANGELOG.md: scripts/generate-changelog.sh extracted feat(release): opt into linux-musl artifacts via shared workflow #48's ## Changelog section into a v0.3.1 entry.
    Cross-checked: cliff.toml chore-skip didn't drop anything (commit subject was feat, not chore).
  • RELEASES.md: release-pipeline table 5 → 7 targets + bundled cliff.toml/never-hand-written documentation.
  • src/skill_install/skill.json: fixture refresh from upstream agentnative-site dev (caught by drift-check on feat(release): opt into linux-musl artifacts via shared workflow #48;
    brought along here).

Created:

  • None.

Renamed:

  • None.

Deleted:

  • None.

Breaking Changes

  • No breaking changes

The binary surface is unchanged. New consumers on Alpine gain an install path; existing consumers see no difference.

Deployment Notes

After this PR squash-merges to main:

git checkout main && git pull
git tag -a -m "Release v0.3.1" v0.3.1
git push origin main --tags

The tag push triggers the now-7-target release pipeline. After the GitHub Release reaches published (homebrew dispatch
and finalize-release flip), backport per the new convention:

./scripts/sync-dev-after-release.sh v0.3.1
git push origin dev

The throwaway spike/musl-build branch (local + remote) can be pruned any time after this PR opens; it served its
purpose.

Checklist

## Summary

Opts agentnative-cli into the two new shared-workflow inputs that landed
in `brettdavies/.github` PR #18, so future
releases ship Alpine/musl artifacts. No source changes; the binary is
identical to v0.3.0.

After this PR merges (and ships via a `release/v0.3.1` cherry-pick to
`main`), every release will produce 7 archives
instead of 5 — adding `agentnative-x86_64-unknown-linux-musl.tar.gz` and
`agentnative-aarch64-unknown-linux-musl.tar.gz`. Alpine and other
musl-libc-host distros gain a first-class install path
beyond `cargo install` and the existing glibc Linux artifact.

Bundled: a small `RELEASES.md` polish that was already dirty in the
working tree (cliff.toml chore-skip warning + "never
hand-written" rule under `Releasing dev to main`), plus the necessary 5
→ 7 target table update.

## Changelog

### Added

- Ship `x86_64-` and `aarch64-unknown-linux-musl` static binaries on
every release. Statically linked against musl libc,
so they run on Alpine and other musl-libc-host distros without glibc,
and on every glibc distro too.

### Documentation

- Document the `cliff.toml` chore-skip footgun and the "CHANGELOG is
generated, never hand-written" rule in
`RELEASES.md` under `Releasing dev to main`. Adds a new review step
(renumbered to 9) and tightens the existing "PRs
  and changelog generation" section.

## Type of Change

- [x] `feat`: New feature (non-breaking change which adds functionality)

## Related Issues/Stories

- Story: n/a
- Issue: n/a
- Architecture: n/a
- Related PRs: brettdavies/.github#17 (shared workflow musl rows +
soft-fail input), brettdavies/.github#18 (release of
#17 to main). agentnative-cli `spike/musl-build` (throwaway) was the
validation surface.

## Testing

- [x] Manual testing completed
- [x] All tests passing

**Test Summary:**

- Unit tests: n/a (workflow opt-in only; no Rust source change)
- Integration tests: n/a
- Coverage: n/a

End-to-end validation completed in the throwaway `spike/musl-build`
workflow before either upstream or this PR opened:

- `cross build --release --locked --target x86_64-unknown-linux-musl` —
green, ~1m45s, statically linked
- `cross build --release --locked --target aarch64-unknown-linux-musl` —
green, ~1m45s, statically linked
- `file target/.../release/anc` matched `statically linked` for both
arches
- x86_64 host smoke test (`anc --version`) — `anc 0.3.0`
- Belt-and-suspenders: `docker run --rm --pull always -v
$PWD/target/.../release:/musl-bin:ro alpine:latest
/musl-bin/anc --version` — `anc 0.3.0`. Confirms exec compatibility with
musl-libc host (Alpine), not just static
  linkage.

`actionlint` clean on the modified `release.yml`. The pre-push hook
(`scripts/hooks/pre-push`: fmt, clippy `-Dwarnings`,
test, cargo-deny, Windows compat) passed.

## Files Modified

**Modified:**

- `.github/workflows/release.yml` — passes `linux_musl_required: true`
and `linux_musl_verify_alpine: true` to the
  shared `rust-release.yml` workflow.
- `RELEASES.md` — updates the release-pipeline table from 5 → 7 targets
(naming the two musl rows and the two opt-in
inputs), and bundles a separate cliff.toml chore-skip + "never
hand-written" docs improvement that was already dirty
  in the working tree.

**Created:**

- None.

**Renamed:**

- None.

**Deleted:**

- None.

## Key Features

- Alpine support: musl-static binaries run on Alpine without glibc, and
on every glibc distro too.
- Belt-and-suspenders Alpine exec verification in CI catches
dynamic-link surprises (`dlopen`, NSS, locale) that pass
  the static-link `file` assertion.
- Hard-fail behavior (`linux_musl_required: true`) means a musl
regression blocks the release, not a silent artifact
  omission.

## Benefits

- Closes the install gap for Alpine users — the existing Homebrew bottle
is glibc-linux only, and `cargo install`
  requires the full Rust toolchain. Now: `wget` + `tar xf` + run.
- Distroless / `scratch` containers gain a usable artifact too.
- The Alpine exec check turns a class of "ship now, find out later in a
user bug report" failures into "fail at CI
  time."

## Breaking Changes

- [x] No breaking changes

## Deployment Notes

- [x] Standard release flow per `RELEASES.md`

After this PR squash-merges to `dev`, ship via the standard cherry-pick:

1. Branch `release/v0.3.1` from `origin/main`.
2. Cherry-pick this commit; bump `Cargo.toml` 0.3.0 → 0.3.1; `cargo
update -p agentnative`.
3. Run `./scripts/generate-completions.sh`, `bash
scripts/sync-skill-fixture.sh`, `./scripts/generate-changelog.sh`.
Cross-check the generated CHANGELOG section against this PR's `##
Changelog` bullets per the cliff.toml chore-skip
   warning.
4. Triple-diff verify, push, open `release: v0.3.1` PR.
5. After merge, annotated tag and push triggers the release pipeline
(now with musl).
6. After the release publishes, run `./scripts/sync-dev-after-release.sh
v0.3.1 && git push origin dev` per the new
   convention.

The throwaway `spike/musl-build` branch in this repo can be pruned
(locally + remotely) any time after this PR opens; it
served its purpose and was never merged anywhere.

## Checklist

- [x] Code follows project conventions and style guidelines
- [x] Commit messages follow Conventional Commits
- [x] Self-review of code completed
- [x] Tests added/updated and passing (validated via spike workflow
before upstream PR opened)
- [x] No new warnings or errors introduced (`actionlint` clean; pre-push
hook clean)
- [x] Changes are backward compatible
@brettdavies
brettdavies merged commit 40273e0 into main May 4, 2026
10 checks passed
@brettdavies
brettdavies deleted the release/v0.3.1 branch May 4, 2026 18:37
brettdavies added a commit to brettdavies/.github that referenced this pull request May 4, 2026
## Summary

Fixes a silent matrix-expansion failure introduced in #17/#18 that bit
agentnative-cli's first attempt at v0.3.1
(release run
[25336702699](https://github.com/brettdavies/agentnative-cli/actions/runs/25336702699)).

The build job's `continue-on-error: ${{ matrix.soft_fail &&
!inputs.linux_musl_required }}` evaluated to `null` for
non-musl matrix rows when the caller passed `linux_musl_required: true`
— `matrix.soft_fail` was undefined for those
rows, `null && false` returns `null`, and GHA refuses non-boolean
job-level booleans by silently dropping the entire
build matrix from the run. The absence cascaded: `publish-crate` `needs:
build` skipped, `release` and `homebrew`
skipped behind it, the v0.3.1 tag pushed but no crate published /
release created / formula dispatched.

Belt-and-suspenders fix:

- **Belt**: normalize the expression to `matrix.soft_fail == true` (and
the same on the post-build annotation step's
  `if:`), so missing-field rows evaluate to `false` instead of `null`.
- **Suspenders**: set `soft_fail: false` explicitly on every non-musl
row, so the matrix is self-documenting (every
row's stance is grep-able) and the implicit-default footgun stops being
a footgun.

Either fix alone closes the immediate bug. Both together prevent the
class — a future matrix row added without
`soft_fail` won't reintroduce this failure.

## Changelog

### Fixed

- Fix silent build-job matrix expansion failure when the caller passed
`linux_musl_required: true`. The expression
`matrix.soft_fail && !inputs.linux_musl_required` returned `null` for
matrix rows without `soft_fail`, which GHA
refuses as a job-level boolean — the entire build matrix dropped from
the run and `publish-crate` / `release` /
  `homebrew` skipped behind it.

## Type of Change

- [x] `fix`: Bug fix (non-breaking change which fixes an issue)

## Related Issues/Stories

- Story: n/a
- Issue: n/a
- Architecture: n/a
- Related PRs: #17 (introduced the matrix rows + expression), #18
(released #17 to main), brettdavies/agentnative-cli#48
(consumer opt-in PR), brettdavies/agentnative-cli#49 (consumer release
PR — the v0.3.1 tag has been deleted from
  agentnative-cli; will be re-pushed after this fix lands on main)

## Testing

- [x] Manual testing completed
- [x] All tests passing

**Test Summary:**

- Unit tests: n/a (workflow-only repo)
- Integration tests: n/a
- Coverage: n/a

`actionlint` clean on the modified `rust-release.yml`. The fix will be
exercised in real conditions when agentnative-cli
re-pushes its v0.3.1 tag after this lands on main — at that point all 7
matrix rows should instantiate (5 hard-fail, 2
soft-fail with `linux_musl_required: true` flipping them to hard-fail).

The original spike validation (brettdavies/agentnative-cli
`spike/musl-build`, 2026-05-04) confirmed the underlying musl
build paths work; this PR addresses only the orchestration glue.

## Files Modified

**Modified:**

- `.github/workflows/rust-release.yml` — Adds explicit `soft_fail:
false` to the 5 non-musl matrix rows
(x86_64-linux-gnu, aarch64-linux-gnu, aarch64-apple-darwin,
x86_64-apple-darwin, x86_64-pc-windows-msvc). Updates the
build-job `continue-on-error` expression and the post-build annotation
step's `if:` to compare `matrix.soft_fail ==
true`. Adds a comment to the matrix block explaining the constraint and
citing the failed run as the canary.

**Created:**

- None.

**Renamed:**

- None.

**Deleted:**

- None.

## Breaking Changes

- [x] No breaking changes

Existing consumers see no behavior change. Consumers passing
`linux_musl_required: false` (default) saw working
soft-fail behavior before this fix because `matrix.soft_fail && true`
returned the matrix-row value (or null for
non-musl rows, but with `continue-on-error: null` GHA seemingly
tolerated it for some expansion paths — only the
`linux_musl_required: true` path triggered the silent drop). The fix
makes both paths reliable.

## Deployment Notes

- [x] No special deployment steps required

After merge to dev → cherry-pick to main, agentnative-cli will re-tag
v0.3.1 and push. Pipeline should run clean: 7
matrix rows instantiate, 5 hard-fail, 2 musl rows hard-fail (because
`linux_musl_required: true` flips their stance). On
a successful musl build the alpine-verify step runs as before.

## Checklist

- [x] Code follows project conventions and style guidelines
- [x] Commit messages follow Conventional Commits
- [x] Self-review of code completed
- [x] Tests added/updated and passing (workflow-only; `actionlint`
clean)
- [x] No new warnings or errors introduced
- [x] Changes are backward compatible
brettdavies added a commit to brettdavies/.github that referenced this pull request May 4, 2026
## Summary

Consolidates two fix commits to main:

- **#20 — `fix(rust-release): normalize build matrix soft_fail
evaluation`** — silent matrix-expansion failure in the
build job's `continue-on-error` expression when callers pass
`linux_musl_required: true`. Bit agentnative-cli's first
attempt at v0.3.1 ([failed
run](https://github.com/brettdavies/agentnative-cli/actions/runs/25336702699))
— tag
pushed, no crate published, no release created. Tag has been deleted;
will be re-pushed after this lands.
Belt-and-suspenders fix: normalize the expression to `matrix.soft_fail
== true` AND set `soft_fail: false` explicitly
  on every non-musl matrix row.

- **#19 — `ci(lint): gate dev pushes and fail on actionlint findings`**
— bundled because it landed on dev between #20
and the cut of this release branch. Single-file change to
`.github/workflows/lint.yml` hardening this repo's own CI:
  actionlint now runs on dev pushes and fails the workflow on findings.

Triple-diff verification clean: A has exactly the two expected files; B
is empty (no non-doc paths on dev missing from
this release); no guarded paths leaked.

## Changelog

### Fixed

- Fix silent build-job matrix expansion failure when the caller passed
`linux_musl_required: true`. The expression
`matrix.soft_fail && !inputs.linux_musl_required` returned `null` for
matrix rows without `soft_fail`, which GHA
refuses as a job-level boolean — the entire build matrix dropped from
the run and `publish-crate` / `release` /
  `homebrew` skipped behind it.

### Changed

- `.github/workflows/lint.yml` (this repo's own CI) now runs actionlint
on `push: dev` and fails the workflow on
  actionlint findings, raising the bar for what reaches dev.

## Type of Change

- [x] `fix`: Bug fix (non-breaking change which fixes an issue)

## Related Issues/Stories

- Story: n/a
- Issue: n/a
- Architecture: n/a
- Related PRs: #20 (the rust-release fix), #19 (the lint hardening), #18
(the release that introduced the soft_fail
bug), brettdavies/agentnative-cli#48 (consumer opt-in),
brettdavies/agentnative-cli#49 (consumer release — v0.3.1 tag
  deleted, will be re-pushed after this lands)

## Testing

- [x] Manual testing completed
- [x] All tests passing

**Test Summary:**

- Unit tests: n/a (workflow-only repo)
- Integration tests: n/a
- Coverage: n/a

`actionlint` clean on both modified workflow files. The rust-release
fix's real-world validation comes when
agentnative-cli re-pushes its v0.3.1 tag after this lands — at that
point all 7 matrix rows should instantiate, 5
hard-fail and 2 musl rows hard-fail (because `linux_musl_required: true`
flips them).

## Files Modified

**Modified:**

- `.github/workflows/rust-release.yml` — see #20.
- `.github/workflows/lint.yml` — see #19.

**Created:**

- None.

**Renamed:**

- None.

**Deleted:**

- None.

## Breaking Changes

- [x] No breaking changes

## Deployment Notes

- [x] No special deployment steps required

After this lands on main, agentnative-cli re-tags v0.3.1 and pushes.
Pipeline should run clean.

## Checklist

- [x] Code follows project conventions and style guidelines
- [x] Commit messages follow Conventional Commits
- [x] Self-review of code completed (PR #20 and #19 reviews apply)
- [x] Tests added/updated and passing (`actionlint` clean on both files)
- [x] No new warnings or errors introduced
- [x] Changes are backward compatible
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant