Prepare release 2026.9.2.2 #57
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Electron Desktop Build | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: electron-desktop-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| desktop: | |
| name: Build ${{ matrix.platform }} | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| NODE_OPTIONS: --max-old-space-size=4096 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: macos | |
| os: macos-15 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 26 | |
| cache: npm | |
| - name: Prepare macOS signing credentials | |
| if: matrix.platform == 'macos' | |
| shell: bash | |
| env: | |
| SIGNING_CSC_LINK: ${{ secrets.CSC_LINK }} | |
| SIGNING_CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} | |
| NOTARY_API_KEY_CONTENT: ${{ secrets.APPLE_API_KEY }} | |
| NOTARY_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }} | |
| NOTARY_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} | |
| NOTARY_API_ISSUER: ${{ secrets.APPLE_API_ISSUER }} | |
| NOTARY_APPLE_ID: ${{ secrets.APPLE_ID }} | |
| NOTARY_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} | |
| NOTARY_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| run: | | |
| set -euo pipefail | |
| append_env() { | |
| local name="$1" | |
| local value="$2" | |
| local delimiter="CANVAS_${name}_${RANDOM}_${RANDOM}" | |
| { | |
| echo "${name}<<${delimiter}" | |
| printf '%s\n' "$value" | |
| echo "$delimiter" | |
| } >> "$GITHUB_ENV" | |
| } | |
| missing=() | |
| [[ -n "${SIGNING_CSC_LINK:-}" ]] || missing+=("CSC_LINK") | |
| [[ -n "${SIGNING_CSC_KEY_PASSWORD:-}" ]] || missing+=("CSC_KEY_PASSWORD") | |
| has_api_key=false | |
| if [[ -n "${NOTARY_API_KEY_ID:-}" && -n "${NOTARY_API_ISSUER:-}" ]] && { [[ -n "${NOTARY_API_KEY_CONTENT:-}" ]] || [[ -n "${NOTARY_API_KEY_BASE64:-}" ]]; }; then | |
| has_api_key=true | |
| fi | |
| has_apple_id=false | |
| if [[ -n "${NOTARY_APPLE_ID:-}" && -n "${NOTARY_APP_SPECIFIC_PASSWORD:-}" && -n "${NOTARY_TEAM_ID:-}" ]]; then | |
| has_apple_id=true | |
| fi | |
| if [[ "$has_api_key" != "true" && "$has_apple_id" != "true" ]]; then | |
| missing+=("APPLE_API_KEY or APPLE_API_KEY_BASE64 with APPLE_API_KEY_ID and APPLE_API_ISSUER, or APPLE_ID with APPLE_APP_SPECIFIC_PASSWORD and APPLE_TEAM_ID") | |
| fi | |
| if (( ${#missing[@]} > 0 )); then | |
| printf 'Missing GitHub secret(s) required for macOS Developer ID signing and notarization:\n' >&2 | |
| printf ' - %s\n' "${missing[@]}" >&2 | |
| exit 1 | |
| fi | |
| append_env "CSC_LINK" "$SIGNING_CSC_LINK" | |
| append_env "CSC_KEY_PASSWORD" "$SIGNING_CSC_KEY_PASSWORD" | |
| if [[ "$has_api_key" == "true" ]]; then | |
| key_path="$RUNNER_TEMP/AuthKey_${NOTARY_API_KEY_ID}.p8" | |
| if [[ -n "${NOTARY_API_KEY_BASE64:-}" ]]; then | |
| printf '%s' "$NOTARY_API_KEY_BASE64" | base64 -D > "$key_path" | |
| else | |
| printf '%s\n' "$NOTARY_API_KEY_CONTENT" > "$key_path" | |
| fi | |
| chmod 600 "$key_path" | |
| echo "APPLE_API_KEY=$key_path" >> "$GITHUB_ENV" | |
| append_env "APPLE_API_KEY_ID" "$NOTARY_API_KEY_ID" | |
| append_env "APPLE_API_ISSUER" "$NOTARY_API_ISSUER" | |
| else | |
| append_env "APPLE_ID" "$NOTARY_APPLE_ID" | |
| append_env "APPLE_APP_SPECIFIC_PASSWORD" "$NOTARY_APP_SPECIFIC_PASSWORD" | |
| append_env "APPLE_TEAM_ID" "$NOTARY_TEAM_ID" | |
| fi | |
| echo "macOS signing credentials are configured." | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Verify release compliance | |
| run: npm run test:licenses:release | |
| - name: Build Electron desktop artifacts | |
| shell: bash | |
| run: | | |
| npm run electron:package | |
| - name: Verify macOS signing and notarization | |
| if: matrix.platform == 'macos' | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| app_path="$(/usr/bin/find dist-electron -type d -name 'Canvas Notebook.app' -print -quit)" | |
| if [[ -z "$app_path" ]]; then | |
| echo "No packaged macOS app bundle found under dist-electron." >&2 | |
| exit 1 | |
| fi | |
| codesign --verify --deep --strict --verbose=2 "$app_path" | |
| xcrun stapler validate "$app_path" | |
| spctl --assess --type execute --verbose=4 "$app_path" | |
| - name: Upload desktop artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: canvas-notebook-desktop-${{ matrix.platform }} | |
| if-no-files-found: error | |
| retention-days: 30 | |
| path: | | |
| dist-electron/*.blockmap | |
| dist-electron/*.dmg | |
| dist-electron/*.zip | |
| dist-electron/latest-mac.yml | |
| release: | |
| name: Publish desktop release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: desktop | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Download desktop artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| pattern: canvas-notebook-desktop-* | |
| path: release-artifacts | |
| merge-multiple: true | |
| - name: Verify updater manifest asset references | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| node scripts/sync-electron-version.mjs | |
| expected_version="$(node -p "require('./electron/package.json').version")" | |
| manifest_version="$(awk '/^version: / { print $2; exit }' release-artifacts/latest-mac.yml)" | |
| [[ "$manifest_version" == "$expected_version" ]] | |
| manifest_files=0 | |
| while IFS= read -r asset; do | |
| [[ -n "$asset" ]] | |
| [[ -f "release-artifacts/$asset" ]] | |
| manifest_files=$((manifest_files + 1)) | |
| done < <(awk '/^ - url: / { print $3 }' release-artifacts/latest-mac.yml) | |
| (( manifest_files > 0 )) | |
| - name: Publish complete desktop release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| files=( | |
| release-artifacts/*.blockmap | |
| release-artifacts/*.dmg | |
| release-artifacts/*.zip | |
| release-artifacts/latest-mac.yml | |
| ) | |
| if (( ${#files[@]} == 0 )); then | |
| echo "No desktop artifacts found for release upload." | |
| exit 1 | |
| fi | |
| if ! gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then | |
| gh release create "$GITHUB_REF_NAME" \ | |
| --title "$GITHUB_REF_NAME" \ | |
| --notes "Desktop artifacts for $GITHUB_REF_NAME." | |
| fi | |
| gh release upload "$GITHUB_REF_NAME" "${files[@]}" --clobber |