Skip to content

chore: bump version to 0.6.0 and prepare release notes (#116) #12

chore: bump version to 0.6.0 and prepare release notes (#116)

chore: bump version to 0.6.0 and prepare release notes (#116) #12

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
build-and-release:
name: Build & Release
runs-on: macos-15
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Initialize Xcode tools
run: sudo xcodebuild -runFirstLaunch
# ── Code Signing Setup ──────────────────────────────────────────────────
- name: Import Developer ID certificate
env:
DEVELOPER_ID_CERT_P12: ${{ secrets.DEVELOPER_ID_CERT_P12 }}
DEVELOPER_ID_CERT_PASSWORD: ${{ secrets.DEVELOPER_ID_CERT_PASSWORD }}
run: |
# Create a temporary keychain so the cert is isolated to this job
KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain"
KEYCHAIN_PASSWORD="$(openssl rand -hex 16)"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
# Decode and import the p12
echo "$DEVELOPER_ID_CERT_P12" | base64 --decode > "$RUNNER_TEMP/cert.p12"
security import "$RUNNER_TEMP/cert.p12" \
-k "$KEYCHAIN_PATH" \
-P "$DEVELOPER_ID_CERT_PASSWORD" \
-T /usr/bin/codesign \
-T /usr/bin/security
# Allow codesign to access the key without a passphrase prompt
security set-key-partition-list \
-S apple-tool:,apple:,codesign: \
-s -k "$KEYCHAIN_PASSWORD" \
"$KEYCHAIN_PATH"
# Add to keychain search list
security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | xargs)
# Store the keychain path for later steps
echo "KEYCHAIN_PATH=$KEYCHAIN_PATH" >> "$GITHUB_ENV"
echo "KEYCHAIN_PASSWORD=$KEYCHAIN_PASSWORD" >> "$GITHUB_ENV"
# Verify the identity
IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" \
| grep "Developer ID Application" | head -1 | sed 's/.*"\(.*\)"/\1/')
if [ -z "$IDENTITY" ]; then
echo "❌ Developer ID certificate not found after import"
exit 1
fi
echo "✅ Imported: $IDENTITY"
echo "CODE_SIGN_IDENTITY=$IDENTITY" >> "$GITHUB_ENV"
- name: Store notarization credentials
env:
NOTARIZE_APPLE_ID: ${{ secrets.NOTARIZE_APPLE_ID }}
NOTARIZE_TEAM_ID: ${{ secrets.NOTARIZE_TEAM_ID }}
NOTARIZE_PASSWORD: ${{ secrets.NOTARIZE_PASSWORD }}
run: |
xcrun notarytool store-credentials "AC_PASSWORD" \
--apple-id "$NOTARIZE_APPLE_ID" \
--team-id "$NOTARIZE_TEAM_ID" \
--password "$NOTARIZE_PASSWORD"
# ── Bundled Tiny Model ─────────────────────────────────────────────────
- name: Set up Python for huggingface-cli
run: |
python3 -m venv "$RUNNER_TEMP/hf-venv"
source "$RUNNER_TEMP/hf-venv/bin/activate"
pip install -U huggingface_hub
echo "$RUNNER_TEMP/hf-venv/bin" >> "$GITHUB_PATH"
- name: Fetch bundled tiny model from Hugging Face
run: |
MODEL_STAGE="$RUNNER_TEMP/whisperkit-coreml"
hf download argmaxinc/whisperkit-coreml \
--include "openai_whisper-tiny/*" \
--local-dir "$MODEL_STAGE"
hf download openai/whisper-tiny \
tokenizer.json tokenizer_config.json \
--local-dir "$MODEL_STAGE/openai_whisper-tiny"
rm -rf "$MODEL_STAGE/.cache" "$MODEL_STAGE/openai_whisper-tiny/.cache"
test -d "$MODEL_STAGE/openai_whisper-tiny"
test -f "$MODEL_STAGE/openai_whisper-tiny/tokenizer.json"
test -f "$MODEL_STAGE/openai_whisper-tiny/tokenizer_config.json"
test -d "$MODEL_STAGE/openai_whisper-tiny/MelSpectrogram.mlmodelc"
test -d "$MODEL_STAGE/openai_whisper-tiny/AudioEncoder.mlmodelc"
test -d "$MODEL_STAGE/openai_whisper-tiny/TextDecoder.mlmodelc"
echo "VOCAMAC_BUNDLED_MODEL_SOURCE=$MODEL_STAGE" >> "$GITHUB_ENV"
# ── Build & Package ──────────────────────────────────────────────────────
- name: Run tests
run: swift test
- name: Build and create signed, notarized DMG
run: ./scripts/dist.sh
env:
VOCAMAC_BUNDLED_MODEL_SOURCE: ${{ env.VOCAMAC_BUNDLED_MODEL_SOURCE }}
- name: Verify code signature
run: codesign -v --deep --strict VocaMac.app
- name: Rename artifacts with version
run: |
ARCH=$(uname -m)
# dist.sh already names the DMG correctly; verify it exists
ls -lh dist/VocaMac-*.dmg
# Create ZIP from the signed .app
ditto -c -k --sequesterRsrc --keepParent VocaMac.app \
"dist/VocaMac-${{ steps.version.outputs.VERSION }}-${ARCH}.zip"
echo "ZIP created:"
ls -lh dist/VocaMac-*.zip
- name: Generate checksums
run: |
cd dist
shasum -a 256 VocaMac-*.dmg VocaMac-*.zip > checksums.txt
cat checksums.txt
# ── Cleanup ─────────────────────────────────────────────────────────────
- name: Delete temporary keychain
if: always()
run: |
security delete-keychain "$KEYCHAIN_PATH" 2>/dev/null || true
# ── Release ─────────────────────────────────────────────────────────────
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
draft: true
files: |
dist/VocaMac-*.dmg
dist/VocaMac-*.zip
dist/checksums.txt
body: |
## VocaMac ${{ steps.version.outputs.VERSION }}
### Installation
1. Download `VocaMac-${{ steps.version.outputs.VERSION }}-arm64.dmg`
2. Open the DMG and drag VocaMac to Applications
3. Open VocaMac from Applications
4. Grant **Microphone**, **Accessibility**, and **Input Monitoring** permissions when prompted
> This release is **Developer ID signed and notarized** by Apple.
> macOS will open it without any security warnings.
### Requirements
- macOS 13 (Ventura) or later
- Apple Silicon (arm64)
### Checksums (SHA-256)
See `checksums.txt` for verification.