Release 0.0.29 #26
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: 🌍 Release | |
| run-name: Release ${{ github.event.release.tag_name }} | |
| on: | |
| release: | |
| types: [published] | |
| permissions: | |
| contents: write | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: release-publish-${{ github.event.release.tag_name }} | |
| cancel-in-progress: false | |
| env: | |
| RELEASE_TAG: ${{ github.event.release.tag_name }} | |
| jobs: | |
| sign-and-notarize: | |
| runs-on: macos-latest | |
| steps: | |
| - name: Checkout released ref | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.RELEASE_TAG }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - name: Install signing dependencies | |
| run: npm ci | |
| - name: Download unsigned macOS artifact | |
| uses: robinraju/release-downloader@v1.11 | |
| with: | |
| tag: ${{ env.RELEASE_TAG }} | |
| fileName: 'forge-*-mac-arm64-unsigned.zip' | |
| - name: Extract app bundle | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p .out/sign | |
| unsigned_zip="$(find . -maxdepth 1 -type f -name 'forge-*-mac-arm64-unsigned.zip' -print -quit)" | |
| if [[ -z "${unsigned_zip}" ]]; then | |
| echo "::error::Unsigned macOS artifact was not downloaded." | |
| exit 1 | |
| fi | |
| unzip -q "${unsigned_zip}" -d .out/sign | |
| app_path="$(find .out/sign -maxdepth 2 -type d -name 'Forge.app' -print -quit)" | |
| if [[ -z "${app_path}" ]]; then | |
| echo "::error::Forge.app was not found in ${unsigned_zip}." | |
| find .out/sign -maxdepth 3 -print | |
| exit 1 | |
| fi | |
| echo "UNSIGNED_ZIP=${unsigned_zip}" >> "$GITHUB_ENV" | |
| echo "APP_PATH=${app_path}" >> "$GITHUB_ENV" | |
| - name: Add cert to keychain | |
| uses: apple-actions/import-codesign-certs@v3 | |
| with: | |
| p12-file-base64: ${{ secrets.MAC_CERT_BASE64 }} | |
| p12-password: ${{ secrets.MAC_CERT_PASSWORD }} | |
| - name: Sign app bundle | |
| shell: bash | |
| env: | |
| MAC_DEV_TEAM_ID: ${{ secrets.MAC_DEV_TEAM_ID }} | |
| run: | | |
| set -euo pipefail | |
| node .github/scripts/sign-electron-app.mjs | |
| - name: Pack app for notarization | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p .out/release | |
| ditto -c -k --keepParent "${APP_PATH}" ".out/release/forge-${RELEASE_TAG}-mac-arm64.zip" | |
| - name: Notarize app | |
| shell: bash | |
| env: | |
| MAC_DEV_LOGIN: ${{ secrets.MAC_DEV_LOGIN }} | |
| MAC_DEV_PASSWORD: ${{ secrets.MAC_DEV_PASSWORD }} | |
| MAC_DEV_TEAM_ID: ${{ secrets.MAC_DEV_TEAM_ID }} | |
| run: | | |
| set -euo pipefail | |
| if [[ -z "${MAC_DEV_LOGIN:-}" || -z "${MAC_DEV_PASSWORD:-}" || -z "${MAC_DEV_TEAM_ID:-}" ]]; then | |
| echo "::error::MAC_DEV_LOGIN, MAC_DEV_PASSWORD, and MAC_DEV_TEAM_ID secrets are required for notarization." | |
| exit 1 | |
| fi | |
| set +e | |
| submit_output="$(xcrun notarytool submit ".out/release/forge-${RELEASE_TAG}-mac-arm64.zip" \ | |
| --apple-id "${MAC_DEV_LOGIN}" \ | |
| --password "${MAC_DEV_PASSWORD}" \ | |
| --team-id "${MAC_DEV_TEAM_ID}" \ | |
| --wait \ | |
| --output-format json 2>&1)" | |
| submit_status=$? | |
| set -e | |
| printf '%s\n' "${submit_output}" | |
| submission_id="$(printf '%s\n' "${submit_output}" | node -e 'const fs = require("node:fs"); const input = fs.readFileSync(0, "utf8"); try { const data = JSON.parse(input); process.stdout.write(data.id || ""); } catch { process.exit(0); }')" | |
| notarization_status="$(printf '%s\n' "${submit_output}" | node -e 'const fs = require("node:fs"); const input = fs.readFileSync(0, "utf8"); try { const data = JSON.parse(input); process.stdout.write(data.status || ""); } catch { process.exit(0); }')" | |
| if [[ -n "${submission_id}" && "${notarization_status}" != "Accepted" ]]; then | |
| echo "::group::Apple notarization log" | |
| xcrun notarytool log \ | |
| --apple-id "${MAC_DEV_LOGIN}" \ | |
| --password "${MAC_DEV_PASSWORD}" \ | |
| --team-id "${MAC_DEV_TEAM_ID}" \ | |
| "${submission_id}" \ | |
| notary-log.json || true | |
| if [[ -f notary-log.json ]]; then | |
| cat notary-log.json | |
| fi | |
| echo "::endgroup::" | |
| fi | |
| if [[ "${submit_status}" -ne 0 || "${notarization_status}" != "Accepted" ]]; then | |
| echo "::error::Notarization failed with status '${notarization_status:-unknown}'." | |
| exit 1 | |
| fi | |
| - name: Pack signed app | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| rm -f ".out/release/forge-${RELEASE_TAG}-mac-arm64.zip" | |
| ditto -c -k --keepParent "${APP_PATH}" ".out/release/forge-${RELEASE_TAG}-mac-arm64.zip" | |
| - name: Generate macOS update metadata | |
| run: node .github/scripts/generate-latest-mac-update.mjs ".out/release/forge-${RELEASE_TAG}-mac-arm64.zip" "${RELEASE_TAG}" | |
| - name: Upload signed macOS artifact | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ env.RELEASE_TAG }} | |
| files: | | |
| .out/release/forge-${{ env.RELEASE_TAG }}-mac-arm64.zip | |
| .out/release/latest-mac.yml | |
| - name: Remove unsigned macOS artifact | |
| continue-on-error: true | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| try { | |
| const tag = process.env.RELEASE_TAG; | |
| const unsignedName = `forge-${tag}-mac-arm64-unsigned.zip`; | |
| const { data: release } = await github.rest.repos.getReleaseByTag({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| tag, | |
| }); | |
| const asset = release.assets.find((candidate) => candidate.name === unsignedName); | |
| if (!asset) { | |
| core.info(`Unsigned artifact not found: ${unsignedName}`); | |
| return; | |
| } | |
| await github.rest.repos.deleteReleaseAsset({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| asset_id: asset.id, | |
| }); | |
| core.info(`Deleted unsigned artifact: ${unsignedName}`); | |
| } catch (error) { | |
| core.warning(`Best-effort cleanup failed: ${error?.message ?? error}`); | |
| } | |
| update-homebrew-tap: | |
| if: ${{ !contains(github.event.release.tag_name, '-') }} | |
| needs: | |
| - sign-and-notarize | |
| uses: ./.github/workflows/release-homebrew-tap.yml | |
| with: | |
| ref: ${{ format('refs/tags/{0}', github.event.release.tag_name) }} | |
| version: ${{ github.event.release.tag_name }} | |
| dry-run: false | |
| secrets: inherit | |
| publish-website: | |
| needs: | |
| - sign-and-notarize | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Checkout released ref | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ env.RELEASE_TAG }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: npm | |
| - name: Build website | |
| run: npm run website:build | |
| - name: Configure GitHub Pages | |
| uses: actions/configure-pages@v5 | |
| - name: Upload GitHub Pages artifact | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: .out/site | |
| - name: Deploy GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 |