release #25
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 | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| channel: | |
| description: Release policy channel | |
| required: true | |
| type: choice | |
| options: | |
| - preview | |
| - stable | |
| version: | |
| description: Semantic release version (preview requires a prerelease) | |
| required: true | |
| type: string | |
| trust: | |
| description: Produce Developer ID-signed and notarized Apple artifacts | |
| required: true | |
| default: true | |
| type: boolean | |
| publish: | |
| description: Enter the separately approved public publication job | |
| required: true | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: portreeve-release-${{ inputs.version }} | |
| cancel-in-progress: false | |
| env: | |
| BUN_VERSION: 1.3.14 | |
| NODE_VERSION: 22 | |
| RELEASE_ROOT: dist/releases/${{ inputs.version }} | |
| TRUSTED_ROOT: dist/trusted/${{ inputs.version }} | |
| PORTREEVE_HOMEPAGE_URL: ${{ github.server_url }}/${{ github.repository }} | |
| PORTREEVE_RELEASE_BASE_URL: | |
| ${{ github.server_url }}/${{ github.repository }}/releases/download | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - run: bun run check | |
| - name: Prepare exact build-once release workspace | |
| run: >- | |
| bun run release:prepare -- --channel "${{ inputs.channel }}" --version "${{ | |
| inputs.version }}" ${{ inputs.trust && '--trusted' || '' }} | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: prepared-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| native-evidence: | |
| needs: prepare | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: macos-15 | |
| platform: macos-arm64 | |
| - runner: macos-15-intel | |
| platform: macos-x64 | |
| - runner: ubuntu-24.04 | |
| platform: linux-x64 | |
| - runner: ubuntu-24.04-arm | |
| platform: linux-arm64 | |
| runs-on: ${{ matrix.runner }} | |
| name: native evidence (${{ matrix.platform }}) | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: prepared-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - name: Restore promoted executable modes | |
| run: chmod 755 "$RELEASE_ROOT"/artifacts/portreeve-v* | |
| - if: startsWith(matrix.platform, 'linux-') | |
| name: Verify a real mixed process and Docker stack | |
| run: bun run stacks:verify | |
| - name: Execute the promoted native artifact and supervised lifecycle | |
| run: >- | |
| bun run release:native-evidence -- --record | |
| "$RELEASE_ROOT/release-record.json" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-${{ matrix.platform }} | |
| path: ${{ env.RELEASE_ROOT }}/evidence/native-${{ matrix.platform }}.json | |
| if-no-files-found: error | |
| retention-days: 7 | |
| aggregate-native-evidence: | |
| if: ${{ !inputs.trust }} | |
| needs: native-evidence | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: prepared-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: native-* | |
| path: ${{ env.RELEASE_ROOT }}/evidence | |
| merge-multiple: true | |
| - name: Join the complete four-target evidence matrix once | |
| run: >- | |
| bun run release:merge-native-evidence -- --record | |
| "$RELEASE_ROOT/release-record.json" --evidence | |
| "$RELEASE_ROOT"/evidence/native-*.json | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-verified-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| qualify-trust: | |
| if: inputs.trust | |
| needs: native-evidence | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: prepared-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: native-* | |
| path: ${{ env.RELEASE_ROOT }}/evidence | |
| merge-multiple: true | |
| - name: Qualify all native candidates without credential access | |
| run: >- | |
| bun run release:qualify-trust -- --record "$RELEASE_ROOT/release-record.json" | |
| --evidence "$RELEASE_ROOT"/evidence/native-*.json | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: trust-qualified-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| release-trust: | |
| if: inputs.trust && github.ref == 'refs/heads/main' | |
| needs: qualify-trust | |
| runs-on: macos-15 | |
| environment: release-trust | |
| permissions: | |
| contents: read | |
| env: | |
| PORTREEVE_APPLE_SIGNING_IDENTITY: ${{ vars.PORTREEVE_APPLE_SIGNING_IDENTITY }} | |
| PORTREEVE_APPLE_TEAM_ID: ${{ vars.PORTREEVE_APPLE_TEAM_ID }} | |
| PORTREEVE_APPLE_NOTARY_KEY_ID: ${{ vars.PORTREEVE_APPLE_NOTARY_KEY_ID }} | |
| PORTREEVE_APPLE_NOTARY_ISSUER_ID: ${{ vars.PORTREEVE_APPLE_NOTARY_ISSUER_ID }} | |
| PORTREEVE_APPLE_NOTARY_KEY_NAME: ${{ vars.PORTREEVE_APPLE_NOTARY_KEY_NAME }} | |
| PORTREEVE_APPLE_CERTIFICATE_P12_BASE64: | |
| ${{ secrets.PORTREEVE_APPLE_CERTIFICATE_P12_BASE64 }} | |
| PORTREEVE_APPLE_CERTIFICATE_PASSWORD: | |
| ${{ secrets.PORTREEVE_APPLE_CERTIFICATE_PASSWORD }} | |
| PORTREEVE_APPLE_NOTARY_KEY_P8_BASE64: | |
| ${{ secrets.PORTREEVE_APPLE_NOTARY_KEY_P8_BASE64 }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: trust-qualified-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - name: Produce both trusted macOS artifact sets without publishing | |
| run: >- | |
| bun run release:produce-apple-trust -- --record | |
| "$RELEASE_ROOT/release-record.json" --qualification | |
| "$RELEASE_ROOT/evidence/trust-qualification.json" --output "$TRUSTED_ROOT" | |
| - name: Preserve failed notarization recovery evidence | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: trusted-recovery-${{ inputs.version }}-${{ github.run_attempt }} | |
| path: ${{ env.TRUSTED_ROOT }}/recovery | |
| if-no-files-found: warn | |
| retention-days: 7 | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: trusted-${{ inputs.version }} | |
| path: ${{ env.TRUSTED_ROOT }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| trusted-native-evidence: | |
| needs: release-trust | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: macos-15 | |
| architecture: arm64 | |
| - runner: macos-15-intel | |
| architecture: x64 | |
| runs-on: ${{ matrix.runner }} | |
| name: Apple trust evidence (macos-${{ matrix.architecture }}) | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: trusted-${{ inputs.version }} | |
| path: ${{ env.TRUSTED_ROOT }} | |
| - name: Restore authoritative executable modes | |
| run: chmod 755 "$TRUSTED_ROOT"/artifacts/portreeve-v* | |
| - name: Verify exact Apple artifacts on their native architecture | |
| run: >- | |
| bun run release:apple-native-evidence -- --record | |
| "$TRUSTED_ROOT/release-record.json" --producer-evidence | |
| "$TRUSTED_ROOT/evidence/apple-trust-producer.json" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: apple-native-${{ matrix.architecture }} | |
| path: | |
| ${{ env.TRUSTED_ROOT }}/evidence/apple-native-${{ matrix.architecture | |
| }}.json | |
| if-no-files-found: error | |
| retention-days: 7 | |
| finalize-trusted-distribution: | |
| needs: trusted-native-evidence | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: trusted-${{ inputs.version }} | |
| path: ${{ env.TRUSTED_ROOT }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: apple-native-* | |
| path: ${{ env.TRUSTED_ROOT }}/evidence | |
| merge-multiple: true | |
| - name: Seal exact distribution metadata and publication plan | |
| run: >- | |
| bun run release:finalize-desktop -- --record | |
| "$TRUSTED_ROOT/release-record.json" --producer-evidence | |
| "$TRUSTED_ROOT/evidence/apple-trust-producer.json" --apple-evidence | |
| "$TRUSTED_ROOT"/evidence/apple-native-*.json --current-update-manifest | |
| distribution/desktop-update.json | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: distribution-${{ inputs.version }} | |
| path: ${{ env.TRUSTED_ROOT }} | |
| if-no-files-found: error | |
| retention-days: 14 | |
| desktop-evidence: | |
| needs: aggregate-native-evidence | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: macos-15 | |
| architecture: arm64 | |
| - runner: macos-15-intel | |
| architecture: x64 | |
| runs-on: ${{ matrix.runner }} | |
| name: Desktop evidence (macos-${{ matrix.architecture }}) | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: native-verified-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - name: Restore promoted executable modes | |
| run: chmod 755 "$RELEASE_ROOT"/artifacts/portreeve-v* | |
| - name: Package, launch, mount, and verify the native Desktop DMG | |
| run: >- | |
| bun run release:package-desktop -- --record | |
| "$RELEASE_ROOT/release-record.json" --arch "${{ matrix.architecture }}" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: desktop-${{ matrix.architecture }} | |
| path: | | |
| ${{ env.RELEASE_ROOT }}/artifacts/PortReeve-*-macos-${{ matrix.architecture }}.dmg | |
| ${{ env.RELEASE_ROOT }}/evidence/desktop-macos-${{ matrix.architecture }}.json | |
| if-no-files-found: error | |
| retention-days: 7 | |
| finalize-distribution: | |
| if: ${{ !inputs.trust }} | |
| needs: desktop-evidence | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: native-verified-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: desktop-* | |
| path: ${{ env.RELEASE_ROOT }} | |
| merge-multiple: true | |
| - name: Finalize cask, checksums, update metadata, and publication plan | |
| run: >- | |
| bun run release:finalize-desktop -- --record | |
| "$RELEASE_ROOT/release-record.json" --evidence | |
| "$RELEASE_ROOT"/evidence/desktop-macos-*.json --current-update-manifest | |
| distribution/desktop-update.json | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: distribution-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| if-no-files-found: error | |
| retention-days: 14 | |
| publish: | |
| if: ${{ always() && inputs.publish && !failure() && !cancelled() }} | |
| needs: [finalize-distribution, finalize-trusted-distribution] | |
| runs-on: ubuntu-24.04 | |
| environment: release-publication | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: ${{ env.BUN_VERSION }} | |
| - run: bun ci | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| name: distribution-${{ inputs.version }} | |
| path: ${{ env.RELEASE_ROOT }} | |
| - name: Publish exact prepared bytes after environment approval | |
| run: >- | |
| bun run release:publish -- --record "$RELEASE_ROOT/release-record.json" | |
| --approved-by "${{ github.actor }} via release-publication environment" | |
| --confirm | |
| env: | |
| GH_TOKEN: ${{ secrets.PORTREEVE_RELEASE_TOKEN }} | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: published-record-${{ inputs.version }} | |
| path: | | |
| ${{ env.RELEASE_ROOT }}/release-record.json | |
| ${{ env.RELEASE_ROOT }}/publication-complete.json | |
| if-no-files-found: error | |
| retention-days: 30 |