Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dd64ee4
Scaffold match cert delivery for the desktop app
mokagio Jun 10, 2026
61f0f86
Sign and notarize the desktop DMG with Developer ID
mokagio Jun 10, 2026
b51f3f0
Add Buildkite pipeline to build the signed desktop DMG
mokagio Jun 10, 2026
e0ad9c0
Tighten verbose AI comments
mokagio Jun 10, 2026
4f8ad51
Add Buildkite agent and plugin config
mokagio Jun 10, 2026
c58fb2b
Read fastlane team id from electron-builder config
mokagio Jun 10, 2026
07b2f4d
Install composer on the agent before the build
mokagio Jun 10, 2026
cacc933
Install static-php-cli build toolchain on the agent
mokagio Jun 10, 2026
9579a24
Set mac.notarize to a boolean
mokagio Jun 10, 2026
b113fb0
Decode literal newlines when writing the notarization key
mokagio Jun 10, 2026
339a573
Read team id from the signing identity, not notarize
mokagio Jun 10, 2026
6489ee2
Drop the cert-type prefix from mac.identity
mokagio Jun 10, 2026
2d39f8c
Verify the notarized app, not the unsigned dmg
mokagio Jun 10, 2026
706431b
Fail on unexpectedly finding multiple DMGs
mokagio Jun 11, 2026
3c83d78
Fail if team ID cannot be computed from JSON
mokagio Jun 11, 2026
b5bf5d2
Accept plain semver release tags
mokagio Jun 12, 2026
a369ef1
Require plain semver release tags
mokagio Jun 12, 2026
3c8e19c
Delete GHA workflow for macOS DMG release — Use Buildkite only
mokagio Jun 16, 2026
5cc6c74
Remove dead desktop release workflow call
mokagio Jun 16, 2026
8a592d4
Document Buildkite desktop release ownership
mokagio Jun 16, 2026
b5aa997
Fix desktop release install note
mokagio Jun 16, 2026
bc118e7
Merge remote-tracking branch 'origin/main' into mokagio/desktop-code-…
priethor Jun 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions .buildkite/commands/release-desktop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env bash

set -euo pipefail

# Build, sign, and notarize the Cortext desktop DMG.

# Release tag builds publish to the GitHub Release.
if [[ "${BUILDKITE_TAG:-}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
version="$BUILDKITE_TAG"
publish=true
else
base_version="$(python3 -c 'import json; print(json.load(open("apps/desktop/package.json"))["version"])')"
version="${base_version}-${BUILDKITE_COMMIT:0:7}"
publish=false
fi

echo "--- :package: install JS + PHP dependencies"
corepack enable
corepack prepare "pnpm@$(node -p "require('./package.json').packageManager.split('@')[1]")" --activate
# The xcode-* agent image ships no composer; brew pulls php in as a dependency.
command -v composer >/dev/null || brew install composer
composer install --no-dev --optimize-autoloader --no-interaction
pnpm install --frozen-lockfile
npm --prefix apps/desktop ci

# Electron 42 skips the binary download during `npm ci`; fetch it so
# electron-builder packages a complete app.
( cd apps/desktop && npx install-electron )

echo "--- :hammer_and_wrench: install static-php-cli build toolchain"
# static-php-cli source-builds any library without a pre-built binary (e.g.
# libxml2), which the minimal agent image can't do unaided.
brew install cmake autoconf automake libtool bison re2c
export PATH="$(brew --prefix bison)/bin:$PATH"

echo "--- :php: build bundled arm64 PHP runtime"
npm --prefix apps/desktop run runtime:php

echo "--- :card_index_dividers: build distribution snapshot"
CORTEXT_DESKTOP_DISTRIBUTION=1 npm --prefix apps/desktop run snapshot

echo "--- :key: install Developer ID cert into the agent keychain"
( cd apps/desktop && install_gems && bundle exec fastlane set_up_signing )

echo "--- :apple: build, sign, notarize DMG"
# electron-builder signs from the match-installed keychain cert (mac.identity)
# and notarizes via its built-in @electron/notarize, driven by APPLE_API_*.
# APPLE_API_KEY must be a path to the .p8, so materialize the key the agent
# carries as APP_STORE_CONNECT_API_KEY_KEY into a temp file.
apple_api_key_path="$(mktemp -t cortext_asc).p8"
trap 'rm -f "$apple_api_key_path"' EXIT
# The secret stores the .p8 with newlines as literal \n; %b turns them back into
# real newlines so the file is a valid PEM (a no-op if they are already real).
printf '%b' "$APP_STORE_CONNECT_API_KEY_KEY" > "$apple_api_key_path"
export APPLE_API_KEY="$apple_api_key_path"
export APPLE_API_KEY_ID="$APP_STORE_CONNECT_API_KEY_KEY_ID"
export APPLE_API_ISSUER="$APP_STORE_CONNECT_API_KEY_ISSUER_ID"
Comment on lines +46 to +57

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be hidden away in CI toolkit if it proves a pattern used by other apps.

I considered adding the env vars directly in CI, but I think it's cleaner to have only the APP_STORE_CONNECT_API_KEY_ definitions there.


npm --prefix apps/desktop run dist -- -c.extraMetadata.version="$version"

echo "--- :white_check_mark: verify signature + notarization"
dmg=(apps/desktop/dist/*.dmg)
[[ ${#dmg[@]} -eq 1 ]] || { echo "Expected exactly one DMG, found ${#dmg[@]}"; exit 1; }
dmg="${dmg[0]}"
# electron-builder signs, notarizes and staples the .app, then wraps it in an
# unsigned .dmg — so the notarized artifact to verify is the app, not the dmg.
app="apps/desktop/dist/mac-arm64/Cortext.app"
codesign --verify --strict --deep --verbose=2 "$app"
spctl --assess --type exec --verbose=2 "$app"
xcrun stapler validate "$app"

if ! "$publish"; then
echo "--- :information_source: no release tag; signed DMG stashed as a Buildkite artifact"
exit 0
fi

echo "--- :rocket: attach DMG to draft GitHub Release"
if ! gh release view "$version" --repo Automattic/cortext >/dev/null 2>&1; then
gh release create "$version" \
--repo Automattic/cortext \
--draft \
--title "Cortext $version" \
--notes "Cortext $version"
fi
gh release upload "$version" "$dmg" --repo Automattic/cortext --clobber
20 changes: 20 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/buildkite/pipeline-schema/main/schema.json
---

agents:
queue: mac

env:
IMAGE_ID: $IMAGE_ID

steps:
- label: ":apple: Build, sign, notarize desktop DMG"
key: release-desktop
command: .buildkite/commands/release-desktop.sh
plugins: [$CI_TOOLKIT_PLUGIN, $NVM_PLUGIN]
Comment thread
priethor marked this conversation as resolved.
artifact_paths:
- "apps/desktop/dist/*.dmg"
- "apps/desktop/dist/*.dmg.blockmap"
notify:
- github_commit_status:
context: Build, Sign & Notarize Desktop
11 changes: 11 additions & 0 deletions .buildkite/shared-pipeline-vars
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh

# Sourced by the pipeline-upload step so these values land in the rendered pipeline.yml.

CI_TOOLKIT_PLUGIN_VERSION='6.0.1'
NVM_PLUGIN_VERSION='0.6.0'
XCODE_VERSION=$(sed -E 's/^~> ?//' .xcode-version)

export IMAGE_ID="xcode-$XCODE_VERSION"
export CI_TOOLKIT_PLUGIN="automattic/a8c-ci-toolkit#$CI_TOOLKIT_PLUGIN_VERSION"
export NVM_PLUGIN="automattic/nvm#$NVM_PLUGIN_VERSION"
151 changes: 0 additions & 151 deletions .github/workflows/release-desktop.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/release-plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ jobs:
run: |
cat >> release-notes.md <<'EOF'

## Opening the macOS app
## Installing the macOS app

This DMG is unsigned, so macOS may show a "Cortext is damaged" warning the first time you open it. Move Cortext to Applications. If that warning appears, click Cancel, open Terminal, and run `xattr -dr com.apple.quarantine /Applications/Cortext.app && open /Applications/Cortext.app`.
The macOS DMG is signed and notarized. Move Cortext to Applications before opening it.
EOF

- name: Build plugin ZIP
Expand Down
17 changes: 3 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ concurrency:
group: cortext-release-${{ inputs.milestone }}
cancel-in-progress: true

# Orchestrator: builds the plugin ZIP and the desktop DMG and lets each attach
# to the same tagged Release. Either child can also be run on its own from the
# Actions tab; the first run creates the draft Release, later runs attach to it.
# GitHub Actions prepares the plugin ZIP and draft Release. Buildkite owns the
# signed desktop DMG and attaches it from the release tag build.
jobs:
bump-version:
name: Bump release version
Expand Down Expand Up @@ -134,19 +133,9 @@ jobs:
ref: ${{ needs.bump-version.outputs.ref }}
secrets: inherit

desktop:
needs: bump-version
uses: ./.github/workflows/release-desktop.yml
with:
version: ${{ needs.bump-version.outputs.version }}
prerelease: ${{ inputs.prerelease }}
dry_run: ${{ inputs.dry_run }}
ref: ${{ needs.bump-version.outputs.ref }}
secrets: inherit

finalize-milestone:
name: Finalize release milestone
needs: [bump-version, plugin, desktop]
needs: [bump-version, plugin]
if: ${{ ! inputs.dry_run }}
runs-on: ubuntu-latest
steps:
Expand Down
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24.15
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.4
1 change: 1 addition & 0 deletions .xcode-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
26.3
4 changes: 4 additions & 0 deletions apps/desktop/.bundle/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_SPECIFIC_PLATFORM: "false"
BUNDLE_FORCE_RUBY_PLATFORM: "true"
6 changes: 6 additions & 0 deletions apps/desktop/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

source 'https://rubygems.org'

gem 'fastlane', '~> 2.236'
gem 'fastlane-plugin-wpmreleasetoolkit', '~> 14.6'
Loading