Skip to content

chore: release v0.41.1 #296

chore: release v0.41.1

chore: release v0.41.1 #296

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Tag to build (e.g., v0.40.1)"
required: true
type: string
target:
description: "Target to build"
required: false
default: all
type: choice
options:
- all
- x86_64-unknown-linux-gnu
- x86_64-apple-darwin
- aarch64-apple-darwin
- x86_64-pc-windows-msvc
permissions:
contents: write
concurrency:
group: release-${{ inputs.tag || github.ref }}
cancel-in-progress: false
env:
CARGO_INCREMENTAL: 0
jobs:
create-release:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
tag: ${{ steps.tag.outputs.value }}
release_id: ${{ steps.create.outputs.id }}
steps:
- name: Resolve tag
id: tag
shell: bash
run: echo "value=${{ inputs.tag || github.ref_name }}" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@v4
with:
ref: ${{ steps.tag.outputs.value }}
fetch-depth: 0
submodules: recursive
- name: Extract release notes
id: notes
shell: bash
env:
RELEASE_TAG: ${{ steps.tag.outputs.value }}
run: |
set -euo pipefail
VERSION="${RELEASE_TAG#v}"
awk -v ver="$VERSION" '
/^## / { if (found) exit; if ($2 == ver) { found=1; next } }
found { print }
' CHANGELOG.md > notes.md || true
if [ ! -s notes.md ]; then
printf 'Release %s\n' "$RELEASE_TAG" > notes.md
fi
delimiter="EOF_notes_$(date +%s)"
{
printf 'content<<%s\n' "$delimiter"
cat notes.md
printf '%s\n' "$delimiter"
} >> "$GITHUB_OUTPUT"
- name: Create draft release
id: create
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.tag.outputs.value }}
name: ${{ steps.tag.outputs.value }}
body: ${{ steps.notes.outputs.content }}
draft: true
prerelease: false
prepare-build:
needs: create-release
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.value }}
required: ${{ steps.matrix.outputs.required }}
steps:
- name: Select build matrix
id: matrix
shell: bash
env:
REQUESTED_TARGET: ${{ inputs.target || 'all' }}
run: |
set -euo pipefail
case "$REQUESTED_TARGET" in
all)
MATRIX='{"include":[{"os":"ubuntu-24.04","target":"x86_64-unknown-linux-gnu","rustTargets":"x86_64-unknown-linux-gnu"},{"os":"macos-15-intel","target":"x86_64-apple-darwin","rustTargets":"aarch64-apple-darwin,x86_64-apple-darwin"},{"os":"macos-latest","target":"aarch64-apple-darwin","rustTargets":"aarch64-apple-darwin,x86_64-apple-darwin"},{"os":"windows-latest","target":"x86_64-pc-windows-msvc","rustTargets":"x86_64-pc-windows-msvc"}]}'
REQUIRED="darwin-aarch64,darwin-x86_64,linux-x86_64,windows-x86_64"
;;
x86_64-unknown-linux-gnu)
MATRIX='{"include":[{"os":"ubuntu-24.04","target":"x86_64-unknown-linux-gnu","rustTargets":"x86_64-unknown-linux-gnu"}]}'
REQUIRED="linux-x86_64"
;;
x86_64-apple-darwin)
MATRIX='{"include":[{"os":"macos-15-intel","target":"x86_64-apple-darwin","rustTargets":"aarch64-apple-darwin,x86_64-apple-darwin"}]}'
REQUIRED="darwin-x86_64"
;;
aarch64-apple-darwin)
MATRIX='{"include":[{"os":"macos-latest","target":"aarch64-apple-darwin","rustTargets":"aarch64-apple-darwin,x86_64-apple-darwin"}]}'
REQUIRED="darwin-aarch64"
;;
x86_64-pc-windows-msvc)
MATRIX='{"include":[{"os":"windows-latest","target":"x86_64-pc-windows-msvc","rustTargets":"x86_64-pc-windows-msvc"}]}'
REQUIRED="windows-x86_64"
;;
*)
echo "Unsupported target: $REQUESTED_TARGET" >&2
exit 1
;;
esac
echo "value=$MATRIX" >> "$GITHUB_OUTPUT"
echo "required=$REQUIRED" >> "$GITHUB_OUTPUT"
build:
needs: [create-release, prepare-build]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare-build.outputs.matrix) }}
runs-on: ${{ matrix.os }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.create-release.outputs.tag }}
fetch-depth: 0
submodules: recursive
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libpipewire-0.3-dev \
libgbm-dev \
libxcb1-dev \
libegl-dev
- name: Import Apple certificate
if: runner.os == 'macOS'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
run: |
set -euo pipefail
KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
KEYCHAIN_PASSWORD="$(openssl rand -base64 32)"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
echo "$APPLE_CERTIFICATE" | base64 --decode > "$RUNNER_TEMP/certificate.p12"
security import "$RUNNER_TEMP/certificate.p12" \
-P "$APPLE_CERTIFICATE_PASSWORD" \
-A -t cert -f pkcs12 \
-k "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
security set-key-partition-list \
-S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security find-identity -v -p codesigning "$KEYCHAIN_PATH"
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.rustTargets }}
- uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri
cache-bin: false
# A release bump updates the root package entry in Cargo.lock, but it
# does not require recompiling the unchanged dependency graph. Keep
# one dependency cache per Rust host and let
# Cargo's fingerprints rebuild only crates whose inputs changed.
shared-key: ataru-release-dependencies
add-rust-environment-hash-key: false
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build Tauri bundles
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
releaseId: ${{ needs.create-release.outputs.release_id }}
includeUpdaterJson: false
args: --target ${{ matrix.target }}
- name: Cleanup keychain
if: runner.os == 'macOS' && always()
run: security delete-keychain "$RUNNER_TEMP/app-signing.keychain-db" || true
finalize-updater:
needs: [create-release, prepare-build, build]
if: needs.build.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ needs.create-release.outputs.tag }}
fetch-depth: 1
- name: Detect signed updater assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ASSET_NAMES=$(gh release view "${{ needs.create-release.outputs.tag }}" --json assets -q '.assets[].name')
printf '%s\n' "$ASSET_NAMES" | grep -qE '\.sig$' || {
echo "Signed Tauri updater assets are required before publishing." >&2
exit 1
}
- name: Generate complete updater manifest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
node scripts/generate-updater-manifest.mjs \
--repo "$GITHUB_REPOSITORY" \
--tag "${{ needs.create-release.outputs.tag }}" \
--require "${{ needs.prepare-build.outputs.required }}"
- name: Upload complete updater manifest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release upload "${{ needs.create-release.outputs.tag }}" latest.json --clobber
publish-release:
needs: [create-release, build, finalize-updater]
if: needs.build.result == 'success' && needs.finalize-updater.result == 'success'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Publish release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release edit "${{ needs.create-release.outputs.tag }}" \
--repo "$GITHUB_REPOSITORY" \
--draft=false \
--latest