name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Version to release (e.g., 0.1.0)"
required: true
type: string
env:
CARGO_TERM_COLOR: always
BINARY_NAME: diff-tui
jobs:
validate:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.version }}"
else
VERSION="${GITHUB_REF#refs/tags/v}"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Release version: $VERSION"
- name: Verify Cargo.toml version matches
run: |
CARGO_VERSION=$(grep -m1 'version = ' Cargo.toml | cut -d'"' -f2)
if [ "$CARGO_VERSION" != "${{ steps.version.outputs.version }}" ]; then
echo "Error: Cargo.toml version ($CARGO_VERSION) doesn't match release version (${{ steps.version.outputs.version }})"
exit 1
fi
build:
needs: validate
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
archive: tar.gz
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
archive: tar.gz
- target: x86_64-apple-darwin
os: macos-latest
archive: tar.gz
- target: aarch64-apple-darwin
os: macos-latest
archive: tar.gz
- target: x86_64-pc-windows-msvc
os: windows-latest
archive: zip
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install musl-tools (Linux musl)
if: matrix.target == 'x86_64-unknown-linux-musl'
run: sudo apt-get update && sudo apt-get install -y musl-tools
- name: Build
run: cargo build --release --target ${{ matrix.target }}
- name: Prepare artifacts (Unix)
if: runner.os != 'Windows'
run: |
ARTIFACT_DIR="${{ env.BINARY_NAME }}-v${{ needs.validate.outputs.version }}-${{ matrix.target }}"
mkdir -p "$ARTIFACT_DIR"
cp "target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}" "$ARTIFACT_DIR/"
cp README.md LICENSE "$ARTIFACT_DIR/" 2>/dev/null || true
tar -czvf "$ARTIFACT_DIR.tar.gz" "$ARTIFACT_DIR"
echo "ARTIFACT=$ARTIFACT_DIR.tar.gz" >> $GITHUB_ENV
- name: Prepare artifacts (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$ARTIFACT_DIR = "${{ env.BINARY_NAME }}-v${{ needs.validate.outputs.version }}-${{ matrix.target }}"
New-Item -ItemType Directory -Path $ARTIFACT_DIR -Force
Copy-Item "target/${{ matrix.target }}/release/${{ env.BINARY_NAME }}.exe" $ARTIFACT_DIR/
Copy-Item README.md, LICENSE $ARTIFACT_DIR/ -ErrorAction SilentlyContinue
Compress-Archive -Path $ARTIFACT_DIR -DestinationPath "$ARTIFACT_DIR.zip"
echo "ARTIFACT=$ARTIFACT_DIR.zip" >> $env:GITHUB_ENV
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.BINARY_NAME }}-${{ matrix.target }}
path: ${{ env.ARTIFACT }}
retention-days: 1
publish-crates:
needs: [validate, build]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Publish to crates.io
run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
release:
needs: [validate, build, publish-crates]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release assets
run: |
mkdir -p release-assets
find artifacts -type f \( -name "*.tar.gz" -o -name "*.zip" \) -exec mv {} release-assets/ \;
ls -la release-assets/
- name: Generate checksums
working-directory: release-assets
run: |
sha256sum * > SHA256SUMS.txt
cat SHA256SUMS.txt
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.validate.outputs.version }}
name: v${{ needs.validate.outputs.version }}
draft: false
prerelease: ${{ contains(needs.validate.outputs.version, '-') }}
generate_release_notes: true
files: |
release-assets/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
create-tag:
if: github.event_name == 'workflow_dispatch'
needs: [validate, release]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Create and push tag
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "v${{ needs.validate.outputs.version }}" -m "Release v${{ needs.validate.outputs.version }}"
git push origin "v${{ needs.validate.outputs.version }}"