From a1947e590fb9405ea67883c39bf942e230bf4e25 Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Wed, 11 Mar 2026 13:14:33 +0000 Subject: [PATCH 1/4] feat: support pre-release tags in release pipeline Pre-release tags (e.g. v5.10.0-rc1) are now handled safely: - Tighten tag filter from v* to v[0-9]+.[0-9]+.[0-9]+* (semver only) - Mark GitHub releases as pre-release via GoReleaser prerelease: auto - Skip Homebrew/Scoop tap updates for pre-releases (skip_upload: auto) - Skip Cloudsmith upload for pre-releases (Makefile hyphen check) - Skip package repo upload (repogen/S3) for pre-releases - Add workflow_dispatch with inputs to opt-in to Homebrew and package repo uploads for testing pre-releases - Validate tag format in both push and workflow_dispatch triggers Closes CLI-111 Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 41 ++++++++++++++++++++++++++++++++--- .goreleaser.yaml | 5 +++++ Makefile | 6 ++++- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6b901b91..91879039 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,20 @@ name: Release on: push: tags: - - "v*" + - "v[0-9]+.[0-9]+.[0-9]+*" + workflow_dispatch: + inputs: + tag: + description: "Tag to release (e.g. v5.10.0-rc1)" + required: true + upload_homebrew: + description: "Upload to Homebrew tap (normally skipped for pre-releases)" + type: boolean + default: false + upload_packages: + description: "Upload to package repositories (normally skipped for pre-releases)" + type: boolean + default: false permissions: contents: write @@ -14,9 +27,25 @@ jobs: environment: production steps: + - name: Resolve tag + id: tag + run: | + TAG="${{ inputs.tag || github.ref_name }}" + if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+'; then + echo "::error::Tag '$TAG' does not match semver format (vMAJOR.MINOR.PATCH)" + exit 1 + fi + echo "tag=$TAG" >> "$GITHUB_OUTPUT" + if [[ "$TAG" == *-* ]]; then + echo "is_prerelease=true" >> "$GITHUB_OUTPUT" + else + echo "is_prerelease=false" >> "$GITHUB_OUTPUT" + fi + - name: Check out repository code uses: actions/checkout@v4 with: + ref: ${{ steps.tag.outputs.tag }} fetch-depth: 0 - name: Setup Go @@ -86,8 +115,12 @@ jobs: - name: Install Go tools run: make goreleaser repogen + - name: Override Homebrew skip_upload + if: inputs.upload_homebrew == true + run: grep -v 'skip_upload' .goreleaser.yaml > .goreleaser.yaml.tmp && mv .goreleaser.yaml.tmp .goreleaser.yaml + - name: Build release (tag) - if: startsWith(github.ref, 'refs/tags/') + if: startsWith(github.ref, 'refs/tags/') || inputs.tag env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} RSA_SIGNING_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/rsa-signing-key.pem @@ -96,13 +129,14 @@ jobs: run: make release - name: Build snapshot (branch) - if: "!startsWith(github.ref, 'refs/tags/')" + if: "!startsWith(github.ref, 'refs/tags/') && !inputs.tag" env: RSA_SIGNING_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/rsa-signing-key.pem GPG_SIGNING_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/gpg-signing-key.asc run: make snapshot - name: Configure AWS credentials + if: steps.tag.outputs.is_prerelease == 'false' || inputs.upload_packages == true uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -110,6 +144,7 @@ jobs: aws-region: eu-west-1 - name: Upload packages to repository + if: steps.tag.outputs.is_prerelease == 'false' || inputs.upload_packages == true env: GPG_PRIVATE_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/gpg-signing-key.asc RSA_PRIVATE_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/rsa-signing-key.pem diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2b8342c0..e6a645c9 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -96,6 +96,7 @@ release: github: owner: upsun name: cli + prerelease: auto footer: | ## Upgrade @@ -146,6 +147,7 @@ archives: brews: - name: platformsh-cli + skip_upload: auto repository: owner: upsun name: homebrew-tap @@ -176,6 +178,7 @@ brews: system "#{bin}/platform --version" - name: upsun-cli + skip_upload: auto repository: owner: upsun name: homebrew-tap @@ -207,6 +210,7 @@ brews: scoops: - name: platform + skip_upload: auto repository: owner: upsun name: homebrew-tap @@ -228,6 +232,7 @@ scoops: - extras/vcredist2022 - name: upsun + skip_upload: auto repository: owner: upsun name: homebrew-tap diff --git a/Makefile b/Makefile index 0a89d638..76aa6d45 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,11 @@ ifndef GPG_SIGNING_KEY_FILE $(error GPG_SIGNING_KEY_FILE is not set. Set it to the path of your GPG private key for RPM signing.) endif PHP_VERSION=$(PHP_VERSION) goreleaser release --clean - VERSION=$(VERSION) bash cloudsmith.sh + @if echo "$(VERSION)" | grep -qv -- '-'; then \ + VERSION=$(VERSION) bash cloudsmith.sh; \ + else \ + echo "Skipping Cloudsmith upload for pre-release version $(VERSION)"; \ + fi .PHONY: test # "We encourage users of encoding/json to test their programs with GOEXPERIMENT=jsonv2 enabled" (https://tip.golang.org/doc/go1.25) From 94ae725e3cb027a46e448dad933a96a9daa6c7c2 Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Wed, 11 Mar 2026 13:20:12 +0000 Subject: [PATCH 2/4] fix: anchor tag validation regex and use sed for skip_upload override - Anchor the semver regex with $ and allow optional pre-release (-rc1) and build metadata (+build.123) suffixes per semver spec. - Use sed instead of grep -v to override skip_upload, replacing the value rather than removing the line. - Quote the sed command to avoid YAML parsing issues. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 91879039..a2c7db3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,7 +31,7 @@ jobs: id: tag run: | TAG="${{ inputs.tag || github.ref_name }}" - if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+'; then + if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$'; then echo "::error::Tag '$TAG' does not match semver format (vMAJOR.MINOR.PATCH)" exit 1 fi @@ -117,7 +117,7 @@ jobs: - name: Override Homebrew skip_upload if: inputs.upload_homebrew == true - run: grep -v 'skip_upload' .goreleaser.yaml > .goreleaser.yaml.tmp && mv .goreleaser.yaml.tmp .goreleaser.yaml + run: "sed -i 's/skip_upload: auto/skip_upload: false/' .goreleaser.yaml" - name: Build release (tag) if: startsWith(github.ref, 'refs/tags/') || inputs.tag From 3832ebc003e5179d03e2c0658bd5723dd6bdaf1a Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Wed, 11 Mar 2026 13:31:40 +0000 Subject: [PATCH 3/4] fix: improve workflow_dispatch inputs and tag detection - Rename upload_homebrew to upload_taps (also covers Scoop). - Rename upload_packages to upload_repos (clarity). - Improve descriptions to say "overrides pre-release skip". - Note in tag input description that the tag must already be pushed. - Set GORELEASER_CURRENT_TAG explicitly so goreleaser does not rely on git describe when triggered via workflow_dispatch. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a2c7db3a..bf8b70ee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,14 +7,14 @@ on: workflow_dispatch: inputs: tag: - description: "Tag to release (e.g. v5.10.0-rc1)" + description: "Tag to release (must already be pushed, e.g. v5.10.0-rc1)" required: true - upload_homebrew: - description: "Upload to Homebrew tap (normally skipped for pre-releases)" + upload_taps: + description: "Upload to Homebrew/Scoop taps (overrides pre-release skip)" type: boolean default: false - upload_packages: - description: "Upload to package repositories (normally skipped for pre-releases)" + upload_repos: + description: "Upload to package repositories via repogen (overrides pre-release skip)" type: boolean default: false @@ -115,13 +115,14 @@ jobs: - name: Install Go tools run: make goreleaser repogen - - name: Override Homebrew skip_upload - if: inputs.upload_homebrew == true + - name: Override tap skip_upload + if: inputs.upload_taps == true run: "sed -i 's/skip_upload: auto/skip_upload: false/' .goreleaser.yaml" - name: Build release (tag) if: startsWith(github.ref, 'refs/tags/') || inputs.tag env: + GORELEASER_CURRENT_TAG: ${{ steps.tag.outputs.tag }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} RSA_SIGNING_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/rsa-signing-key.pem GPG_SIGNING_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/gpg-signing-key.asc @@ -136,7 +137,7 @@ jobs: run: make snapshot - name: Configure AWS credentials - if: steps.tag.outputs.is_prerelease == 'false' || inputs.upload_packages == true + if: steps.tag.outputs.is_prerelease == 'false' || inputs.upload_repos == true uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -144,7 +145,7 @@ jobs: aws-region: eu-west-1 - name: Upload packages to repository - if: steps.tag.outputs.is_prerelease == 'false' || inputs.upload_packages == true + if: steps.tag.outputs.is_prerelease == 'false' || inputs.upload_repos == true env: GPG_PRIVATE_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/gpg-signing-key.asc RSA_PRIVATE_KEY_FILE: ${{ steps.signing-keys.outputs.key_dir }}/rsa-signing-key.pem From d94ce38d35768964d029ce0a6f8a8b3246d34306 Mon Sep 17 00:00:00 2001 From: Patrick Dawkins Date: Wed, 11 Mar 2026 13:33:25 +0000 Subject: [PATCH 4/4] fix: use glob-compatible tag filter pattern The tag filter uses fnmatch globs, not regex. The previous pattern v[0-9]+.[0-9]+.[0-9]+* treated + as a literal character and only matched single-digit version components. Use v[0-9]* (v followed by a digit) as a broad filter, and rely on the semver validation in the Resolve tag step for strict checking. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf8b70ee..fd2e5136 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: Release on: push: tags: - - "v[0-9]+.[0-9]+.[0-9]+*" + - "v[0-9]*" workflow_dispatch: inputs: tag: