mirror of
https://github.com/bahdotsh/wrkflw.git
synced 2026-09-02 20:25:31 +02:00
The release builds were running without --locked, which means cargo is free to re-resolve dependencies however it pleases. For a release binary, that's *not great* — you want reproducible builds from the exact Cargo.lock that was committed, not whatever cargo feels like doing today. While at it, the changelog generation was silently falling through to the "list all commits" path if the release tag wasn't found in the tag list. Now it emits a ::warning annotation so you at least know something went sideways instead of staring at a suspiciously long changelog wondering where it all came from.
177 lines
5.6 KiB
YAML
177 lines
5.6 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "v*"
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "Tag to release (e.g., v1.0.0)"
|
|
required: true
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
env:
|
|
CARGO_TERM_COLOR: always
|
|
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
|
|
|
|
jobs:
|
|
changelog:
|
|
name: Generate Changelog
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
changelog: ${{ steps.changelog.outputs.changelog }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Validate tag format
|
|
run: |
|
|
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
|
|
echo "::error::Tag '${RELEASE_TAG}' does not match expected format vX.Y.Z"
|
|
exit 1
|
|
fi
|
|
- name: Validate tag exists
|
|
run: |
|
|
if ! git tag -l "${RELEASE_TAG}" | grep -q .; then
|
|
echo "::error::Tag ${RELEASE_TAG} does not exist as a git tag"
|
|
exit 1
|
|
fi
|
|
- name: Generate changelog
|
|
id: changelog
|
|
run: |
|
|
# Get the previous tag
|
|
all_tags=$(git tag --sort=-v:refname | grep "^v")
|
|
if ! echo "$all_tags" | grep -F -x -q "${RELEASE_TAG}"; then
|
|
echo "::warning::Tag ${RELEASE_TAG} not found in tag list; generating changelog from all commits"
|
|
fi
|
|
prev_tag=$(echo "$all_tags" | grep -F -x -A1 "${RELEASE_TAG}" | tail -1)
|
|
[ "$prev_tag" = "${RELEASE_TAG}" ] && prev_tag="" # No previous tag found
|
|
if [ -z "$prev_tag" ]; then
|
|
# First release: use all commits
|
|
changelog=$(git log --pretty=format:"- %s (%h)" --no-merges --max-count=100)
|
|
else
|
|
changelog=$(git log "${prev_tag}..${RELEASE_TAG}" --pretty=format:"- %s (%h)" --no-merges)
|
|
fi
|
|
# Escape for GitHub Actions output
|
|
{
|
|
echo "changelog<<CHANGELOG_EOF"
|
|
echo "$changelog"
|
|
echo "CHANGELOG_EOF"
|
|
} >> "$GITHUB_OUTPUT"
|
|
|
|
build:
|
|
name: Build (${{ matrix.target }})
|
|
runs-on: ${{ matrix.os }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- target: x86_64-unknown-linux-gnu
|
|
os: ubuntu-latest
|
|
- target: x86_64-unknown-linux-musl
|
|
os: ubuntu-latest
|
|
- target: aarch64-unknown-linux-gnu
|
|
os: ubuntu-latest
|
|
- target: x86_64-apple-darwin
|
|
os: macos-latest
|
|
- target: aarch64-apple-darwin
|
|
os: macos-latest
|
|
- target: x86_64-pc-windows-msvc
|
|
os: windows-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
targets: ${{ matrix.target }}
|
|
- uses: Swatinem/rust-cache@v2
|
|
|
|
- name: Install cross-compilation tools
|
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y gcc-aarch64-linux-gnu
|
|
|
|
- name: Install musl tools
|
|
if: matrix.target == 'x86_64-unknown-linux-musl'
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y musl-tools
|
|
|
|
- name: Configure linker for aarch64-linux-gnu
|
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
|
run: |
|
|
mkdir -p .cargo
|
|
echo '[target.aarch64-unknown-linux-gnu]' > .cargo/config.toml
|
|
echo 'linker = "aarch64-linux-gnu-gcc"' >> .cargo/config.toml
|
|
|
|
- name: Build
|
|
run: cargo build --release --locked --target ${{ matrix.target }}
|
|
|
|
- name: Package (Unix)
|
|
if: runner.os != 'Windows'
|
|
run: tar czf wrkflw-${{ matrix.target }}.tar.gz -C target/${{ matrix.target }}/release wrkflw
|
|
|
|
- name: Package (Windows)
|
|
if: runner.os == 'Windows'
|
|
shell: pwsh
|
|
run: |
|
|
Compress-Archive -Path "target/${{ matrix.target }}/release/wrkflw.exe" -DestinationPath "wrkflw-${{ matrix.target }}.zip"
|
|
|
|
- name: Upload artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: wrkflw-${{ matrix.target }}
|
|
path: wrkflw-${{ matrix.target }}.*
|
|
|
|
publish:
|
|
name: Publish to crates.io
|
|
runs-on: ubuntu-latest
|
|
needs: [build, changelog]
|
|
# Only publish on tag push — manual dispatch uses a branch ref, intentionally excluded
|
|
# because publishing to crates.io is irreversible
|
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: dtolnay/rust-toolchain@stable
|
|
- uses: Swatinem/rust-cache@v2
|
|
- name: Cache cargo-workspaces
|
|
id: cache-cargo-ws
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cargo/bin/cargo-workspaces
|
|
key: cargo-workspaces-0.4.2
|
|
- name: Install cargo-workspaces
|
|
if: steps.cache-cargo-ws.outputs.cache-hit != 'true'
|
|
run: cargo install cargo-workspaces@0.4.2
|
|
- name: Publish all crates
|
|
run: cargo workspaces publish --from-git --yes
|
|
env:
|
|
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
|
|
|
release:
|
|
name: Create GitHub Release
|
|
runs-on: ubuntu-latest
|
|
needs: [build, changelog]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: artifacts
|
|
merge-multiple: true
|
|
|
|
- name: Create release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: ${{ env.RELEASE_TAG }}
|
|
name: wrkflw ${{ env.RELEASE_TAG }}
|
|
body: |
|
|
## What's Changed
|
|
${{ needs.changelog.outputs.changelog }}
|
|
files: artifacts/*
|
|
generate_release_notes: false
|