diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..db8f189 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,42 @@ +name: Release + +on: + push: + tags: ['v*'] + +permissions: + contents: write # create the GitHub Release + id-token: write # mint the OIDC token cosign exchanges for a signing cert + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 + + - name: Build source tarball from the tag + run: | + git archive --format=tar.gz \ + --prefix="gosystems-${GITHUB_REF_NAME}/" \ + -o "gosystems-${GITHUB_REF_NAME}.tar.gz" \ + "${GITHUB_REF_NAME}" + + - name: Sign artifact (keyless, Sigstore) + run: | + cosign sign-blob --yes \ + --output-signature "gosystems-${GITHUB_REF_NAME}.tar.gz.sig" \ + --output-certificate "gosystems-${GITHUB_REF_NAME}.pem" \ + "gosystems-${GITHUB_REF_NAME}.tar.gz" + + - name: Create GitHub Release with signed assets + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "${GITHUB_REF_NAME}" \ + --title "GoSystems ${GITHUB_REF_NAME}" \ + --generate-notes \ + "gosystems-${GITHUB_REF_NAME}.tar.gz" \ + "gosystems-${GITHUB_REF_NAME}.tar.gz.sig" \ + "gosystems-${GITHUB_REF_NAME}.pem" diff --git a/README.md b/README.md index ab227a4..31c2b92 100644 --- a/README.md +++ b/README.md @@ -77,3 +77,26 @@ Run tests with: go test ./internal/... ``` ***Note: I built this project to deepen my understanding of how web communication works under the hood of APIs and frameworks.*** + +## Verifying releases + +Every release tarball is signed keylessly with [Sigstore cosign](https://docs.sigstore.dev/) +from this repository's `release.yml` GitHub Actions workflow. The signature is recorded +in the public Rekor transparency log. + +To verify (example for `v1.0.0` — adjust the tag in both the asset names and the identity): + +```sh +# Arch/EndeavourOS: sudo pacman -S cosign + +cosign verify-blob \ + --certificate gosystems-v1.0.0.pem \ + --certificate-identity 'https://github.com/LD-RW/GoSystems-High-Performance-HTTP-1.1-Server/.github/workflows/release.yml@refs/tags/v1.0.0' \ + --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \ + --signature gosystems-v1.0.0.tar.gz.sig \ + gosystems-v1.0.0.tar.gz +``` + +Successful output is `Verified OK`. This proves the tarball was produced and signed by +this exact workflow at this exact tag; any tampering with the artifact, signature, or +certificate breaks verification.