feat: implement okf standard (#25) #65
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: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: | |
| - opened | |
| - synchronize | |
| branches: | |
| - main | |
| - "release/v*" | |
| workflow_dispatch: | |
| inputs: | |
| force_release: | |
| description: "Force a release even if no changes" | |
| required: false | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: release-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} | |
| cancel-in-progress: true | |
| env: | |
| GO_VERSION: "1.24" | |
| INITIAL_VERSION: "v0.0.1" | |
| NODE_VERSION: "22" | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| PR_RELEASE_MODULE: github.com/compozy/releasepr@v0.0.15 | |
| permissions: | |
| contents: write | |
| packages: write | |
| pull-requests: write | |
| id-token: write | |
| attestations: write | |
| jobs: | |
| release-pr: | |
| name: Create/Update Release PR | |
| if: | | |
| (github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| !contains(github.event.head_commit.message, 'release:') && | |
| !startsWith(github.event.head_commit.message, 'ci(release):') && | |
| !startsWith(github.event.head_commit.message, 'Merge pull request') && | |
| github.event.head_commit.author.name != 'github-actions[bot]') || | |
| (github.event_name == 'workflow_dispatch') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| shell: bash | |
| run: | | |
| export GOTMPDIR="$RUNNER_TEMP/go-tmp" | |
| echo "GOTMPDIR=$GOTMPDIR" >> "$GITHUB_ENV" | |
| mkdir -p "$GOTMPDIR" | |
| - uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: "false" | |
| - uses: ./.github/actions/setup-git-cliff | |
| - name: Run PR Release Orchestrator | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} | |
| INITIAL_VERSION: ${{ env.INITIAL_VERSION }} | |
| run: | | |
| go run "${{ env.PR_RELEASE_MODULE }}" pr-release --force --enable-rollback --ci-output | |
| dry-run-split: | |
| name: Dry-Run Build (${{ matrix.id }}) | |
| if: | | |
| github.event_name == 'pull_request' && | |
| (startsWith(github.event.pull_request.title, 'ci(release): Release ') || | |
| startsWith(github.base_ref, 'release/v')) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: linux-amd64 | |
| runner: ubuntu-latest | |
| ggoos: linux | |
| ggoarch: amd64 | |
| - id: linux-arm64 | |
| runner: ubuntu-24.04-arm | |
| ggoos: linux | |
| ggoarch: arm64 | |
| - id: darwin-amd64 | |
| runner: macos-15-intel | |
| ggoos: darwin | |
| ggoarch: amd64 | |
| - id: darwin-arm64 | |
| runner: macos-latest | |
| ggoos: darwin | |
| ggoarch: arm64 | |
| - id: windows-amd64 | |
| runner: windows-latest | |
| ggoos: windows | |
| ggoarch: amd64 | |
| runs-on: ${{ matrix.runner }} | |
| env: | |
| GGOOS: ${{ matrix.ggoos }} | |
| GGOARCH: ${{ matrix.ggoarch }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| shell: bash | |
| run: | | |
| export GOTMPDIR="$RUNNER_TEMP/go-tmp" | |
| echo "GOTMPDIR=$GOTMPDIR" >> "$GITHUB_ENV" | |
| mkdir -p "$GOTMPDIR" | |
| - uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: false | |
| - name: Setup GoReleaser | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser-pro | |
| version: ~> v2 | |
| install-only: true | |
| - name: Run GoReleaser Dry-Run Split | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} | |
| run: goreleaser release --snapshot --clean --split | |
| - name: Pack GoReleaser shard | |
| shell: bash | |
| run: tar -czf "goreleaser-${{ matrix.id }}.tgz" -C dist . | |
| - name: Upload GoReleaser shard | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: goreleaser-${{ matrix.id }} | |
| path: goreleaser-${{ matrix.id }}.tgz | |
| if-no-files-found: error | |
| dry-run: | |
| name: Dry-Run Release Check | |
| if: | | |
| github.event_name == 'pull_request' && | |
| (startsWith(github.event.pull_request.title, 'ci(release): Release ') || | |
| startsWith(github.base_ref, 'release/v')) | |
| needs: dry-run-split | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| shell: bash | |
| run: | | |
| export GOTMPDIR="$RUNNER_TEMP/go-tmp" | |
| echo "GOTMPDIR=$GOTMPDIR" >> "$GITHUB_ENV" | |
| mkdir -p "$GOTMPDIR" | |
| - uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: false | |
| - name: Setup Release Tools | |
| uses: ./.github/actions/setup-release | |
| with: | |
| goreleaser-distribution: goreleaser-pro | |
| - name: Validate changelog generation | |
| run: git-cliff --unreleased --verbose | |
| - name: Download GoReleaser shards | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: goreleaser-* | |
| path: .artifacts | |
| - name: Restore GoReleaser dist | |
| shell: bash | |
| run: | | |
| mkdir -p dist | |
| find .artifacts -name '*.tgz' -print0 | while IFS= read -r -d '' archive; do | |
| tar -xzf "$archive" -C dist | |
| done | |
| - name: Merge GoReleaser Dry-Run | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} | |
| run: goreleaser continue --merge | |
| prepare-release-tag: | |
| name: Prepare Release Tag | |
| if: | | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| contains(github.event.head_commit.message, 'ci(release):') | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.create-tag.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - uses: ./.github/actions/setup-git-cliff | |
| - name: Create Git Tag | |
| id: create-tag | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| run: | | |
| VERSION=$(git cliff --bumped-version 2>/dev/null | sed 's/^v//') | |
| if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag -a "v$VERSION" -m "Release v$VERSION" | |
| git push origin "v$VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Created and pushed tag v$VERSION" | |
| else | |
| echo "Could not get version from git-cliff. Got: $VERSION" | |
| echo "Fallback: Extract from commit message" | |
| VERSION=$(git log -1 --pretty=format:"%s" | sed -E 's/.*Release v([0-9]+\.[0-9]+\.[0-9]+).*/\1/') | |
| if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git tag -a "v$VERSION" -m "Release v$VERSION" | |
| git push origin "v$VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Created and pushed tag v$VERSION" | |
| else | |
| echo "Could not extract version from any source. Got: $VERSION" | |
| exit 1 | |
| fi | |
| fi | |
| release-split: | |
| name: Release Build (${{ matrix.id }}) | |
| if: | | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| contains(github.event.head_commit.message, 'ci(release):') | |
| needs: prepare-release-tag | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - id: linux-amd64 | |
| runner: ubuntu-latest | |
| ggoos: linux | |
| ggoarch: amd64 | |
| - id: linux-arm64 | |
| runner: ubuntu-24.04-arm | |
| ggoos: linux | |
| ggoarch: arm64 | |
| - id: darwin-amd64 | |
| runner: macos-15-intel | |
| ggoos: darwin | |
| ggoarch: amd64 | |
| - id: darwin-arm64 | |
| runner: macos-latest | |
| ggoos: darwin | |
| ggoarch: arm64 | |
| - id: windows-amd64 | |
| runner: windows-latest | |
| ggoos: windows | |
| ggoarch: amd64 | |
| runs-on: ${{ matrix.runner }} | |
| env: | |
| GGOOS: ${{ matrix.ggoos }} | |
| GGOARCH: ${{ matrix.ggoarch }} | |
| GORELEASER_CURRENT_TAG: v${{ needs.prepare-release-tag.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| shell: bash | |
| run: | | |
| export GOTMPDIR="$RUNNER_TEMP/go-tmp" | |
| echo "GOTMPDIR=$GOTMPDIR" >> "$GITHUB_ENV" | |
| mkdir -p "$GOTMPDIR" | |
| - uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: false | |
| - name: Setup GoReleaser | |
| uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser-pro | |
| version: ~> v2 | |
| install-only: true | |
| - name: Run GoReleaser Split | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} | |
| run: goreleaser release --clean --split | |
| - name: Pack GoReleaser shard | |
| shell: bash | |
| run: tar -czf "goreleaser-${{ matrix.id }}.tgz" -C dist . | |
| - name: Upload GoReleaser shard | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: goreleaser-${{ matrix.id }} | |
| path: goreleaser-${{ matrix.id }}.tgz | |
| if-no-files-found: error | |
| release: | |
| name: Production Release | |
| if: | | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| contains(github.event.head_commit.message, 'ci(release):') | |
| needs: | |
| - prepare-release-tag | |
| - release-split | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| env: | |
| GORELEASER_CURRENT_TAG: v${{ needs.prepare-release-tag.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| shell: bash | |
| run: | | |
| export GOTMPDIR="$RUNNER_TEMP/go-tmp" | |
| echo "GOTMPDIR=$GOTMPDIR" >> "$GITHUB_ENV" | |
| mkdir -p "$GOTMPDIR" | |
| - name: Set up Go with caching | |
| uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: "true" | |
| - uses: ./.github/actions/setup-node | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Setup Release Tools | |
| uses: ./.github/actions/setup-release | |
| with: | |
| goreleaser-distribution: goreleaser-pro | |
| cosign-version: "v2.2.4" | |
| - name: Download GoReleaser shards | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: goreleaser-* | |
| path: .artifacts | |
| - name: Restore GoReleaser dist | |
| shell: bash | |
| run: | | |
| mkdir -p dist | |
| find .artifacts -name '*.tgz' -print0 | while IFS= read -r -d '' archive; do | |
| tar -xzf "$archive" -C dist | |
| done | |
| - name: Merge Production Release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| COSIGN_EXPERIMENTAL: 1 | |
| GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} | |
| run: goreleaser continue --merge |