name: Release and Publish
on:
workflow_dispatch:
inputs:
release_type:
description: "Release type (will auto-bump version)"
required: true
default: "patch"
type: choice
options:
- major
- minor
- patch
permissions:
actions: write
contents: write
id-token: write
attestations: write
jobs:
release:
name: Create Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.bump.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Configure Git
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
cache-all-crates: true
- name: Install cargo-edit
run: cargo install cargo-edit
- name: Bump version
id: bump
run: |
echo "Release type: '${{ github.event.inputs.release_type }}'"
# Read current version from Cargo.toml using grep and sed
current_version=$(grep '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
echo "Current version from Cargo.toml: $current_version"
if [ "${{ github.event.inputs.release_type }}" = "major" ]; then
new_version=$(echo $current_version | awk -F. '{print $1+1 ".0.0"}')
elif [ "${{ github.event.inputs.release_type }}" = "minor" ]; then
new_version=$(echo $current_version | awk -F. '{print $1 "." $2+1 ".0"}')
else
new_version=$(echo $current_version | awk -F. '{print $1 "." $2 "." $3+1}')
fi
echo "Auto-bumped version: $new_version"
echo "version=$new_version" >> $GITHUB_OUTPUT
echo "Final version output: $new_version"
- name: Update Cargo.toml version
run: |
cargo set-version ${{ steps.bump.outputs.version }}
- name: Update Cargo.lock
run: cargo check
- name: Create changelog
run: |
echo "# Changelog for ${{ steps.bump.outputs.version }}" > CHANGELOG.md
echo "" >> CHANGELOG.md
echo "## [Unreleased]" >> CHANGELOG.md
echo "" >> CHANGELOG.md
# Get the previous tag or use initial commit
if git tag --sort=-version:refname | head -n1 | grep -q .; then
previous_tag=$(git tag --sort=-version:refname | head -n1)
echo "## Changes since $previous_tag" >> CHANGELOG.md
echo "" >> CHANGELOG.md
# Get commits since last tag
commits=$(git log --oneline --no-merges "$previous_tag..HEAD" | head -20)
if [ -n "$commits" ]; then
echo "### Commits" >> CHANGELOG.md
echo "" >> CHANGELOG.md
echo "$commits" | while read -r commit; do
echo "- $commit" >> CHANGELOG.md
done
echo "" >> CHANGELOG.md
fi
else
echo "## Initial Release" >> CHANGELOG.md
echo "" >> CHANGELOG.md
echo "### Features" >> CHANGELOG.md
echo "- Initial project setup" >> CHANGELOG.md
echo "" >> CHANGELOG.md
fi
- name: Build release
run: cargo build --release
- name: Create release assets
run: |
mkdir -p release
cp target/release/zackstrap release/zackstrap-ubuntu
tar -czf release/zackstrap-ubuntu.tar.gz -C release zackstrap-ubuntu
- name: Generate artifact attestations
uses: actions/attest-build-provenance@v3
with:
subject-path: "${{ github.workspace }}/release/zackstrap-ubuntu.tar.gz"
- name: Commit and push changes
run: |
git add Cargo.toml Cargo.lock CHANGELOG.md
git commit -m "Bump version to ${{ steps.bump.outputs.version }}"
git tag -a "v${{ steps.bump.outputs.version }}" -m "Release v${{ steps.bump.outputs.version }}"
git push origin main
git push origin "v${{ steps.bump.outputs.version }}"
- name: Create GitHub Release
id: create_release
uses: softprops/action-gh-release@v1
with:
tag_name: "v${{ steps.bump.outputs.version }}"
name: "Release v${{ steps.bump.outputs.version }}"
body: |
## Release v${{ steps.bump.outputs.version }}
This release includes the following changes since the previous version.
### 📋 Changelog
See the [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) file for detailed information about this release.
### 🚀 Installation
```bash
cargo install zackstrap
```
### 📖 Usage
```bash
zackstrap --help
```
### 🔗 Links
- [Repository](https://github.com/${{ github.repository }})
- [Documentation](https://docs.rs/zackstrap)
- [Issues](https://github.com/${{ github.repository }}/issues)
draft: false
prerelease: false
files: release/zackstrap-ubuntu.tar.gz
publish:
name: Publish to Crates.io
runs-on: ubuntu-latest
needs: release
if: success()
steps:
- name: Wait for git push to propagate
run: |
echo "Waiting for git push to propagate..."
sleep 10
echo "Proceeding with checkout..."
- name: Checkout code
uses: actions/checkout@v6
with:
ref: "main"
fetch-depth: 1
- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
cache-all-crates: true
- name: Verify version
run: |
echo "Verifying version before publishing..."
current_version=$(grep '^version = ' Cargo.toml | sed 's/version = "\(.*\)"/\1/')
echo "Current version in Cargo.toml: $current_version"
echo "Expected version from release job: ${{ needs.release.outputs.version }}"
if [ "$current_version" != "${{ needs.release.outputs.version }}" ]; then
echo "❌ Version mismatch! Expected ${{ needs.release.outputs.version }} but found $current_version"
exit 1
fi
echo "✅ Version verified: $current_version"
- name: Publish to crates.io
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}