vaken 0.1.0

Tiny macOS menu bar utility to keep your Mac awake — Rust wrapper around `caffeinate`.
name: Release

# Tag-driven release: pushing a `vX.Y.Z` tag runs the full CI gate, builds
# the universal `.app`, attaches it to a GitHub Release, and publishes the
# crate to crates.io. No manual release steps.
#
# Prerequisites:
#   - secrets.CARGO_REGISTRY_TOKEN — API token from https://crates.io/me.
#     Shared across all GnomesOfZurich repos via the org-level secret of
#     the same name (matches the convention used by axess + scxml).
#   - GITHUB_TOKEN — provided automatically; needs `contents: write` (set
#     in the permissions block below).

on:
  push:
    tags:
      - "v*.*.*"

permissions:
  contents: write

jobs:
  # Run the same gate CI runs on every push. If anything's red, the
  # tag stops here — no half-published release, no orphan crates.io
  # version.
  verify:
    uses: ./.github/workflows/ci.yml

  build-app:
    name: Build .app
    runs-on: macos-latest
    needs: verify
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - uses: taiki-e/install-action@v2
        with:
          tool: cargo-bundle

      - name: Confirm tag matches Cargo.toml version
        run: |
          tag_version="${GITHUB_REF_NAME#v}"
          cargo_version=$(awk -F'"' '/^version = "/ {print $2; exit}' Cargo.toml)
          if [ "$tag_version" != "$cargo_version" ]; then
            echo "Tag $GITHUB_REF_NAME (parsed: $tag_version) doesn't match Cargo.toml version $cargo_version" >&2
            echo "Bump Cargo.toml + CHANGELOG.md before tagging, or retag." >&2
            exit 1
          fi

      - name: Bundle .app
        run: cargo bundle --release

      - name: Zip the bundle
        # GitHub Releases prefer a single file. Zipping preserves the
        # bundle's directory structure (required for an .app to launch
        # after download).
        run: |
          cd target/release/bundle/osx
          zip -ry Vaken.app.zip Vaken.app
          mv Vaken.app.zip "$GITHUB_WORKSPACE/Vaken-${GITHUB_REF_NAME}.app.zip"

      - name: Upload bundle artifact
        uses: actions/upload-artifact@v4
        with:
          name: vaken-app-bundle
          path: Vaken-${{ github.ref_name }}.app.zip
          if-no-files-found: error

  github-release:
    name: GitHub Release
    runs-on: ubuntu-latest
    needs: build-app
    steps:
      - uses: actions/checkout@v5

      - name: Extract this version's changelog section
        id: changelog
        run: |
          version="${GITHUB_REF_NAME#v}"
          # Slice from the matching heading to the next ## heading (exclusive).
          awk -v ver="$version" '
            $0 ~ "^## \\[" ver "\\]" { p=1; next }
            p && /^## / { exit }
            p { print }
          ' CHANGELOG.md > release-notes.md
          if [ ! -s release-notes.md ]; then
            echo "Could not find CHANGELOG section for $version — release notes will fall back to tag message" >&2
            git tag -l --format='%(contents)' "$GITHUB_REF_NAME" > release-notes.md
          fi

      - uses: actions/download-artifact@v4
        with:
          name: vaken-app-bundle

      - name: Create GitHub Release
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          gh release create "$GITHUB_REF_NAME" \
            --title "$GITHUB_REF_NAME" \
            --notes-file release-notes.md \
            "Vaken-${GITHUB_REF_NAME}.app.zip"

  crates-io:
    name: Publish to crates.io
    runs-on: macos-latest
    needs: github-release
    steps:
      - uses: actions/checkout@v5
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2

      - name: cargo publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish