Sign installers with cosign #44
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: Sign installers with cosign | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Release tag name (e.g. v1.2.3). If empty, will use latest.' | |
| required: false | |
| default: '' | |
| workflow_run: | |
| workflows: ["Builder main installer"] | |
| types: [completed] | |
| permissions: | |
| contents: write | |
| id-token: write | |
| jobs: | |
| sign: | |
| if: > | |
| ( | |
| github.event_name == 'workflow_run' && | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'release' | |
| ) | |
| || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Determine release tag | |
| id: tag | |
| uses: actions/github-script@v7 | |
| with: | |
| result-encoding: string | |
| script: | | |
| // grab tag from user input | |
| const inputTag = '${{ github.event.inputs.tag }}'; | |
| if (inputTag) { | |
| return inputTag; | |
| } | |
| // grab tag from last release | |
| const latest = await github.rest.repos.getLatestRelease({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo | |
| }); | |
| return latest.data.tag_name; | |
| - name: Download release assets via GH CLI | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release download ${{ steps.tag.outputs.result }} \ | |
| --repo ${{ github.repository }} \ | |
| --pattern '*.exe' \ | |
| --dir artifacts | |
| - name: Install cosign | |
| run: | | |
| curl -sSL -o cosign \ | |
| https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 | |
| chmod +x cosign | |
| - name: Fetch OIDC token | |
| id: oidc | |
| uses: actions/github-script@v7 | |
| with: | |
| result-encoding: string | |
| script: | | |
| // minimal OIDC fetch for Sigstore | |
| return await core.getIDToken('sigstore'); | |
| - name: Keyless sign installers | |
| env: | |
| COSIGN_EXPERIMENTAL: '1' | |
| run: | | |
| for exe in artifacts/*.exe; do | |
| ./cosign sign-blob --yes \ | |
| --identity-token "${{ steps.oidc.outputs.result }}" \ | |
| --output-signature "${exe}.sig" \ | |
| --output-certificate "${exe}.pem" \ | |
| "$exe" | |
| done | |
| - name: Verify signatures | |
| run: | | |
| for exe in artifacts/*.exe; do | |
| ./cosign verify-blob \ | |
| --certificate-identity-regexp "https://github\\.com/${{ github.repository }}/.*" \ | |
| --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ | |
| --signature "${exe}.sig" \ | |
| --certificate "${exe}.pem" \ | |
| "$exe" | |
| done | |
| - name: Package signatures | |
| run: | | |
| cd artifacts | |
| zip -j "cosign-signatures-${{ steps.tag.outputs.result }}.zip" *.exe.sig *.exe.pem | |
| - name: Publish signatures | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.tag.outputs.result }} | |
| files: artifacts/cosign-signatures-*.zip |