Merge pull request #18 from golift/feat/windows-release #11
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
| # Release pipeline. Push a full semver tag (v1.2.3) and this workflow: | |
| # 1. Builds and publishes binaries with GoReleaser Pro (Authenticode on | |
| # Windows PE when CODESIGN_URL is set; Apple sign+notarize on darwin | |
| # when MACOS_SIGN_P12 is set). | |
| # 2. Publishes the signerd Docker image to GHCR with the same tag. | |
| # 3. Force-moves the floating tags (v1, v1.2) that GitHub Actions | |
| # consumers track with `uses: golift/codesign@v1`, but only when this | |
| # tag is the highest matching vN.* / vN.N.*. | |
| # | |
| # The trigger matches ONLY vN.N.N. GitHub's filter-pattern syntax (not a | |
| # regex, but it does support `[0-9]` classes and `+` repetition — see the | |
| # "filter pattern cheat sheet" in the GitHub Actions docs) must match the | |
| # whole tag, so the floating vN / vN.N tags this workflow itself pushes can | |
| # never re-trigger it, and neither can prerelease tags like v1.2.3-beta. | |
| # A job-level guard also rejects anything that is not strict vN.N.N. | |
| # Never retag a published vN.N.N. Breaking Action input/output changes mean | |
| # v2.0.0 and a new v2 floater. Floating tags are for `uses:`; Go module | |
| # consumers resolve real semver tags. | |
| name: release | |
| on: | |
| push: | |
| tags: | |
| - 'v[0-9]+.[0-9]+.[0-9]+' | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: codesign-release | |
| cancel-in-progress: false | |
| jobs: | |
| goreleaser: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: require-strict-semver | |
| run: | | |
| if ! [[ "${GITHUB_REF_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "ref ${GITHUB_REF_NAME} is not a strict vN.N.N tag" >&2 | |
| exit 1 | |
| fi | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version-file: go.mod | |
| - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - name: install-codesign | |
| env: | |
| GOBIN: ${{ runner.temp }}/codesign-bin | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${GOBIN}" | |
| go install ./cmd/codesign | |
| echo "${GOBIN}" >> "${GITHUB_PATH}" | |
| echo "CODESIGN_BIN=${GOBIN}/codesign" >> "${GITHUB_ENV}" | |
| # GoReleaser Pro enables notarize when MACOS_SIGN_P12 is set, then | |
| # skips the notary submit if issuer/key/id are empty and still exits 0. | |
| # Fail here so a half-configured org cannot publish signed-only darwin. | |
| - name: require-apple-sign-secrets | |
| env: | |
| MACOS_SIGN_P12: ${{ secrets.MACOS_SIGN_P12 }} | |
| MACOS_SIGN_PASSWORD: ${{ secrets.MACOS_SIGN_PASSWORD }} | |
| MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} | |
| MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} | |
| MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${MACOS_SIGN_P12}" ]; then | |
| echo "MACOS_SIGN_P12 unset; Darwin archives will not be signed or notarized" | |
| exit 0 | |
| fi | |
| missing= | |
| [ -n "${MACOS_SIGN_PASSWORD}" ] || missing="${missing} MACOS_SIGN_PASSWORD" | |
| [ -n "${MACOS_NOTARY_KEY}" ] || missing="${missing} MACOS_NOTARY_KEY" | |
| [ -n "${MACOS_NOTARY_KEY_ID}" ] || missing="${missing} MACOS_NOTARY_KEY_ID" | |
| [ -n "${MACOS_NOTARY_ISSUER_ID}" ] || missing="${missing} MACOS_NOTARY_ISSUER_ID" | |
| if [ -n "${missing}" ]; then | |
| echo "MACOS_SIGN_P12 is set but Apple sign+notarize secrets are incomplete:${missing}" >&2 | |
| exit 1 | |
| fi | |
| - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 | |
| with: | |
| distribution: goreleaser-pro | |
| version: '~> v2' | |
| args: release --clean --timeout 60m | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GORELEASER_KEY: ${{ secrets.GORELEASER_PRO_KEY }} | |
| CODESIGN_URL: ${{ secrets.CODESIGN_URL }} | |
| CODESIGN_CLIENT_CERT: ${{ secrets.CODESIGN_CLIENT_CERT }} | |
| CODESIGN_CLIENT_KEY: ${{ secrets.CODESIGN_CLIENT_KEY }} | |
| CODESIGN_NAME: Go Lift Code Sign | |
| CODESIGN_WEBSITE: https://github.com/golift/codesign | |
| MACOS_SIGN_P12: ${{ secrets.MACOS_SIGN_P12 }} | |
| MACOS_SIGN_PASSWORD: ${{ secrets.MACOS_SIGN_PASSWORD }} | |
| MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} | |
| MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} | |
| MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} | |
| docker: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: require-strict-semver | |
| run: | | |
| if ! [[ "${GITHUB_REF_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "ref ${GITHUB_REF_NAME} is not a strict vN.N.N tag" >&2 | |
| exit 1 | |
| fi | |
| - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - uses: docker/setup-buildx-action@37fe631027851001ddb9b187196cc803df7f5f0e # v4.3.0 | |
| - name: decide-tags | |
| id: tags | |
| run: | | |
| set -euo pipefail | |
| git fetch --tags --force | |
| image="ghcr.io/${{ github.repository }}" | |
| tags="${image}:${GITHUB_REF_NAME}" | |
| highest="$(git tag -l 'v*.*.*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1)" | |
| if [ "${highest}" = "${GITHUB_REF_NAME}" ]; then | |
| tags="${tags}"$'\n'"${image}:latest" | |
| fi | |
| { | |
| echo "tags<<EOF" | |
| echo "${tags}" | |
| echo "EOF" | |
| echo "date=$(git show -s --format=%cI "${GITHUB_SHA}")" | |
| # GoReleaser stamps {{.Version}} (no leading v); match it so the | |
| # image binary's -version agrees with the archive binary's. | |
| echo "version=${GITHUB_REF_NAME#v}" | |
| } >> "${GITHUB_OUTPUT}" | |
| - uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 | |
| with: | |
| context: . | |
| push: true | |
| provenance: true | |
| sbom: true | |
| tags: ${{ steps.tags.outputs.tags }} | |
| build-args: | | |
| VERSION=${{ steps.tags.outputs.version }} | |
| REVISION=${{ github.sha }} | |
| BUILDDATE=${{ steps.tags.outputs.date }} | |
| BRANCH=${{ github.ref_name }} | |
| # Plant/move the floating tags AFTER the release succeeds, and only when | |
| # this tag is the highest of its major/minor series so a backport cannot | |
| # regress uses: golift/codesign@v1. | |
| floating-tags: | |
| needs: [goreleaser, docker] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - name: move-floating-tags | |
| run: | | |
| set -euo pipefail | |
| tag="${GITHUB_REF_NAME}" | |
| if ! [[ "${tag}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "ref ${tag} is not a strict vN.N.N tag" >&2 | |
| exit 1 | |
| fi | |
| git fetch --tags --force | |
| highest() { | |
| git tag -l "$1" | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1 | |
| } | |
| major="${tag%%.*}" | |
| minor="${tag%.*}" | |
| advance() { | |
| local floater="$1" | |
| local pattern="$2" | |
| if [ "$(highest "${pattern}")" = "${tag}" ]; then | |
| git tag --force "${floater}" "${tag}" | |
| git push --force origin "${floater}" | |
| else | |
| echo "skip ${floater}: ${tag} is not the highest ${pattern}" | |
| fi | |
| } | |
| advance "${major}" "${major}.*" | |
| advance "${minor}" "${minor}.*" |