* ci: migrate ESLint to Biome, optimize workflows, fix tar vulnerability - Replace ESLint with Biome (15-25x faster linting) - Pin Biome to 2.3.11 for consistent behavior across local/CI - Disable useArrowFunction rule (breaks vitest constructor mocks) - Add composite actions for DRY workflow setup - Fix tar vulnerability (CVE-2026-23745) by upgrading to v7.5.3 - Add @electron/rebuild override to ensure consistent tar version - Update electron-builder to 26.4.0 Co-Authored-By: Claude Opus 4.5 <[email protected]> * fix(workflows): address all 15 PR review findings HIGH priority fixes: - Add [email protected] override to frontend package.json (CVE-2026-23745) - Use setup-node-frontend composite action in release.yml (4 build jobs) - Use setup-node-frontend composite action in beta-release.yml (4 build jobs) MEDIUM priority fixes: - Add notarization status verification ('Accepted') before stapling - Add blockmap files to beta-release asset copying (delta updates) - Add DMG validation with fallback in release.yml - Extract yq checksum to env block, single definition per step - Fix snake_case to kebab-case in notarization action outputs LOW priority fixes: - Add config files (pyproject.toml, tsconfig*.json, biome.jsonc) to CI paths - Document yq checksum requirement in merge-macos-manifests - Always use jq for notarization ID parsing (no regex fallback) - Add blockmap files to dry-run-summary job - Change noControlCharactersInRegex from off to warn - Rename biome.json to biome.jsonc, add comments explaining disabled rules noSecrets rule kept off due to 2700+ false positives on normal strings. Co-Authored-By: Claude Opus 4.5 <[email protected]> * fix(lint): correct biome.jsonc path in workflow triggers The lint workflow path filter referenced 'biome.json' but the actual config file is 'biome.jsonc' (renamed to support comments). This fix ensures the lint workflow triggers when the Biome config is modified. Co-Authored-By: Claude Opus 4.5 <[email protected]> * fix(workflows): address 6 PR review findings - QUAL-001/002: Add DMG file existence checks before stapling - QUAL-003: Quote all path variables in merge-macos-manifests - QUAL-004: Add semver validation in update-readme.py - QUAL-005: Document noDangerouslySetInnerHtml security rule decision - LOGIC-001: Add warning when both notarization IDs are empty Co-Authored-By: Claude Opus 4.5 <[email protected]> * feat(workflows): add gate jobs for branch protection Add summary/gate jobs to match existing branch protection rules: - CI Complete: aggregates test-python and test-frontend results - Lint Complete: aggregates python and typescript lint results - Security Summary: aggregates codeql and python-security results These jobs provide a single status check for branch protection instead of requiring individual job names which can change with matrix configs. Co-Authored-By: Claude Opus 4.5 <[email protected]> --------- Co-authored-by: Claude Opus 4.5 <[email protected]>
161 lines
6.0 KiB
YAML
161 lines
6.0 KiB
YAML
name: 'Finalize macOS Notarization'
|
|
description: 'Wait for Apple notarization to complete and staple tickets to DMG files'
|
|
|
|
inputs:
|
|
apple-id:
|
|
description: 'Apple ID for notarization'
|
|
required: true
|
|
apple-app-specific-password:
|
|
description: 'Apple app-specific password'
|
|
required: true
|
|
apple-team-id:
|
|
description: 'Apple Team ID'
|
|
required: true
|
|
intel-notarization-id:
|
|
description: 'Notarization request ID for Intel build'
|
|
required: false
|
|
default: ''
|
|
arm64-notarization-id:
|
|
description: 'Notarization request ID for ARM64 build'
|
|
required: false
|
|
default: ''
|
|
intel-dmg-file:
|
|
description: 'Filename of the Intel DMG'
|
|
required: false
|
|
default: ''
|
|
arm64-dmg-file:
|
|
description: 'Filename of the ARM64 DMG'
|
|
required: false
|
|
default: ''
|
|
intel-artifact-path:
|
|
description: 'Path to Intel build artifacts'
|
|
required: false
|
|
default: 'intel'
|
|
arm64-artifact-path:
|
|
description: 'Path to ARM64 build artifacts'
|
|
required: false
|
|
default: 'arm64'
|
|
timeout:
|
|
description: 'Timeout in seconds for notarization wait'
|
|
required: false
|
|
default: '3600'
|
|
|
|
outputs:
|
|
intel-stapled:
|
|
description: 'Whether Intel DMG was successfully stapled'
|
|
value: ${{ steps.staple.outputs.intel_stapled }}
|
|
arm64-stapled:
|
|
description: 'Whether ARM64 DMG was successfully stapled'
|
|
value: ${{ steps.staple.outputs.arm64_stapled }}
|
|
|
|
runs:
|
|
using: 'composite'
|
|
steps:
|
|
- name: Wait for notarization and staple
|
|
id: staple
|
|
shell: bash
|
|
env:
|
|
APPLE_ID: ${{ inputs.apple-id }}
|
|
APPLE_APP_SPECIFIC_PASSWORD: ${{ inputs.apple-app-specific-password }}
|
|
APPLE_TEAM_ID: ${{ inputs.apple-team-id }}
|
|
INTEL_NOTARIZATION_ID: ${{ inputs.intel-notarization-id }}
|
|
ARM64_NOTARIZATION_ID: ${{ inputs.arm64-notarization-id }}
|
|
INTEL_DMG: ${{ inputs.intel-dmg-file }}
|
|
ARM64_DMG: ${{ inputs.arm64-dmg-file }}
|
|
INTEL_PATH: ${{ inputs.intel-artifact-path }}
|
|
ARM64_PATH: ${{ inputs.arm64-artifact-path }}
|
|
TIMEOUT: ${{ inputs.timeout }}
|
|
run: |
|
|
intel_stapled=false
|
|
arm64_stapled=false
|
|
|
|
if [ -z "$APPLE_ID" ]; then
|
|
echo "Skipping notarization wait: APPLE_ID not configured"
|
|
echo "intel_stapled=false" >> "$GITHUB_OUTPUT"
|
|
echo "arm64_stapled=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
|
|
# Warn if no notarization IDs provided (could indicate submission failure)
|
|
if [ -z "$INTEL_NOTARIZATION_ID" ] && [ -z "$ARM64_NOTARIZATION_ID" ]; then
|
|
echo "::warning::No notarization IDs provided - nothing to finalize. Check if notarization submission succeeded."
|
|
echo "intel_stapled=false" >> "$GITHUB_OUTPUT"
|
|
echo "arm64_stapled=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
|
|
# Wait for Intel notarization
|
|
if [ -n "$INTEL_NOTARIZATION_ID" ]; then
|
|
echo "Waiting for Intel notarization: $INTEL_NOTARIZATION_ID"
|
|
if ! xcrun notarytool wait "$INTEL_NOTARIZATION_ID" \
|
|
--apple-id "$APPLE_ID" \
|
|
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
|
|
--team-id "$APPLE_TEAM_ID" \
|
|
--timeout "$TIMEOUT"; then
|
|
echo "::error::Intel notarization failed or timed out"
|
|
exit 1
|
|
fi
|
|
# Verify notarization was accepted (not just processed)
|
|
INTEL_STATUS=$(xcrun notarytool info "$INTEL_NOTARIZATION_ID" \
|
|
--apple-id "$APPLE_ID" \
|
|
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
|
|
--team-id "$APPLE_TEAM_ID" \
|
|
--output-format json | jq -r '.status // "Unknown"')
|
|
if [ "$INTEL_STATUS" != "Accepted" ]; then
|
|
echo "::error::Intel notarization status is '$INTEL_STATUS', expected 'Accepted'"
|
|
exit 1
|
|
fi
|
|
echo "Intel notarization status: $INTEL_STATUS"
|
|
# Verify DMG file exists before stapling
|
|
if [ ! -f "$INTEL_PATH/$INTEL_DMG" ]; then
|
|
echo "::error::Intel DMG not found at $INTEL_PATH/$INTEL_DMG"
|
|
exit 1
|
|
fi
|
|
echo "Stapling Intel DMG: $INTEL_PATH/$INTEL_DMG"
|
|
if ! xcrun stapler staple "$INTEL_PATH/$INTEL_DMG"; then
|
|
echo "::error::Failed to staple Intel DMG"
|
|
exit 1
|
|
fi
|
|
echo "Successfully stapled Intel DMG"
|
|
intel_stapled=true
|
|
fi
|
|
|
|
# Wait for ARM64 notarization
|
|
if [ -n "$ARM64_NOTARIZATION_ID" ]; then
|
|
echo "Waiting for ARM64 notarization: $ARM64_NOTARIZATION_ID"
|
|
if ! xcrun notarytool wait "$ARM64_NOTARIZATION_ID" \
|
|
--apple-id "$APPLE_ID" \
|
|
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
|
|
--team-id "$APPLE_TEAM_ID" \
|
|
--timeout "$TIMEOUT"; then
|
|
echo "::error::ARM64 notarization failed or timed out"
|
|
exit 1
|
|
fi
|
|
# Verify notarization was accepted (not just processed)
|
|
ARM64_STATUS=$(xcrun notarytool info "$ARM64_NOTARIZATION_ID" \
|
|
--apple-id "$APPLE_ID" \
|
|
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
|
|
--team-id "$APPLE_TEAM_ID" \
|
|
--output-format json | jq -r '.status // "Unknown"')
|
|
if [ "$ARM64_STATUS" != "Accepted" ]; then
|
|
echo "::error::ARM64 notarization status is '$ARM64_STATUS', expected 'Accepted'"
|
|
exit 1
|
|
fi
|
|
echo "ARM64 notarization status: $ARM64_STATUS"
|
|
# Verify DMG file exists before stapling
|
|
if [ ! -f "$ARM64_PATH/$ARM64_DMG" ]; then
|
|
echo "::error::ARM64 DMG not found at $ARM64_PATH/$ARM64_DMG"
|
|
exit 1
|
|
fi
|
|
echo "Stapling ARM64 DMG: $ARM64_PATH/$ARM64_DMG"
|
|
if ! xcrun stapler staple "$ARM64_PATH/$ARM64_DMG"; then
|
|
echo "::error::Failed to staple ARM64 DMG"
|
|
exit 1
|
|
fi
|
|
echo "Successfully stapled ARM64 DMG"
|
|
arm64_stapled=true
|
|
fi
|
|
|
|
echo "intel_stapled=$intel_stapled" >> "$GITHUB_OUTPUT"
|
|
echo "arm64_stapled=$arm64_stapled" >> "$GITHUB_OUTPUT"
|