name: Release
on:
push:
branches:
- main pull_request:
types: [ opened, synchronize, reopened, labeled, unlabeled ]
permissions: {}
jobs:
release-pr:
permissions:
contents: write
pull-requests: write
issues: write
statuses: write
runs-on: ubuntu-latest
outputs:
release_pr: ${{ toJSON(steps.release-pr.outputs) }}
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@v5
- uses: actionutils/trusted-tag-verifier@68bef2f18f8ceb5c4dccc5542cadcfbc82ed4656 with:
verify: 'actionutils/create-release-pr'
- uses: actionutils/create-release-pr@v0
id: release-pr
update-release-pr:
needs: [release-pr]
if: fromJSON(needs.release-pr.outputs.release_pr).state == 'release_pr_open'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
id-token: write steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a with:
egress-policy: audit
- uses: actions/checkout@v5
with:
ref: ${{ fromJSON(needs.release-pr.outputs.release_pr).pr_branch }}
- uses: actions/dependency-review-action@v4
id: dependency-review
with:
base-ref: ${{ fromJSON(needs.release-pr.outputs.release_pr).current_tag }}
head-ref: main
- uses: chainguard-dev/actions/setup-gitsign@0cda751b114eb55c388e88f7479292668165602a
- name: Update README installation section
if: fromJSON(needs.release-pr.outputs.release_pr).next_tag != ''
env:
VERSION: ${{ fromJSON(needs.release-pr.outputs.release_pr).next_tag }}
run: |
# Build kugiri first
cargo build --release
# Update README with new version
./scripts/update-installation.sh "$VERSION"
# Commit if there are changes
git add README.md
if git diff --cached --exit-code; then
echo "No changes to README.md"
else
git commit -m "docs: Update README installation section to $VERSION"
git push
fi
- name: Update CHANGELOG with release notes
if: fromJSON(needs.release-pr.outputs.release_pr).next_tag != ''
env:
VERSION: ${{ fromJSON(needs.release-pr.outputs.release_pr).next_tag }}
RELEASE_NOTES: ${{ fromJSON(needs.release-pr.outputs.release_pr).release_notes }}
run: |
# Create auto-generated title
TITLE="# [$VERSION](https://github.com/${{ github.repository }}/releases/tag/$VERSION) - $(date +%Y-%m-%d)"
# Check if {version} section exists
if ./target/release/kugiri extract CHANGELOG.md --id "$VERSION" > /tmp/existing_section.md 2>/dev/null; then
echo "Found existing $VERSION section, updating auto-generated parts directly in CHANGELOG"
# Update the auto-generated-title directly in CHANGELOG
echo "$TITLE" | ./target/release/kugiri update CHANGELOG.md \
--id "auto-generated-title" \
--write
# Update the auto-generated-notes directly in CHANGELOG
echo "$RELEASE_NOTES" | ./target/release/kugiri update CHANGELOG.md \
--id "auto-generated-notes" \
--write
else
echo "No existing $VERSION section found, creating new structure"
# Create new section with wrapped auto-generated parts
echo "$TITLE" | ./target/release/kugiri wrap --id "auto-generated-title" > /tmp/complete_entry.md
echo "" >> /tmp/complete_entry.md
# Create note with auto-generated-notes inside
echo "$RELEASE_NOTES" | ./target/release/kugiri wrap --id "auto-generated-notes" | \
./target/release/kugiri wrap --id "note-$VERSION" >> /tmp/complete_entry.md
# Insert new section after changelog marker
./target/release/kugiri insert CHANGELOG.md \
--id "$VERSION" \
--body-file /tmp/complete_entry.md \
--after "changelog" \
--write
fi
# Commit if there are changes
git add CHANGELOG.md
if git diff --cached --exit-code; then
echo "No changes to CHANGELOG.md"
else
git commit -m "docs: Update CHANGELOG for $VERSION"
git push
fi
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Install cargo-edit
if: fromJSON(needs.release-pr.outputs.release_pr).next_tag != ''
uses: taiki-e/cache-cargo-install-action@b33c63d3b3c85540f4eba8a4f71a5cc0ce030855 with:
tool: cargo-edit
- name: Bump version in Cargo.{toml,lock}
if: fromJSON(needs.release-pr.outputs.release_pr).next_tag != ''
env:
VERSION: ${{ fromJSON(needs.release-pr.outputs.release_pr).next_tag }}
run: |
# Remove 'v' prefix if present for cargo set-version
VERSION=${VERSION#v}
cargo set-version "$VERSION"
git add Cargo.{toml,lock}
if git diff --cached --exit-code; then
echo "No changes to commit"
else
git commit -m "Bump version to $VERSION"
git push
fi
- uses: mlugg/setup-zig@8d6198c65fb0feaa111df26e6b467fea8345e46f - uses: sigstore/cosign-installer@v3.9.2 - uses: anchore/sbom-action/download-syft@v0.20.5 - name: Preinstall cargo-zigbuild
uses: taiki-e/cache-cargo-install-action@b33c63d3b3c85540f4eba8a4f71a5cc0ce030855 with:
tool: cargo-zigbuild
locked: true
- name: Install mingw binutils (dlltool)
uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 with:
packages: binutils-mingw-w64
version: 1.0
- uses: goreleaser/goreleaser-action@v6
id: goreleaser
with:
version: '~> v2'
args: release --clean --draft --snapshot --skip publish
- uses: actions/upload-artifact@v4
with:
name: snapshot
path: ./dist
verify-releaser:
needs: [release-pr]
if: fromJSON(needs.release-pr.outputs.release_pr).state == 'release_required'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Harden the runner (Audit all outbound calls)
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a with:
egress-policy: audit
- name: Verify Trusted Tag Releaser
uses: actionutils/trusted-tag-verifier@68bef2f18f8ceb5c4dccc5542cadcfbc82ed4656 with:
verify: 'actionutils/trusted-go-releaser@v1'
release:
needs: [verify-releaser, release-pr]
if: fromJSON(needs.release-pr.outputs.release_pr).state == 'release_required'
concurrency:
group: "release"
cancel-in-progress: false
permissions:
id-token: write contents: write pull-requests: write attestations: write actions: read uses: actionutils/trusted-go-releaser/.github/workflows/trusted-release-workflow.yml@v1
with:
environment: release
setup-zig: true
install-mingw-dlltool: true
secrets:
github-token: ${{ secrets.GITHUB_TOKEN }}
publish:
needs: [release-pr, release]
if: fromJSON(needs.release-pr.outputs.release_pr).state == 'release_required'
runs-on: ubuntu-latest
permissions:
id-token: write steps:
- uses: actions/checkout@v5
- uses: rust-lang/crates-io-auth-action@v1
id: auth
- run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}