name: Release
on:
push:
tags:
- 'v*'
env:
CARGO_TERM_COLOR: always
jobs:
publish-crates-io:
name: Publish to crates.io
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: Swatinem/rust-cache@v2
- name: Verify tag matches Cargo.toml version
run: |
set -euxo pipefail
python3 - <<'PY'
import os
import sys
try:
import tomllib # py3.11+
except ModuleNotFoundError:
print("Python 'tomllib' not available. Use a runner with Python 3.11+.", file=sys.stderr)
raise
ref = os.environ.get("GITHUB_REF_NAME", "")
if not ref.startswith("v"):
print(f"Expected tag like vX.Y.Z, got: {ref}", file=sys.stderr)
sys.exit(1)
tag_version = ref.removeprefix("v")
with open("Cargo.toml", "rb") as f:
cargo = tomllib.load(f)
cargo_version = cargo.get("package", {}).get("version", "")
if not cargo_version:
print("Could not read [package].version from Cargo.toml", file=sys.stderr)
sys.exit(1)
if tag_version != cargo_version:
print(f"Tag version ({tag_version}) does not match Cargo.toml version ({cargo_version})", file=sys.stderr)
sys.exit(1)
print(f"Version check OK: tag={tag_version} cargo={cargo_version}")
PY
- name: Publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
set -euxo pipefail
cargo publish --locked
build:
name: Build Release
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build release binary
run: cargo build --release
- name: Create release archive
run: |
cd target/release
tar -czvf synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz synheart-sensor
shasum -a 256 synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz > synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz.sha256
- name: Upload release artifact
uses: actions/upload-artifact@v6
with:
name: release-macos-x86_64
path: |
target/release/synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz
target/release/synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz.sha256
build-arm:
name: Build Release (ARM64)
runs-on: macos-14
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build release binary
run: cargo build --release
- name: Create release archive
run: |
cd target/release
tar -czvf synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz synheart-sensor
shasum -a 256 synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz > synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz.sha256
- name: Upload release artifact
uses: actions/upload-artifact@v6
with:
name: release-macos-arm64
path: |
target/release/synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz
target/release/synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz.sha256
build-windows:
name: Build Release (Windows x86_64)
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Build release binary
run: cargo build --release
- name: Create release archive
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$tag = "${{ github.ref_name }}"
$outDir = "target/release"
$bin = Join-Path $outDir "synheart-sensor.exe"
$zip = Join-Path $outDir ("synheart-sensor-{0}-windows-x86_64.zip" -f $tag)
$sha = "$zip.sha256"
if (!(Test-Path $bin)) {
throw "Expected binary not found: $bin"
}
if (Test-Path $zip) { Remove-Item $zip -Force }
if (Test-Path $sha) { Remove-Item $sha -Force }
Compress-Archive -Path $bin -DestinationPath $zip
$hash = (Get-FileHash -Algorithm SHA256 $zip).Hash.ToLower()
"$hash $(Split-Path -Leaf $zip)" | Out-File -FilePath $sha -Encoding ascii
- name: Upload release artifact
uses: actions/upload-artifact@v6
with:
name: release-windows-x86_64
path: |
target/release/synheart-sensor-${{ github.ref_name }}-windows-x86_64.zip
target/release/synheart-sensor-${{ github.ref_name }}-windows-x86_64.zip.sha256
release:
name: Create Release
needs: [build, build-arm, build-windows]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- name: Download x86_64 artifacts
uses: actions/download-artifact@v7
with:
name: release-macos-x86_64
path: artifacts/
- name: Download ARM64 artifacts
uses: actions/download-artifact@v7
with:
name: release-macos-arm64
path: artifacts/
- name: Download Windows artifacts
uses: actions/download-artifact@v7
with:
name: release-windows-x86_64
path: artifacts/
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
files: |
artifacts/synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz
artifacts/synheart-sensor-${{ github.ref_name }}-macos-x86_64.tar.gz.sha256
artifacts/synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz
artifacts/synheart-sensor-${{ github.ref_name }}-macos-arm64.tar.gz.sha256
artifacts/synheart-sensor-${{ github.ref_name }}-windows-x86_64.zip
artifacts/synheart-sensor-${{ github.ref_name }}-windows-x86_64.zip.sha256
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}