name: Release
on:
push:
tags: [ "v*" ]
permissions:
contents: write
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-24.04, target: x86_64-unknown-linux-gnu }
- { os: ubuntu-24.04, target: x86_64-unknown-linux-musl }
- { os: ubuntu-24.04, target: aarch64-unknown-linux-musl }
- { os: ubuntu-24.04, target: armv7-unknown-linux-musleabihf }
- { os: macos-14, target: aarch64-apple-darwin }
- { os: windows-2022, target: x86_64-pc-windows-msvc }
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
- if: runner.os == 'Linux' && contains(matrix.target, 'musl')
uses: mlugg/setup-zig@v2
with:
version: 0.15.2
- name: Install cargo-zigbuild
if: runner.os == 'Linux' && contains(matrix.target, 'musl')
run: cargo install cargo-zigbuild --locked
- name: Build binary
shell: bash
env:
TARGET: ${{ matrix.target }}
USE_ZIGBUILD: ${{ runner.os == 'Linux' && contains(matrix.target, 'musl') }}
run: |
set -euo pipefail
if [[ "$USE_ZIGBUILD" == "true" ]]; then
cargo zigbuild --release --locked --target "$TARGET"
else
cargo build --release --locked --target "$TARGET"
fi
- name: Package archive (Unix)
if: runner.os != 'Windows'
id: package_unix
shell: bash
env:
TARGET: ${{ matrix.target }}
OS_LABEL: ${{ matrix.os }}
run: |
set -euo pipefail
artifact="watchctl-${TARGET}-${OS_LABEL}"
dist="$GITHUB_WORKSPACE/dist"
staging="$dist/$artifact"
rm -rf "$staging"
mkdir -p "$staging"
cp "target/${TARGET}/release/watchctl" "$staging/watchctl"
cp LICENSE "$staging/LICENSE"
tar -C "$dist" -czf "$dist/${artifact}.tar.gz" "$artifact"
pushd "$dist" >/dev/null
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "${artifact}.tar.gz" > "${artifact}.tar.gz.sha256"
else
shasum -a 256 "${artifact}.tar.gz" > "${artifact}.tar.gz.sha256"
fi
popd >/dev/null
- name: Package archive (Windows)
if: runner.os == 'Windows'
id: package_windows
shell: pwsh
env:
TARGET: ${{ matrix.target }}
OS_LABEL: ${{ matrix.os }}
run: |
$artifact = "watchctl-$env:TARGET-$env:OS_LABEL"
$dist = Join-Path $env:GITHUB_WORKSPACE 'dist'
$binary = Join-Path $env:GITHUB_WORKSPACE "target/$env:TARGET/release/watchctl.exe"
if (!(Test-Path $dist)) {
New-Item $dist -ItemType Directory | Out-Null
}
$staging = Join-Path $dist $artifact
if (Test-Path $staging) {
Remove-Item $staging -Recurse -Force
}
New-Item $staging -ItemType Directory -Force | Out-Null
Copy-Item $binary "$staging/watchctl.exe"
Copy-Item "LICENSE" "$staging/LICENSE"
Compress-Archive -Path "$staging/*" -DestinationPath "$dist/$artifact.zip" -Force
Push-Location $dist
$hash = Get-FileHash "$artifact.zip" -Algorithm SHA256
$entry = "{0} {1}" -f $hash.Hash.ToLower(), "$artifact.zip"
Set-Content -Path "$artifact.zip.sha256" -Value $entry -Encoding ASCII
Pop-Location
- name: Upload build artifact (Unix)
if: runner.os != 'Windows'
uses: actions/upload-artifact@v4
with:
name: watchctl-${{ matrix.target }}-${{ matrix.os }}
path: |
dist/watchctl-${{ matrix.target }}-${{ matrix.os }}.tar.gz
dist/watchctl-${{ matrix.target }}-${{ matrix.os }}.tar.gz.sha256
- name: Upload build artifact (Windows)
if: runner.os == 'Windows'
uses: actions/upload-artifact@v4
with:
name: watchctl-${{ matrix.target }}-${{ matrix.os }}
path: |
dist/watchctl-${{ matrix.target }}-${{ matrix.os }}.zip
dist/watchctl-${{ matrix.target }}-${{ matrix.os }}.zip.sha256
release:
needs: build
runs-on: ubuntu-24.04
steps:
- uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Publish release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ github.ref_name }}
GH_REPO: ${{ github.repository }}
run: |
set -euo pipefail
tag="$TAG_NAME"
state="$(gh release view "$tag" --json draft -q '.draft' 2>/dev/null || echo 'not_found')"
publish_after_upload=false
if [[ "$state" == "not_found" ]]; then
gh release create "$tag" --draft --title "Release $tag" --generate-notes
publish_after_upload=true
elif [[ "$state" == "true" ]]; then
publish_after_upload=true
fi
gh release upload "$tag" artifacts/* --clobber
if [[ "$publish_after_upload" == "true" ]]; then
gh release edit "$tag" --draft=false --latest
fi