From b3c0442cb7e956c327f737b12e68783ab34ca87b Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 02:25:06 -0500 Subject: [PATCH 1/6] ci: add release-plz for crates.io publishing with trusted publishing Add release-plz alongside cargo-dist to automate crates.io publishing. release-plz handles version bumping, changelog generation, and crate publishing via OIDC trusted publishing (no token secret needed). cargo-dist continues to handle binary builds, Homebrew, SBOM, and GitHub Releases -- triggered by the git tags release-plz creates. - Add release-plz.toml (git_release_enable=false, delegates to cargo-dist) - Add .github/workflows/release-plz.yml (official quickstart pattern) - Update release-process.md to document the two-tool pipeline - Pin release-plz v0.3.155 in mise.toml Signed-off-by: UncleSp1d3r --- .github/workflows/release-plz.yml | 51 +++++++++++++++++++ docs/src/release-process.md | 85 ++++++++++--------------------- mise.lock | 4 ++ mise.toml | 1 + release-plz.toml | 8 +++ 5 files changed, 90 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/release-plz.yml create mode 100644 release-plz.toml diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml new file mode 100644 index 00000000..c17b598b --- /dev/null +++ b/.github/workflows/release-plz.yml @@ -0,0 +1,51 @@ +name: release-plz + +on: + push: + branches: [main] + +jobs: + release-plz-release: + name: Release-plz release + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Run release-plz + uses: release-plz/action@v0.5 + with: + command: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + release-plz-pr: + name: Release-plz PR + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + concurrency: + group: release-plz-${{ github.ref }} + cancel-in-progress: false + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + persist-credentials: false + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Run release-plz + uses: release-plz/action@v0.5 + with: + command: release-pr + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/docs/src/release-process.md b/docs/src/release-process.md index 64bd47e5..06844944 100644 --- a/docs/src/release-process.md +++ b/docs/src/release-process.md @@ -297,74 +297,41 @@ git push origin --delete hotfix/v0.2.1 ## Release Automation -### GitHub Actions Workflow - -```yaml -# .github/workflows/release.yml -name: Release - -on: - push: - tags: - - v* - -jobs: - release: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Setup Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - - - name: Run tests - run: cargo test --all-features - - - name: Build release - run: cargo build --release - - - name: Create release - uses: actions/create-release@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: false - prerelease: false -``` +Releases are automated by two complementary tools: -### Automated Checks +- **release-plz**: Manages crates.io publishing, version bumping, changelog generation, and git tagging +- **cargo-dist**: Builds cross-platform binaries, Homebrew formulas, SBOM, and GitHub Releases -```bash -#!/bin/bash -# scripts/pre_release_check.sh +### How It Works -set -e +1. Every push to `main` triggers release-plz, which opens (or updates) a **release PR** with: + - Version bump in `Cargo.toml` + - Updated `CHANGELOG.md` (generated via git-cliff) + - Semantic versioning based on conventional commits -echo "Running pre-release checks..." +2. When the release PR is **merged**, release-plz: + - Publishes the crate to **crates.io** + - Creates a **git tag** (e.g., `v0.2.0`) -# Code quality -cargo fmt -- --check -cargo clippy -- -D warnings +3. The git tag triggers **cargo-dist**, which: + - Builds binaries for all target platforms + - Generates SLSA attestations and SBOM + - Publishes the Homebrew formula + - Creates the **GitHub Release** with all artifacts -# Tests -cargo test --all-features -cargo test --doc +### Configuration Files -# Security -cargo audit - -# Performance -cargo bench --bench evaluation_bench +| File | Purpose | +|------|---------| +| `release-plz.toml` | release-plz configuration (crates.io, tags, changelog) | +| `dist-workspace.toml` | cargo-dist configuration (binaries, Homebrew, SBOM) | +| `cliff.toml` | git-cliff changelog template (shared by both tools) | -# Documentation -cargo doc --document-private-items +### Authentication -echo "All pre-release checks passed!" -``` +- **crates.io**: Uses [trusted publishing](https://doc.rust-lang.org/cargo/reference/registry-authentication.html#oidc-token-exchange) (OIDC) -- no token secret needed. Requires configuring the trusted publisher on crates.io and `id-token: write` permission in the workflow. Note: the first publish of a new crate must be done manually with `cargo publish`. +- **Homebrew tap**: Requires a `HOMEBREW_TAP_TOKEN` secret with write access to the tap repository. +- **GitHub Releases**: Uses the automatic `GITHUB_TOKEN`. ## Release Schedule diff --git a/mise.lock b/mise.lock index 83ae4cb2..aa249306 100644 --- a/mise.lock +++ b/mise.lock @@ -86,6 +86,10 @@ backend = "cargo:mdbook-tabs" version = "0.15.3" backend = "cargo:mdbook-toc" +[[tools."cargo:release-plz"]] +version = "0.3.155" +backend = "cargo:release-plz" + [[tools.just]] version = "1.46.0" backend = "aqua:casey/just" diff --git a/mise.toml b/mise.toml index 603a0db1..6f741445 100644 --- a/mise.toml +++ b/mise.toml @@ -30,3 +30,4 @@ pre-commit = "latest" "cargo:cargo-machete" = "0.9.1" "cargo:git-cliff" = "2.12.0" scorecard = "5.4.0" +"cargo:release-plz" = "0.3.155" diff --git a/release-plz.toml b/release-plz.toml new file mode 100644 index 00000000..183b4109 --- /dev/null +++ b/release-plz.toml @@ -0,0 +1,8 @@ +[workspace] +# release-plz handles crates.io publish + git tags +# cargo-dist handles GitHub Releases (triggered by the tag) +git_release_enable = false +git_tag_enable = true +publish = true +semver_check = true +changelog_config = "cliff.toml" From 83e0a6cca6ee455a5a4a51e035e8e9ee74ace40e Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 02:28:18 -0500 Subject: [PATCH 2/6] fix(ci): enable persist-credentials for signed tag pushing release-plz needs persist-credentials: true on the release job to push signed tags via the git CLI instead of the GitHub API. Signed-off-by: UncleSp1d3r --- .github/workflows/release-plz.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index c17b598b..1073ce54 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -16,7 +16,8 @@ jobs: uses: actions/checkout@v6 with: fetch-depth: 0 - persist-credentials: false + # persist-credentials required for pushing signed tags via git CLI + persist-credentials: true - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Run release-plz From a5d606d97a125f7deb13a4a18fe42558d92e15ac Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 02:29:14 -0500 Subject: [PATCH 3/6] refactor(ci): use mise-action instead of dtolnay/rust-toolchain Use the same jdx/mise-action pattern as all other workflows. This installs the pinned Rust toolchain from mise.toml along with all other project dependencies in a single step. Signed-off-by: UncleSp1d3r --- .github/workflows/release-plz.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 1073ce54..4be43049 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -18,8 +18,9 @@ jobs: fetch-depth: 0 # persist-credentials required for pushing signed tags via git CLI persist-credentials: true - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 + with: + install: true - name: Run release-plz uses: release-plz/action@v0.5 with: @@ -42,8 +43,9 @@ jobs: with: fetch-depth: 0 persist-credentials: false - - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + - uses: jdx/mise-action@6d1e696aa24c1aa1bcc1adea0212707c71ab78a8 # v3.6.1 + with: + install: true - name: Run release-plz uses: release-plz/action@v0.5 with: From a699eb5b6f7ebe94bae1830d3301339e779d7c03 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 02:32:57 -0500 Subject: [PATCH 4/6] ci: add merge gate job for branch protection Add a ci-pass job that acts as a single required status check. It passes when all CI jobs succeed OR when they are skipped due to path filtering (no Rust changes). This allows setting one required check ("CI") in branch protection instead of listing every job. Signed-off-by: UncleSp1d3r --- .github/workflows/ci.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc1edd3c..911fc6a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,3 +149,22 @@ jobs: with: token: ${{ secrets.QLTY_COVERAGE_TOKEN }} files: lcov.info + + # Single required status check for branch protection. + # Passes when all jobs pass OR when jobs are skipped (no Rust changes). + ci-pass: + name: CI + runs-on: ubuntu-latest + if: always() + needs: [quality, test, test-cross-platform, coverage] + steps: + - name: Check results + run: | + results=("${{ needs.quality.result }}" "${{ needs.test.result }}" "${{ needs.test-cross-platform.result }}" "${{ needs.coverage.result }}") + for result in "${results[@]}"; do + if [[ "$result" != "success" && "$result" != "skipped" ]]; then + echo "Job failed with result: $result" + exit 1 + fi + done + echo "All jobs passed or were skipped" From d9dcd548a31dc628db3aa21cabd6e02dd78ba546 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 02:40:36 -0500 Subject: [PATCH 5/6] fix(ci): pin GitHub Actions to commit SHAs for supply chain security Pin actions/checkout and release-plz/action to full commit SHAs with version comments, matching the established pattern across all other workflows in this repository. Signed-off-by: UncleSp1d3r --- .github/workflows/release-plz.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 4be43049..7a2a02b8 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -13,7 +13,7 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 # persist-credentials required for pushing signed tags via git CLI @@ -22,7 +22,7 @@ jobs: with: install: true - name: Run release-plz - uses: release-plz/action@v0.5 + uses: release-plz/action@52440b50d383aa252927de395c8b2c1e0a9cf8e9 # v0.5 with: command: release env: @@ -39,7 +39,7 @@ jobs: cancel-in-progress: false steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 persist-credentials: false @@ -47,7 +47,7 @@ jobs: with: install: true - name: Run release-plz - uses: release-plz/action@v0.5 + uses: release-plz/action@52440b50d383aa252927de395c8b2c1e0a9cf8e9 # v0.5 with: command: release-pr env: From cc096dbb7b65b4d866d468d62a270db3c7c176a4 Mon Sep 17 00:00:00 2001 From: UncleSp1d3r Date: Sun, 15 Feb 2026 02:43:48 -0500 Subject: [PATCH 6/6] chore(ci): update changelog with recent CI enhancements and fixes Signed-off-by: UncleSp1d3r --- CHANGELOG.md | 37 ++++++++++++------------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0657783..b3e89c8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,37 +17,24 @@ All notable changes to this project will be documented in this file. - Evaluation enhancements with confidence, MIME, tags, metadata ([#29](https://github.com/EvilBit-Labs/libmagic-rs/pull/29)) - Strength calculation & documentation improvements ([#21](https://github.com/EvilBit-Labs/libmagic-rs/pull/21)) ([#30](https://github.com/EvilBit-Labs/libmagic-rs/pull/30)) +### Bug Fixes + +- **ci**: Enable persist-credentials for signed tag pushing +- **ci**: Pin GitHub Actions to commit SHAs for supply chain security + +### Refactor + +- **ci**: Use mise-action instead of dtolnay/rust-toolchain + ### Documentation - Comprehensive mdbook rewrite, rustdoc fixes, and test stability ([#33](https://github.com/EvilBit-Labs/libmagic-rs/pull/33)) -- **agents**: Update AGENTS.md to reflect implemented features and future plans -- **agents**: Fix inaccurate feature claims in AGENTS.md -- **readme**: Update README.md with project badges for visibility -- Improve SECURITY.md with scope, safe harbor, and responsible disclosure -- Add PGP key for encrypted vulnerability reporting -- Use support@evilbitlabs.io for security contact to match PGP key -- Add code review requirements to AGENTS.md and CONTRIBUTING.md -- Add quick reference and OSSF quality standards to CLAUDE.md -- Add DCO requirement to CONTRIBUTING.md -- Add project governance model and update development guide -- Update roadmap to match milestones and add non-goals -- Add release verification guide for signed artifacts -- Add security assurance case for OSSF gold criteria -- **readme**: Add OpenSSF Best Practices badge -- Move OSSF standards from CLAUDE.md to AGENTS.md -- Extract roadmap into ROADMAP.md to keep README concise -- Add project-level Claude Code skills for Rust development +- Comprehensive documentation, security, and CI hardening ([#58](https://github.com/EvilBit-Labs/libmagic-rs/pull/58)) ### Miscellaneous Tasks - **ci**: Add GitHub workflows for auditing, security, and documentation - Add Contributor Covenant Code of Conduct ([#2](https://github.com/EvilBit-Labs/libmagic-rs/pull/2)) -- Pin all GitHub Actions to SHA hashes for supply chain security -- Revert SHA pins in release.yml (managed by cargo-dist) -- Add git-cliff changelog generation and simplify justfile -- Commit Cargo.lock for reproducible binary builds -- Commit mise.lock for reproducible dev tool versions -- Add SPDX license and copyright headers to all source files -- Add Claude Code hook to enforce DCO sign-off on commits -- Add hookify rules for Rust code safety warnings +- Add release-plz for crates.io publishing with trusted publishing +- Add merge gate job for branch protection