cachekit-core 0.2.1

LZ4 compression, xxHash3 integrity, AES-256-GCM encryption for byte payloads
Documentation
name: Release

on:
  push:
    branches:
      - main
  # Manual re-publish escape hatch: lets the publish job run for the version
  # currently on main when an automated release published the tag but the
  # publish job failed downstream (e.g. a transient Sigstore/Fulcio outage).
  workflow_dispatch: {}

permissions:
  contents: write
  pull-requests: write

# Serialise release runs so a push and a manual dispatch can't race into two
# concurrent cargo publish attempts. Never cancel an in-flight publish.
concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

jobs:
  release-please:
    runs-on: cachekit
    outputs:
      release_created: ${{ steps.release.outputs.release_created }}
      tag_name: ${{ steps.release.outputs.tag_name }}
    steps:
      - uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
        id: app-token
        with:
          app-id: ${{ secrets.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}

      - uses: googleapis/release-please-action@8b8fd2cc23b2e18957157a9d923d75aa0c6f6ad5 # v4
        id: release
        with:
          token: ${{ steps.app-token.outputs.token }}

  publish:
    needs: release-please
    # Run on an automated release, OR on a manual dispatch — but a manual dispatch
    # must target main (workflow_dispatch can be fired from any ref; restricting to
    # refs/heads/main stops a feature branch from publishing its own Cargo.toml).
    # Explicit == 'true' avoids relying on string-coercion of the action output.
    if: ${{ needs.release-please.outputs.release_created == 'true' || (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') }}
    # GitHub-hosted: the self-hosted ARC pods have unreliable DNS/egress to Sigstore
    # (Fulcio/Rekor), which intermittently fails build-provenance + SBOM attestation
    # and blocks publish. A hosted runner has reliable egress to Sigstore + crates.io,
    # and the publish job is infrequent + free on public repos.
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
      attestations: write
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Install Rust toolchain
        uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable

      - name: Cache cargo registry
        uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2

      - name: Run tests before publish
        run: cargo test --all-features

      - name: Package crate
        run: cargo package

      - name: Attest Build Provenance
        uses: actions/attest-build-provenance@96b4a1ef7235a096b17240c259729fdd70c83d45 # v2
        with:
          subject-path: target/package/*.crate

      - name: Install cargo-sbom
        # --force is required: the self-hosted runner's CARGO_HOME (/cache/cargo) is a
        # persistent volume, so the binary survives between runs and a plain install
        # exits 101 ("binary `cargo-sbom` already exists"). --force reinstalls the
        # --locked pinned version idempotently.
        run: cargo install cargo-sbom --locked --force

      - name: Generate SBOM
        run: |
          cargo sbom --output-format cyclone_dx_json_1_6 > sbom.cdx.json
          test -s sbom.cdx.json || { echo "::error::SBOM file is empty"; exit 1; }

      - name: Attest SBOM
        uses: actions/attest-sbom@10926c72720ffc3f7b666661c8e55b1344e2a365 # v2
        with:
          subject-path: target/package/*.crate
          sbom-path: sbom.cdx.json

      - name: Publish to crates.io
        run: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}