Skip to content

feat(release): add release automation with changelog generation#1177

Merged
geoffjay merged 2 commits intomainfrom
issue-137
Apr 18, 2026
Merged

feat(release): add release automation with changelog generation#1177
geoffjay merged 2 commits intomainfrom
issue-137

Conversation

@geoffjay
Copy link
Copy Markdown
Owner

Implements automated release infrastructure triggered by v* git tags.

What's added:

  • .github/workflows/release.yml - GitHub Actions workflow that triggers on v* tag pushes, builds release binaries in a matrix for macOS arm64 (aarch64-apple-darwin), macOS x86_64 (x86_64-apple-darwin), and Linux x86_64 (x86_64-unknown-linux-gnu), generates release notes via git-cliff, and creates a GitHub Release with all binaries attached as assets
  • cliff.toml - git-cliff configuration mapping conventional commit types (feat, fix, refactor, perf, docs, chore(deps)) to changelog sections; includes GitHub PR link enrichment
  • crates/xtask/src/main.rs - New cargo xtask release [--dry-run] subcommand that verifies a clean working tree, reads the workspace version from Cargo.toml, updates CHANGELOG.md via git-cliff (if installed), commits the changelog, and creates an annotated git tag; --dry-run previews all steps without making changes

Release workflow:

# After bumping version in Cargo.toml and committing:
cargo xtask release        # creates tag v0.3.0
git push origin v0.3.0    # triggers CI → builds + GitHub Release

Closes #137

- Add .github/workflows/release.yml triggered by v* tags; builds
  binaries for macOS arm64/x86_64 and Linux x86_64, generates release
  notes via git-cliff, and creates a GitHub Release with attached assets
- Add cliff.toml for conventional-commits changelog configuration
- Add `cargo xtask release [--dry-run]` subcommand that verifies a
  clean working tree, updates CHANGELOG.md via git-cliff, and creates
  an annotated git tag ready to push

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@geoffjay geoffjay added the review-agent Used to invoke a review by an agent tracking this label label Apr 18, 2026
Copy link
Copy Markdown
Owner Author

@geoffjay geoffjay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — PR #1177: Release Automation

Good structure overall. The three-file split (workflow, cliff config, xtask subcommand) is clean and each piece does one thing. Two issues need to be fixed before merge.


Branch target

This PR targets main directly. CLAUDE.md states all work branches off feature/autonomous-pipeline and PRs back into it, never directly to main. Release tooling may be intentionally excluded from that rule, but worth confirming with the project owner before merging.


Blocking issues

1. Unchecked exit codes for git add and git commit in release() (crates/xtask/src/main.rs, ~lines 685–701)

Command::new("git")
    .args(["add", "CHANGELOG.md"])
    .status()
    .context("Failed to stage CHANGELOG.md")?;
Command::new("git")
    .args(["commit", "-m", &format!("chore(release): update changelog for {tag}")])
    .status()
    .context("Failed to commit CHANGELOG.md")?;

.status().context(...)? only propagates an io::Error if the process failed to spawn — it does not fail when the command exits non-zero. If git add or git commit returns exit code 1, execution silently continues and the tag is created on a commit that does not include the updated CHANGELOG.md.

Every other long-running command in this codebase (e.g. build_release()) explicitly checks .success(). Apply the same pattern here:

let status = Command::new("git")
    .args(["add", "CHANGELOG.md"])
    .status()
    .context("Failed to stage CHANGELOG.md")?;
if !status.success() {
    anyhow::bail!("git add CHANGELOG.md failed");
}

Same fix needed for the git commit call immediately below.


Non-blocking suggestions

2. Linux target: x86_64-unknown-linux-gnux86_64-unknown-linux-musl (.github/workflows/release.yml)

GNU-linked binaries dynamically link against glibc. The ubuntu-latest runner ships glibc 2.35+, so binaries built there will fail on older distributions (Ubuntu 20.04, CentOS, Alpine) with GLIBC_X.XX not found. For distributed release binaries, musl produces a fully static binary that runs on any Linux regardless of system glibc version.

Change the target and add musl-tools:

- target: x86_64-unknown-linux-musl
  os: ubuntu-latest
# In the Linux protoc step:
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler musl-tools

3. GitHub PR link enrichment silently produces no links (.github/workflows/release.yml, "Generate release notes" step)

cliff.toml includes {% if commit.github.pr_number %} enrichment, but git-cliff reads GITHUB_TOKEN from the environment to query the GitHub API. Actions does not expose secrets.GITHUB_TOKEN automatically as an env var — it must be wired explicitly:

- name: Generate release notes
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: git cliff --current --output RELEASE_NOTES.md

Without this, pr_number is always empty and PR links never appear in release notes. The release still works — it just degrades silently.

4. No pre-flight checks in cargo xtask release (crates/xtask/src/main.rs)

The function creates a tag without verifying the build is clean. If run on a commit that hasn't passed CI, the release workflow fires on potentially broken code. Consider adding cargo fmt --check and cargo clippy -- -D warnings before creating the tag.

5. Misleading variable name staged (~line 682)

let staged = Command::new("git").args(["diff", "--quiet", "CHANGELOG.md"]) checks for unstaged working-tree changes, not staged ones. Rename to changelog_changed or has_changes.

6. filter_commits = false in cliff.toml

With conventional_commits = true + filter_unconventional = true, any conventional commit type not covered by a parser (e.g. ^revert, custom types) passes through ungrouped. Setting filter_commits = true ensures only commits matching a non-skip parser appear in the changelog.


What's correct

  • fetch-depth: 0 on all jobs — required for git-cliff to walk tag history. ✓
  • fail-fast: false on the build matrix — single-platform failure doesn't cancel others. ✓
  • permissions: contents: write scoped to the release job only. ✓
  • Protoc install steps for both Linux and macOS. ✓
  • ${bin/cli/agent} bash substitution in packaging — correctly renames the user-facing binary. ✓
  • extract_workspace_version() line parser handles real-world Cargo.toml formatting correctly. ✓
  • git diff --quiet CHANGELOG.md exit code semantics are correct (0 = no diff, 1 = changed). ✓

@geoffjay geoffjay added needs-rework PR has review feedback that must be addressed before merging and removed review-agent Used to invoke a review by an agent tracking this label labels Apr 18, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 18, 2026

Codecov Report

❌ Patch coverage is 0% with 89 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.10%. Comparing base (b04ff00) to head (85cf711).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
crates/xtask/src/main.rs 0.00% 89 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1177      +/-   ##
==========================================
- Coverage   60.33%   60.10%   -0.24%     
==========================================
  Files         228      228              
  Lines       25489    25578      +89     
==========================================
- Hits        15380    15374       -6     
- Misses      10109    10204      +95     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@geoffjay geoffjay merged commit a70a5f9 into main Apr 18, 2026
5 of 12 checks passed
@geoffjay geoffjay deleted the issue-137 branch April 18, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-rework PR has review feedback that must be addressed before merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add release automation with changelog generation

1 participant