Skip to content

Release 0.6.1

Release 0.6.1 #59

Workflow file for this run

name: Release
on:
push:
branches:
- main
tags:
- "v*"
workflow_dispatch:
permissions:
actions: write
contents: write
id-token: write
jobs:
validate-release-version:
name: Validate Tag and Cargo Version
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Verify Cargo.lock is tracked
run: git ls-files --error-unmatch Cargo.lock >/dev/null
- name: Ensure tag matches Cargo.toml version
if: startsWith(github.ref, 'refs/tags/v')
env:
TAG: ${{ github.ref_name }}
run: |
TAG_VERSION="${TAG#v}"
CARGO_VERSION="$(awk -F '"' '/^version = / {print $2; exit}' Cargo.toml)"
if [ -z "$CARGO_VERSION" ]; then
echo "Could not read package version from Cargo.toml" >&2
exit 1
fi
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "Tag version ($TAG_VERSION) does not match Cargo.toml version ($CARGO_VERSION)." >&2
echo "Bump Cargo.toml, run cargo check, commit Cargo.lock, then retag." >&2
exit 1
fi
build-release-macos:
name: Build release assets (darwin-arm64)
runs-on: macos-14
needs: validate-release-version
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: web/package-lock.json
- name: Install frontend dependencies
run: |
cd web
npm ci
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin
- name: Cache Rust
uses: Swatinem/rust-cache@v2
with:
shared-key: release-darwin-arm64
key: aarch64-apple-darwin
- name: Install cargo-bundle
uses: taiki-e/cache-cargo-install-action@v2
with:
tool: cargo-bundle
- name: Build app bundle
env:
ATTN_DEFAULT_RELAY_URL: https://relay.attn.sh
run: |
scripts/macos-build-bundle.sh prod aarch64-apple-darwin
APP_PATH="$(find target/aarch64-apple-darwin -path '*/bundle/osx/*.app' -maxdepth 6 | head -n1)"
if [ -z "$APP_PATH" ]; then
echo "No app bundle found" >&2
exit 1
fi
DMG_PATH="$(dirname "$APP_PATH")/attn.dmg"
echo "APP_PATH=$APP_PATH" >> "$GITHUB_ENV"
echo "DMG_PATH=$DMG_PATH" >> "$GITHUB_ENV"
- name: Prepare binary assets
if: startsWith(github.ref, 'refs/tags/v')
env:
TAG: ${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || format('vdev-{0}', github.run_number) }}
run: |
VERSION="${TAG#v}"
mkdir -p dist
cp "target/aarch64-apple-darwin/release/attn" "dist/attn-v${VERSION}-darwin-arm64"
chmod +x "dist/attn-v${VERSION}-darwin-arm64"
shasum -a 256 "dist/attn-v${VERSION}-darwin-arm64" > "dist/attn-v${VERSION}-darwin-arm64.sha256"
- name: Import code signing certificate
if: startsWith(github.ref, 'refs/tags/v')
id: signing
env:
CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE }}
CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
CERTIFICATE_PATH="$RUNNER_TEMP/build_certificate.p12"
KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
if [ -z "$CERTIFICATE_BASE64" ] || [ -z "$CERTIFICATE_PASSWORD" ] || [ -z "$KEYCHAIN_PASSWORD" ]; then
echo "Missing required signing secrets." >&2
exit 1
fi
echo -n "$CERTIFICATE_BASE64" | base64 --decode > "$CERTIFICATE_PATH" || \
echo -n "$CERTIFICATE_BASE64" | base64 -D > "$CERTIFICATE_PATH"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security import "$CERTIFICATE_PATH" -P "$CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> "$GITHUB_ENV"
- name: Sign app bundle
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: scripts/macos-sign-app.sh "$APP_PATH" "$APPLE_SIGNING_IDENTITY"
- name: Prepare app zip assets
if: startsWith(github.ref, 'refs/tags/v')
env:
TAG: ${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || format('vdev-{0}', github.run_number) }}
run: |
VERSION="${TAG#v}"
APP_DIR="$(dirname "$APP_PATH")"
APP_NAME="$(basename "$APP_PATH")"
ZIP_NAME="attn-v${VERSION}-darwin-arm64.app.zip"
cd "$APP_DIR"
ditto -c -k --sequesterRsrc --keepParent "$APP_NAME" "$ZIP_NAME"
mv "$ZIP_NAME" "$GITHUB_WORKSPACE/dist/$ZIP_NAME"
shasum -a 256 "$GITHUB_WORKSPACE/dist/$ZIP_NAME" > "$GITHUB_WORKSPACE/dist/$ZIP_NAME.sha256"
- name: Create DMG
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: scripts/macos-create-dmg.sh "$APP_PATH" "$DMG_PATH"
- name: Notarize DMG
if: startsWith(github.ref, 'refs/tags/v')
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: scripts/macos-notarize-dmg.sh "$DMG_PATH"
- name: Prepare DMG assets
if: startsWith(github.ref, 'refs/tags/v')
env:
TAG: ${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || format('vdev-{0}', github.run_number) }}
run: |
VERSION="${TAG#v}"
cp "$DMG_PATH" "dist/attn-v${VERSION}-darwin-arm64.dmg"
shasum -a 256 "dist/attn-v${VERSION}-darwin-arm64.dmg" > "dist/attn-v${VERSION}-darwin-arm64.dmg.sha256"
- name: Upload release artifacts
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-artifact@v4
with:
name: release-darwin-arm64
path: dist/*
retention-days: 7
- name: Cleanup keychain
if: always()
run: |
if [ -n "${KEYCHAIN_PATH:-}" ] && [ -f "$KEYCHAIN_PATH" ]; then
security delete-keychain "$KEYCHAIN_PATH"
fi
build-release-linux:
name: Build release assets (linux-x64)
runs-on: ubuntu-latest
needs: validate-release-version
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: web/package-lock.json
- name: Install frontend dependencies
run: |
cd web
npm ci
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-gnu
- name: Cache Rust
uses: Swatinem/rust-cache@v2
with:
shared-key: release-linux-x64
key: x86_64-unknown-linux-gnu
- name: Build release binary
env:
ATTN_DEFAULT_RELAY_URL: https://relay.attn.sh
run: cargo build --release --target x86_64-unknown-linux-gnu
- name: Prepare binary assets
if: startsWith(github.ref, 'refs/tags/v')
env:
TAG: ${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || format('vdev-{0}', github.run_number) }}
run: |
VERSION="${TAG#v}"
mkdir -p dist
cp "target/x86_64-unknown-linux-gnu/release/attn" "dist/attn-v${VERSION}-linux-x64"
chmod +x "dist/attn-v${VERSION}-linux-x64"
sha256sum "dist/attn-v${VERSION}-linux-x64" > "dist/attn-v${VERSION}-linux-x64.sha256"
- name: Upload release artifacts
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/upload-artifact@v4
with:
name: release-linux-x64
path: dist/*
retention-days: 7
publish-release:
name: Publish GitHub Release
runs-on: ubuntu-latest
needs: [build-release-macos, build-release-linux]
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Download macOS artifacts
uses: actions/download-artifact@v4
with:
path: dist
name: release-darwin-arm64
- name: Download Linux artifacts
uses: actions/download-artifact@v4
with:
path: dist
name: release-linux-x64
- name: Create or update release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
run: |
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG already exists; uploading updated assets."
else
gh release create "$TAG" \
--title "$TAG" \
--notes "Automated release for $TAG."
fi
gh release upload "$TAG" dist/* --clobber
# NOTE: no crates.io publish. `cargo install attn` is intentionally NOT a
# supported install path — attn is a wry/GTK desktop GUI (not a clean
# cargo-installable CLI) and the generic `attn` crate name isn't ours.
# Supported paths: Homebrew (cask/formula) + npx attnmd + the DMG.
publish-npm:
name: Publish npm package
runs-on: ubuntu-latest
needs: publish-release
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
- name: Publish package
run: npm publish --access public --provenance
update-homebrew:
name: Update Homebrew tap
runs-on: ubuntu-latest
needs: publish-release
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Update tap formula
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
VERSION="${GITHUB_REF_NAME#v}"
./homebrew/update-tap.sh "$VERSION"