Skip to content

Commit d1d59db

Browse files
committed
fix(release): notarize mac desktop artifacts
1 parent db92a38 commit d1d59db

3 files changed

Lines changed: 59 additions & 36 deletions

File tree

.github/workflows/electron-ci.yml

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,12 @@ jobs:
6868

6969
- name: Prepare macOS code signing
7070
id: mac-signing
71-
if: ${{ matrix.platform == 'macos-latest' && github.event_name != 'pull_request' && env.APPLE_CERTIFICATE != '' && env.APPLE_CERTIFICATE_PASSWORD != '' }}
71+
if: ${{ startsWith(matrix.platform, 'macos-') && github.event_name != 'pull_request' && env.APPLE_CERTIFICATE != '' && env.APPLE_CERTIFICATE_PASSWORD != '' }}
7272
shell: bash
7373
run: |
7474
set -euo pipefail
7575
CSC_PATH="$RUNNER_TEMP/certificate.p12"
76-
python3 - <<'EOF'
77-
import base64
78-
import os
79-
from pathlib import Path
80-
81-
target = Path(os.environ["RUNNER_TEMP"]) / "certificate.p12"
82-
target.write_bytes(base64.b64decode(os.environ["APPLE_CERTIFICATE"]))
83-
EOF
76+
printf '%s' "$APPLE_CERTIFICATE" | base64 --decode > "$CSC_PATH"
8477
echo "CSC_LINK=$CSC_PATH" >> "$GITHUB_ENV"
8578
echo "CSC_KEY_PASSWORD=$APPLE_CERTIFICATE_PASSWORD" >> "$GITHUB_ENV"
8679
echo "has_cert=true" >> "$GITHUB_OUTPUT"
@@ -91,7 +84,7 @@ jobs:
9184
run: pnpm --filter @memohai/desktop build:dir
9285

9386
- name: Verify macOS signature
94-
if: ${{ matrix.platform == 'macos-latest' && steps.mac-signing.outputs.has_cert == 'true' }}
87+
if: ${{ startsWith(matrix.platform, 'macos-') && steps.mac-signing.outputs.has_cert == 'true' }}
9588
shell: bash
9689
run: |
9790
set -euo pipefail

.github/workflows/release.yml

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ jobs:
4545
name: Publish npm packages
4646
runs-on: ubuntu-latest
4747
timeout-minutes: 15
48+
if: github.event_name == 'push'
4849
steps:
4950
- uses: actions/checkout@v4
5051
- name: Sync workspace versions
@@ -91,7 +92,7 @@ jobs:
9192
desktop-build:
9293
name: Build desktop (${{ matrix.platform }})
9394
runs-on: ${{ matrix.platform }}
94-
timeout-minutes: 60
95+
timeout-minutes: 120
9596
strategy:
9697
fail-fast: false
9798
matrix:
@@ -135,26 +136,27 @@ jobs:
135136
- name: Install JS dependencies
136137
run: pnpm install --frozen-lockfile
137138
- name: Require macOS code signing secrets
138-
if: ${{ matrix.platform == 'macos-latest' && (env.APPLE_CERTIFICATE == '' || env.APPLE_CERTIFICATE_PASSWORD == '') }}
139+
if: ${{ startsWith(matrix.platform, 'macos-') }}
139140
shell: bash
140141
run: |
141-
echo "APPLE_CERTIFICATE and APPLE_CERTIFICATE_PASSWORD are required for signed macOS desktop releases." >&2
142-
exit 1
142+
set -euo pipefail
143+
missing=()
144+
[[ -n "${APPLE_CERTIFICATE:-}" ]] || missing+=("APPLE_CERTIFICATE")
145+
[[ -n "${APPLE_CERTIFICATE_PASSWORD:-}" ]] || missing+=("APPLE_CERTIFICATE_PASSWORD")
146+
147+
if (( ${#missing[@]} > 0 )); then
148+
printf 'Missing required macOS release secret(s):\n' >&2
149+
printf ' - %s\n' "${missing[@]}" >&2
150+
exit 1
151+
fi
143152
- name: Prepare macOS code signing
144153
id: mac-signing
145-
if: ${{ matrix.platform == 'macos-latest' && env.APPLE_CERTIFICATE != '' && env.APPLE_CERTIFICATE_PASSWORD != '' }}
154+
if: ${{ startsWith(matrix.platform, 'macos-') }}
146155
shell: bash
147156
run: |
148157
set -euo pipefail
149158
CSC_PATH="$RUNNER_TEMP/certificate.p12"
150-
python3 - <<'EOF'
151-
import base64
152-
import os
153-
from pathlib import Path
154-
155-
target = Path(os.environ["RUNNER_TEMP"]) / "certificate.p12"
156-
target.write_bytes(base64.b64decode(os.environ["APPLE_CERTIFICATE"]))
157-
EOF
159+
printf '%s' "$APPLE_CERTIFICATE" | base64 --decode > "$CSC_PATH"
158160
echo "CSC_LINK=$CSC_PATH" >> "$GITHUB_ENV"
159161
echo "CSC_KEY_PASSWORD=$APPLE_CERTIFICATE_PASSWORD" >> "$GITHUB_ENV"
160162
echo "has_cert=true" >> "$GITHUB_OUTPUT"
@@ -164,18 +166,51 @@ jobs:
164166
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
165167
CSC_IDENTITY_AUTO_DISCOVERY: ${{ steps.mac-signing.outputs.has_cert == 'true' && 'true' || 'false' }}
166168
run: pnpm --filter @memohai/desktop ${{ matrix.build_cmd }}
167-
- name: Verify macOS signature
168-
if: ${{ matrix.platform == 'macos-latest' && steps.mac-signing.outputs.has_cert == 'true' }}
169+
- name: Verify macOS bundles
170+
if: ${{ startsWith(matrix.platform, 'macos-') && steps.mac-signing.outputs.has_cert == 'true' }}
169171
shell: bash
170172
run: |
171173
set -euo pipefail
172-
app_path="$(find apps/desktop/dist -name 'Memoh.app' -type d | head -n 1)"
173-
if [[ -z "$app_path" ]]; then
174-
echo "Memoh.app not found in apps/desktop/dist" >&2
174+
175+
declare -a bundles=(
176+
"arm64:darwin-arm64:apps/desktop/dist/mac-arm64/Memoh.app"
177+
"x64:darwin-x64:apps/desktop/dist/mac/Memoh.app"
178+
)
179+
180+
for bundle in "${bundles[@]}"; do
181+
IFS=: read -r arch qdrant_target app_path <<<"$bundle"
182+
183+
if [[ ! -d "$app_path" ]]; then
184+
echo "Missing $arch app bundle: $app_path" >&2
185+
exit 1
186+
fi
187+
188+
qdrant_root="$app_path/Contents/Resources/qdrant"
189+
qdrant_bin="$qdrant_root/$qdrant_target/qdrant"
190+
if [[ ! -x "$qdrant_bin" ]]; then
191+
echo "Missing $arch qdrant binary: $qdrant_bin" >&2
192+
find "$qdrant_root" -maxdepth 3 -type f -print || true
193+
exit 1
194+
fi
195+
196+
extra_qdrant_dirs="$(find "$qdrant_root" -mindepth 1 -maxdepth 1 -type d ! -name "$qdrant_target" -print -quit)"
197+
if [[ -n "$extra_qdrant_dirs" ]]; then
198+
echo "Unexpected qdrant resource in $arch app: $extra_qdrant_dirs" >&2
199+
find "$qdrant_root" -mindepth 1 -maxdepth 1 -type d -print
200+
exit 1
201+
fi
202+
203+
codesign --verify --deep --strict --verbose=2 "$app_path"
204+
codesign -dv --verbose=4 "$app_path" 2>&1 | grep -F "Developer ID Application"
205+
done
206+
207+
shopt -s nullglob
208+
dmg_artifacts=(apps/desktop/dist/Memoh-Desktop-*-mac-arm64.dmg apps/desktop/dist/Memoh-Desktop-*-mac-x64.dmg)
209+
if (( ${#dmg_artifacts[@]} != 2 )); then
210+
echo "Expected mac arm64/x64 dmg artifacts." >&2
211+
ls -lh apps/desktop/dist || true
175212
exit 1
176213
fi
177-
codesign --verify --deep --strict --verbose=2 "$app_path"
178-
codesign -dv --verbose=4 "$app_path" 2>&1 | grep -F "Developer ID Application"
179214
- name: Upload desktop artifacts
180215
uses: actions/upload-artifact@v4
181216
with:
@@ -185,7 +220,6 @@ jobs:
185220
apps/desktop/dist/*.deb
186221
apps/desktop/dist/*.rpm
187222
apps/desktop/dist/*.dmg
188-
apps/desktop/dist/*.zip
189223
apps/desktop/dist/*.exe
190224
if-no-files-found: error
191225

@@ -215,7 +249,6 @@ jobs:
215249
release-artifacts/desktop/*.deb
216250
release-artifacts/desktop/*.rpm
217251
release-artifacts/desktop/*.dmg
218-
release-artifacts/desktop/*.zip
219252
release-artifacts/desktop/*.exe
220253
)
221254
if [[ ${#files[@]} -eq 0 ]]; then

apps/desktop/electron-builder.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ extraResources:
3939
mac:
4040
category: public.app-category.productivity
4141
target:
42-
- target: dmg
43-
arch: [arm64, x64]
44-
- target: zip
45-
arch: [arm64, x64]
42+
- dmg
4643
icon: build/icon.icon
4744
artifactName: ${productName}-Desktop-${version}-mac-${arch}.${ext}
4845
notarize: false

0 commit comments

Comments
 (0)