Skip to content

Release

Release #90

Workflow file for this run

name: Release
on:
push:
tags: ["v*"]
workflow_dispatch:
inputs:
bump:
description: "Version bump type (leave 'auto' to detect from commit messages)"
required: true
type: choice
default: auto
options:
- auto
- patch
- minor
- major
permissions:
contents: write
packages: write
env:
CARGO_TERM_COLOR: always
jobs:
# Manual dispatch path: bump Cargo.toml, commit, tag, push.
# Downstream jobs run in this same workflow run (keyed off needs.bump)
# because tag pushes signed by GITHUB_TOKEN don't cascade into a new
# workflow run — so we can't rely on the `push: tags` trigger firing.
bump:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-22.04
outputs:
new_tag: ${{ steps.version.outputs.tag }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Detect bump type from commits
id: detect
run: |
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
RANGE="HEAD"
else
RANGE="${LAST_TAG}..HEAD"
fi
COMMITS=$(git log --pretty=format:"%s" "$RANGE")
echo "## Commits since $LAST_TAG:"
echo "$COMMITS"
echo ""
BUMP="patch"
if echo "$COMMITS" | grep -qiE "^feat(\(.*\))?!:|BREAKING CHANGE"; then
BUMP="major"
elif echo "$COMMITS" | grep -qiE "^feat(\(.*\))?:"; then
BUMP="minor"
elif echo "$COMMITS" | grep -qiE "^(fix|perf)(\(.*\))?:"; then
BUMP="patch"
fi
echo "detected=$BUMP" >> "$GITHUB_OUTPUT"
echo "Detected bump: $BUMP"
- name: Resolve bump type
id: bump
run: |
if [ "${{ inputs.bump }}" = "auto" ]; then
BUMP="${{ steps.detect.outputs.detected }}"
else
BUMP="${{ inputs.bump }}"
fi
echo "type=$BUMP" >> "$GITHUB_OUTPUT"
echo "Using bump type: $BUMP"
- name: Compute new version
id: version
run: |
CURRENT=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)"/\1/')
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"
case "${{ steps.bump.outputs.type }}" in
major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;;
minor) MINOR=$((MINOR + 1)); PATCH=0 ;;
patch) PATCH=$((PATCH + 1)) ;;
esac
NEW="${MAJOR}.${MINOR}.${PATCH}"
echo "current=$CURRENT" >> "$GITHUB_OUTPUT"
echo "new=$NEW" >> "$GITHUB_OUTPUT"
echo "tag=v${NEW}" >> "$GITHUB_OUTPUT"
- name: Summary
run: |
echo "### Release Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "| | |" >> "$GITHUB_STEP_SUMMARY"
echo "|---|---|" >> "$GITHUB_STEP_SUMMARY"
echo "| **Current** | v${{ steps.version.outputs.current }} |" >> "$GITHUB_STEP_SUMMARY"
echo "| **New** | ${{ steps.version.outputs.tag }} |" >> "$GITHUB_STEP_SUMMARY"
echo "| **Bump** | ${{ steps.bump.outputs.type }} |" >> "$GITHUB_STEP_SUMMARY"
echo "| **Auto-detected** | ${{ steps.detect.outputs.detected }} |" >> "$GITHUB_STEP_SUMMARY"
- name: Bump Cargo.toml
run: sed -i "0,/^version = \".*\"/s//version = \"${{ steps.version.outputs.new }}\"/" Cargo.toml
- name: Update Cargo.lock
run: cargo generate-lockfile
- name: Commit, tag, and push
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock
git commit -m "chore: release ${{ steps.version.outputs.tag }}"
git tag "${{ steps.version.outputs.tag }}"
git push origin main --tags
build-linux:
name: Build Linux (${{ matrix.target }})
needs: [bump]
if: |
always() &&
(startsWith(github.ref, 'refs/tags/') || needs.bump.result == 'success')
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
arch: x86_64
- target: aarch64-unknown-linux-gnu
arch: aarch64
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.bump.outputs.new_tag || github.ref }}
- uses: dtolnay/rust-toolchain@1.95.0
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: release-${{ matrix.target }}
- name: Install cross-compilation tools
if: matrix.arch == 'aarch64'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
echo '[target.aarch64-unknown-linux-gnu]' >> ~/.cargo/config.toml
echo 'linker = "aarch64-linux-gnu-gcc"' >> ~/.cargo/config.toml
- name: Build
run: |
T="${{ matrix.target }}"
cargo build --release --target $T --no-default-features --features fuse,vendored-openssl --bin hf-mount-fuse
cargo build --release --target $T --no-default-features --features fuse,vendored-openssl --bin hf-mount-fuse-sidecar
cargo build --release --target $T --no-default-features --features nfs,vendored-openssl --bin hf-mount-nfs
cargo build --release --target $T --no-default-features --features vendored-openssl --bin hf-mount
- name: Package
run: |
mkdir -p dist
for bin in hf-mount-fuse hf-mount-fuse-sidecar hf-mount-nfs hf-mount; do
cp target/${{ matrix.target }}/release/$bin dist/${bin}-${{ matrix.arch }}-linux
done
chmod +x dist/*
- uses: actions/upload-artifact@v4
with:
name: linux-${{ matrix.arch }}
path: dist/
build-macos:
name: Build macOS (${{ matrix.arch }})
needs: [bump]
if: |
always() &&
(startsWith(github.ref, 'refs/tags/') || needs.bump.result == 'success')
runs-on: ${{ matrix.runner }}
strategy:
matrix:
include:
- arch: arm64
target: aarch64-apple-darwin
runner: macos-14
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.bump.outputs.new_tag || github.ref }}
- uses: dtolnay/rust-toolchain@1.95.0
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install macFUSE
run: brew install macfuse
- name: Build
run: |
T="${{ matrix.target }}"
cargo build --release --target $T --no-default-features --features fuse,vendored-openssl --bin hf-mount-fuse
cargo build --release --target $T --no-default-features --features fuse,vendored-openssl --bin hf-mount-fuse-sidecar
cargo build --release --target $T --no-default-features --features nfs,vendored-openssl --bin hf-mount-nfs
cargo build --release --target $T --no-default-features --features vendored-openssl --bin hf-mount
- name: Package
run: |
mkdir -p dist
for bin in hf-mount-fuse hf-mount-fuse-sidecar hf-mount-nfs hf-mount; do
cp target/${{ matrix.target }}/release/$bin dist/${bin}-${{ matrix.arch }}-apple-darwin
done
chmod +x dist/*
- uses: actions/upload-artifact@v4
with:
name: macos-${{ matrix.arch }}
path: dist/
# Compute the docker tag base + whether to push :latest. A bumped
# release wins, then a manually-pushed tag, else fall back to sha-<sha>.
# `latest` only on stable releases (tag matches `v\d` and has no `-`).
docker-tag:
needs: [bump]
if: always() && needs.bump.result != 'failure'
runs-on: ubuntu-22.04
outputs:
base: ${{ steps.compute.outputs.base }}
push_latest: ${{ steps.compute.outputs.push_latest }}
steps:
- id: compute
run: |
NEW_TAG="${{ needs.bump.outputs.new_tag }}"
if [[ -n "$NEW_TAG" ]]; then
BASE="$NEW_TAG"
elif [[ "${GITHUB_REF}" == refs/tags/* ]]; then
BASE="${GITHUB_REF#refs/tags/}"
else
BASE="sha-${GITHUB_SHA}"
fi
PUSH_LATEST=false
if [[ "$BASE" =~ ^v[0-9] && "$BASE" != *"-"* ]]; then
PUSH_LATEST=true
fi
echo "base=$BASE" >> "$GITHUB_OUTPUT"
echo "push_latest=$PUSH_LATEST" >> "$GITHUB_OUTPUT"
docker:
needs: [bump, docker-tag]
if: always() && needs.docker-tag.result == 'success'
uses: ./.github/workflows/_docker-build.yml
with:
ref: ${{ needs.bump.outputs.new_tag || github.ref }}
tag_base: ${{ needs.docker-tag.outputs.base }}
push_latest: ${{ needs.docker-tag.outputs.push_latest == 'true' }}
release:
name: Create Release
needs: [bump, build-linux, build-macos]
if: |
always() &&
needs.build-linux.result == 'success' &&
needs.build-macos.result == 'success' &&
(startsWith(github.ref, 'refs/tags/') || needs.bump.result == 'success')
runs-on: ubuntu-22.04
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
pattern: '{linux-*,macos-*}'
merge-multiple: true
- name: List artifacts
run: ls -lh artifacts/
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ needs.bump.outputs.new_tag || github.ref_name }}"
gh release create "$TAG" artifacts/* \
--repo "${{ github.repository }}" \
--title "$TAG" \
--generate-notes