blob: 3a79b15b3380b9f419ed85ed1182fcb382b2c7cd [file]
name: Release desktop
on:
workflow_dispatch:
permissions:
contents: write
concurrency:
group: release-desktop
cancel-in-progress: false
jobs:
build:
if: github.ref == 'refs/heads/main'
strategy:
# Both platforms ship from one dispatch, so a failure on one still leaves
# the other artifact available for diagnosis.
fail-fast: false
matrix:
include:
- platform: macos
runner: macos-15
- platform: windows
runner: windows-2025
runs-on: ${{ matrix.runner }}
environment: release
timeout-minutes: 45
defaults:
run:
# Windows runners default to pwsh; the release steps are written once,
# in bash, for both platforms.
shell: bash
steps:
- name: Check out the dispatched commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Install dependencies
run: npm ci
- name: Audit production dependencies
run: npm audit --omit=dev --audit-level=moderate
- name: Write App Store Connect API key
if: matrix.platform == 'macos'
env:
APPLE_API_KEY_CONTENT: ${{ secrets.APPLE_API_KEY }}
APPLE_API_KEY_PATH: ${{ runner.temp }}/AuthKey_Maka.p8
run: |
umask 077
printf '%s' "$APPLE_API_KEY_CONTENT" > "$APPLE_API_KEY_PATH"
- name: Resolve and reserve release identity
id: release
env:
GH_TOKEN: ${{ github.token }}
run: |
version="$(node -p "require('./apps/desktop/package.json').version")"
tag="v${version}"
dmg="apps/desktop/release/Maka-${version}-mac-arm64.dmg"
exe="apps/desktop/release/Maka-${version}-win-x64.exe"
if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
echo "Tag ${tag} already exists." >&2
exit 1
fi
if gh release view "$tag" >/dev/null 2>&1; then
echo "Release ${tag} already exists." >&2
exit 1
fi
{
echo "version=${version}"
echo "tag=${tag}"
echo "dmg=${dmg}"
echo "exe=${exe}"
} >> "$GITHUB_OUTPUT"
- name: Package notarized app and signed DMG
if: matrix.platform == 'macos'
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
APPLE_API_KEY: ${{ runner.temp }}/AuthKey_Maka.p8
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
run: npm run package:macos-arm64
- name: Notarize and staple the signed final DMG
if: matrix.platform == 'macos'
env:
APPLE_API_KEY: ${{ runner.temp }}/AuthKey_Maka.p8
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }}
DMG_PATH: ${{ steps.release.outputs.dmg }}
run: |
codesign --verify --verbose=4 "$DMG_PATH"
xcrun notarytool submit "$DMG_PATH" \
--key "$APPLE_API_KEY" \
--key-id "$APPLE_API_KEY_ID" \
--issuer "$APPLE_API_ISSUER" \
--wait
xcrun stapler staple "$DMG_PATH"
codesign --verify --verbose=4 "$DMG_PATH"
xcrun stapler validate "$DMG_PATH"
spctl --assess \
--type open \
--context context:primary-signature \
--verbose=4 \
"$DMG_PATH"
- name: Verify the final DMG
if: matrix.platform == 'macos'
run: npm run verify:macos-arm64 -- "${{ steps.release.outputs.dmg }}"
# Windows has no Authenticode certificate yet, so this build is unsigned
# and there is nothing to notarize between packaging and verification.
- name: Package the Windows installer and ZIP
if: matrix.platform == 'windows'
run: npm run package:windows-x64
- name: Verify the Windows release
if: matrix.platform == 'windows'
run: npm run verify:windows-x64 -- "${{ steps.release.outputs.exe }}"
- name: Upload the verified release assets
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-${{ matrix.platform }}
path: |
apps/desktop/release/Maka-*
apps/desktop/release/latest*.yml
if-no-files-found: error
retention-days: 7
- name: Remove temporary release credentials
if: always() && matrix.platform == 'macos'
run: rm -f "${{ runner.temp }}/AuthKey_Maka.p8"
source:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
timeout-minutes: 20
defaults:
run:
shell: bash
steps:
- name: Check out the dispatched commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- name: Install pinned dependency metadata
run: npm ci --ignore-scripts
- name: Materialize bundled Git source materials
run: npm run prepare:bundled-git-source
- name: Archive and hash source materials
run: |
version="$(node -p "require('./apps/desktop/package.json').version")"
archive_dir="apps/desktop/release-sources"
archive_name="Maka-${version}-bundled-git-source.tar.gz"
archive="${archive_dir}/${archive_name}"
tar -C apps/desktop/release-sources/bundled-git -czf "$archive" .
(cd "$archive_dir" && sha256sum "$archive_name" > "${archive_name}.sha256")
- name: Upload verified source assets
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-source
path: |
apps/desktop/release-sources/Maka-*-bundled-git-source.tar.gz
apps/desktop/release-sources/Maka-*-bundled-git-source.tar.gz.sha256
if-no-files-found: error
retention-days: 7
publish:
# One draft release carries both platforms, so it is created once, after
# every platform has been packaged and verified.
needs: [build, source]
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
shell: bash
steps:
- name: Check out the dispatched commit
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.sha }}
persist-credentials: false
- name: Download the verified release assets
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: release-*
path: release-assets
merge-multiple: true
- name: Create draft GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
version="$(node -p "require('./apps/desktop/package.json').version")"
tag="v${version}"
notes="Apple Silicon macOS and Windows x64 release built from commit ${GITHUB_SHA}.
Before publishing, download these draft assets on another Apple Silicon Mac and on a Windows x64 machine, and complete .github/RELEASE_CHECKLIST.md.
The Windows build is unsigned: SmartScreen warns on first launch, and the download has to be checked against its .sha256 file.
Bundled Git source materials and their checksum are attached to this draft. The packaged applications also carry the GPLv2 license and written source offer.
Known limitation: Computer Use is not included in this release."
gh release create "$tag" release-assets/* \
--draft \
--target "$GITHUB_SHA" \
--title "Maka ${version}" \
--notes "$notes"
echo "Draft release ${tag} created from ${GITHUB_SHA}." >> "$GITHUB_STEP_SUMMARY"