diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..717ce20c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,76 @@ +name: Release + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + version: + description: 'Version to validate (e.g. 0.73.0).' + type: string + required: true + +permissions: + contents: write + +jobs: + release: + runs-on: macos-latest + environment: release + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v5 + with: + go-version: stable + + - name: Determine version + id: ver + run: | + if [ "${{ github.event_name }}" = "push" ]; then + v=${GITHUB_REF_NAME#v} + else + v='${{ inputs.version }}' + fi + echo "version=$v" >> "$GITHUB_OUTPUT" + echo "Resolved version: '$v'" + + - name: Verify version consistency + run: | + set -e + V='${{ steps.ver.outputs.version }}' + R=$(echo "$V" | sed 's/\./\\./g') + grep -q "^${R}$" CHANGELOG.md + grep -qF "\"fzf ${V}\"" man/man1/fzf.1 + grep -qF "\"fzf ${V}\"" man/man1/fzf-tmux.1 + grep -qF "${V}" install + grep -qF "${V}" install.ps1 + + - name: Extract release notes + run: | + set -e + mkdir -p tmp + V='${{ steps.ver.outputs.version }}' + R=$(echo "$V" | sed 's/\./\\./g') + sed -n "/^${R}$/,/^[0-9]/p" CHANGELOG.md \ + | tail -r | sed '1,/^ *$/d' | tail -r | sed '1,2d' \ + | tee tmp/release-note + + - name: Run goreleaser + uses: goreleaser/goreleaser-action@v6 + with: + version: latest + args: >- + ${{ github.event_name == 'push' + && 'release --clean --release-notes tmp/release-note' + || 'release --snapshot --clean --skip=publish' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + MACOS_SIGN_P12: ${{ secrets.MACOS_SIGN_P12 }} + MACOS_SIGN_PASSWORD: ${{ secrets.MACOS_SIGN_PASSWORD }} + MACOS_NOTARY_ISSUER_ID: ${{ secrets.MACOS_NOTARY_ISSUER_ID }} + MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} + MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..20600130 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,52 @@ +Release process +=============== + +Building, signing, notarizing, and publishing is handled by +[`.github/workflows/release.yml`](.github/workflows/release.yml), +triggered by a tag push. + +## Steps + +1. Update version in the following files and commit on `master`: + - `CHANGELOG.md` + - `main.go` + - `install` + - `install.ps1` + - `man/man1/fzf.1` + - `man/man1/fzf-tmux.1` + +2. Sign and push the tag. + + ```sh + export V=v0.73.0 + git tag -s $V -m $V + + # Push the tag only. master on origin still points to the old version, + # so /master/install keeps resolving against existing binaries during + # the publish window. + git push origin $V + ``` + +3. The workflow fires on the tag push and pauses on the `release` + environment gate. Approve it in the Actions tab to release. + +4. After the GitHub release is published, fast-forward `master`: + + ```sh + git push origin master + ``` + +## Testing the workflow + +To exercise the workflow without firing a real release: + +1. Actions tab -> **Release** -> **Run workflow**. +2. Pick a branch and enter the version currently on that branch + (the version-consistency check requires the input to match the + files in the checked-out tree). +3. Approve the `release` environment gate when prompted. +4. Goreleaser runs with `--snapshot --skip=publish`. Signing and + notarization run; only the GitHub release upload is skipped. + +Use this to validate the workflow YAML, version-extraction logic, +the macOS runner setup, and the signing/notarization credentials.