v2 #3
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: | |
| # Trigger on push to main for Release PR creation/update | |
| push: | |
| branches: | |
| - main | |
| # Trigger on PR events for dry-run checks | |
| pull_request: | |
| types: | |
| - opened | |
| - synchronize | |
| branches: | |
| - main | |
| - "release/v*" | |
| # Manual trigger for emergency releases | |
| workflow_dispatch: | |
| inputs: | |
| force_release: | |
| description: "Force a release even if no changes" | |
| required: false | |
| type: boolean | |
| default: true | |
| concurrency: | |
| group: release-${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} | |
| cancel-in-progress: true | |
| env: | |
| GO_VERSION: "1.26.1" | |
| INITIAL_VERSION: "v0.1.0" | |
| NODE_VERSION: "22" | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| PR_RELEASE_MODULE: github.com/productize/releasepr@v0.0.21 | |
| permissions: | |
| contents: write | |
| packages: write | |
| pull-requests: write | |
| id-token: write | |
| attestations: write | |
| jobs: | |
| # Job 1: Create or update Release PR | |
| 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@v6 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| env: | |
| GOTMPDIR: ${{ runner.temp }}/go-tmp | |
| run: mkdir -p "$GOTMPDIR" | |
| - uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: "false" | |
| - uses: ./.github/actions/setup-node | |
| - 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 }} | |
| GOTMPDIR: ${{ runner.temp }}/go-tmp | |
| run: | | |
| go run "${{ env.PR_RELEASE_MODULE }}" pr-release --force --enable-rollback --ci-output | |
| # Job 2: Dry-run checks on Release PR | |
| dry-run: | |
| name: Dry-Run Release Check | |
| if: | | |
| github.event_name == 'pull_request' && | |
| (startsWith(github.event.pull_request.title, 'ci(release): Release ') || | |
| startsWith(github.event.pull_request.title, 'release: Release ') || | |
| startsWith(github.base_ref, 'release/v')) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| env: | |
| GOTMPDIR: ${{ runner.temp }}/go-tmp | |
| run: mkdir -p "$GOTMPDIR" | |
| - uses: ./.github/actions/setup-go | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| install-tools: false | |
| - uses: ./.github/actions/setup-node | |
| - name: Setup Release Tools | |
| uses: ./.github/actions/setup-release | |
| with: | |
| goreleaser-distribution: goreleaser | |
| setup-docker: false | |
| setup-docker-login: false | |
| - name: Run Dry-Run Orchestrator | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} | |
| GITHUB_HEAD_REF: ${{ github.head_ref }} | |
| GITHUB_ISSUE_NUMBER: ${{ github.event.pull_request.number }} | |
| GOTMPDIR: ${{ runner.temp }}/go-tmp | |
| run: go run "${{ env.PR_RELEASE_MODULE }}" dry-run --ci-output | |
| # Job 3: Production release on merge | |
| release: | |
| name: Production Release | |
| if: | | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/main' && | |
| (contains(github.event.head_commit.message, 'ci(release):') || | |
| startsWith(github.event.head_commit.message, 'release:')) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 120 | |
| env: | |
| DOCKER_CLI_EXPERIMENTAL: enabled | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Prepare Go temporary directory | |
| env: | |
| GOTMPDIR: ${{ runner.temp }}/go-tmp | |
| run: 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 | |
| - name: Setup Release Tools | |
| uses: ./.github/actions/setup-release | |
| with: | |
| goreleaser-distribution: goreleaser | |
| setup-docker: false | |
| setup-docker-login: false | |
| cosign-version: "v2.2.4" | |
| - name: Create Git Tag | |
| id: release-version | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| run: | | |
| # Use git-cliff to get the bumped version | |
| 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 "Created and pushed tag v$VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| 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 "Created and pushed tag v$VERSION" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "Could not extract version from any source. Got: $VERSION" | |
| exit 1 | |
| fi | |
| fi | |
| - uses: goreleaser/goreleaser-action@v6 | |
| with: | |
| distribution: goreleaser | |
| version: ~> v2 | |
| args: >- | |
| release --clean | |
| --release-header-tmpl=.goreleaser.release-header.md.tmpl | |
| --release-footer-tmpl=.goreleaser.release-footer.md.tmpl | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} | |
| COSIGN_EXPERIMENTAL: 1 | |
| GOTMPDIR: ${{ runner.temp }}/go-tmp | |
| - name: Build npm CLI package | |
| run: >- | |
| node npm/cli/prepare-package.mjs | |
| --version "${{ steps.release-version.outputs.version }}" | |
| --dist dist | |
| --out dist/npm/@productize/cli | |
| - name: Publish npm CLI package | |
| run: npm publish dist/npm/@productize/cli --access public |