From 7d49e2fe81d23f13eccbd11224dd31e329f55bc3 Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 10:03:15 +0100 Subject: [PATCH 1/7] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20skip-prerelea?= =?UTF-8?q?se=20in=20create-release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/create-release.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index ffb42b2ac..43362c3d8 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -21,6 +21,11 @@ on: description: 'For stable/latest: type the branch name to confirm (e.g., "main")' required: false type: string + skip_prerelease: + description: 'Skip pre-release requirement and publish stable/latest directly (⚠️ WARN: Use with caution)' + required: false + type: boolean + default: false jobs: create-release-pr: @@ -170,7 +175,7 @@ jobs: yarn changeset pre enter ${{ inputs.release_type }} - name: Validate latest release eligibility - if: (inputs.release_type == 'latest' || inputs.release_type == 'stable') && steps.check-prerelease.outputs.prerelease != 'true' + if: (inputs.release_type == 'latest' || inputs.release_type == 'stable') && steps.check-prerelease.outputs.prerelease != 'true' && inputs.skip_prerelease != true run: | echo "👹 Oops! Cannot release 'latest' without a pre-release version first..." echo "💡 You must release through 'test' or 'rc' before creating a stable release." @@ -234,7 +239,7 @@ jobs: echo "🤖 Target version is $TARGET_VERSION" echo "🤖 Maintenance branch would be $MAINTENANCE_BRANCH" - if [[ "$CURRENT_BRANCH" == "main" ]]; then + if [[ "$CURRENT_BRANCH" == "main" ]] && [[ "${{ inputs.skip_prerelease }}" != "true" ]]; then if git ls-remote --exit-code --heads origin "$MAINTENANCE_BRANCH" >/dev/null 2>&1; then echo "⚠️ WARNING: Maintenance branch '$MAINTENANCE_BRANCH' already exists for version $BASE_VERSION." echo "💡 Please checkout the branch $MAINTENANCE_BRANCH and create the release from there to ensure proper version line maintenance." From f90a7a2a0fbde76e64a8d2f98ecd9b75cd3685fc Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 10:06:45 +0100 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20skip-prerelea?= =?UTF-8?q?se=20support=20in=20release-publisher?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/create-release.yml | 2 +- .github/workflows/release-publisher.yml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 43362c3d8..61ca964f9 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -254,7 +254,7 @@ jobs: run: | # WARNING: This is coupled with a verify release commit # if you need to modify, apply the changes accordingly - COMMIT_TITLE=$(.scripts/bash/generate-release-commit-message "${{ steps.version-package.outputs.version }}" "${{ inputs.release_type }}") + COMMIT_TITLE=$(.scripts/bash/generate-release-commit-message "${{ steps.version-package.outputs.version }}" "${{ inputs.release_type }}" "${{ inputs.skip_prerelease }}") echo "title=$COMMIT_TITLE" >> $GITHUB_OUTPUT echo "branch=changeset-release/v${{ steps.version-package.outputs.version }}-${{ inputs.release_type }}" >> $GITHUB_OUTPUT diff --git a/.github/workflows/release-publisher.yml b/.github/workflows/release-publisher.yml index 9b17eadc5..0684e1090 100644 --- a/.github/workflows/release-publisher.yml +++ b/.github/workflows/release-publisher.yml @@ -39,11 +39,13 @@ jobs: if OUTPUT=$(.scripts/bash/verify-release-commit "$COMMIT_MSG"); then VERSION=$(echo "$OUTPUT" | awk '{print $1}') RELEASE_TYPE=$(echo "$OUTPUT" | awk '{print $2}') + SKIP_PRERELEASE=$(echo "$OUTPUT" | awk '{print $3}') echo "✅ Detected release PR merge for version $VERSION ($RELEASE_TYPE)" echo "is_release=true" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT echo "tag=v$VERSION" >> $GITHUB_OUTPUT echo "release_type=$RELEASE_TYPE" >> $GITHUB_OUTPUT + echo "skip_prerelease=$SKIP_PRERELEASE" >> $GITHUB_OUTPUT else echo "⚠️ This is not a release PR merge. Skipping release." echo "is_release=false" >> $GITHUB_OUTPUT @@ -63,7 +65,7 @@ jobs: echo "🤖 Current branch is $CURRENT_BRANCH" echo "🤖 Maintenance branch is $MAINTENANCE_BRANCH" - if [[ "$CURRENT_BRANCH" == "main" ]]; then + if [[ "$CURRENT_BRANCH" == "main" ]] && [[ "${{ steps.verify-merge.outputs.skip_prerelease }}" != "true" ]]; then if git ls-remote --exit-code --heads origin "$MAINTENANCE_BRANCH" >/dev/null 2>&1; then echo "⚠️ WARNING: Maintenance branch '$MAINTENANCE_BRANCH' already exists. Are you trying to update an existing pre-release version?" echo "💡 Please checkout the branch $MAINTENANCE_BRANCH and create the release from there to ensure proper version line maintenance, please!" From 2f89af29880a3323a2f352dfe82fd8895ede60c9 Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 10:14:31 +0100 Subject: [PATCH 3/7] =?UTF-8?q?docs:=20=F0=9F=93=9D=20add=20skip=20pre-rel?= =?UTF-8?q?ease=20warning=20to=20README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index b1fa3b207..2cc52f280 100644 --- a/README.md +++ b/README.md @@ -610,6 +610,9 @@ Use the [Create a new release Pull Request](./docs/package-release.md#create-a-n See [Package Release](./docs/package-release.md) for detailed instructions, including use-cases. +> [!CAUTION] +> A `skip_prerelease` option exists for emergency scenarios but **bypasses quality safeguards**. Only use when absolutely necessary. See [emergency release documentation](./docs/package-release.md#emergency-release-with-skip-prerelease). + ### Component RFC To propose a new component, open an RFC using the [Component RFC template](https://github.com/ClickHouse/click-ui/compare/main...branchName?template=component_rfc.md). From 00ccc725e636a71b6ada6779ea6f0f38fe4ecf80 Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 10:20:41 +0100 Subject: [PATCH 4/7] =?UTF-8?q?docs:=20=F0=9F=93=9D=20add=20skip=20pre-rel?= =?UTF-8?q?ease=20and=20emergency=20release=20to=20package-release.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/package-release.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/package-release.md b/docs/package-release.md index e58a97a23..78e7aa03a 100644 --- a/docs/package-release.md +++ b/docs/package-release.md @@ -16,6 +16,7 @@ - [Create a new release](#create-a-new-release) - [Updating a pending release version](#updating-a-pending-release-version) - [Promoting to stable release](#promoting-to-stable-release) + - [Emergency release with skip prerelease](#emergency-release-with-skip-prerelease) **TLDR;** Use the [Create a new release Pull Request](#create-a-new-release-pull-request) for automated process. @@ -60,6 +61,9 @@ You can find the pull requests in the GitHub tab [Pull Request](https://github.c > Releasing a "stable" or "latest" version requires that you have previously published a pre-release version (e.g. test or rc / release candidate). This process exists to help us maintain quality standards. > Only promote a release to "stable" or "latest" when you are confident it is production-ready, e.g., after thorough testing and gathering feedback from users or consumers. Take extra caution with "latest" in particular, as it becomes the default version installed by users. +> [!CAUTION] +> The workflow includes a `skip_prerelease` option that bypasses both the prerelease requirement and maintenance branch safeguards. **Use only in emergencies** (e.g., critical security hotfixes). This publishes directly from `main` without validation, increasing risk of shipping untested code to production. + Once the pull request is approved and merged, it'll trigger the release of a new version to [npm registry](https://www.npmjs.com/package/@clickhouse/click-ui?activeTab=versions). The process will also create a branch for long lived version maintenance support, e.g. `chore/v0.5.0-rc.1`. @@ -258,3 +262,28 @@ git push origin chore/sync-v1.0.0-changes-back-to-main > [!IMPORTANT] > This step is critical. The `main` branch must reflect the stable release state to ensure future pre-releases start from the correct version baseline. + +### Emergency release with skip prerelease + +In exceptional circumstances (e.g., critical security vulnerabilities), you may need to publish a `stable` or `latest` release immediately without a prerelease. + +> [!CAUTION] +> This bypasses quality safeguards. Only use when the risk of **not** releasing immediately exceeds the risk of potential regressions. + +Follow these steps: + +1. Ensure the fix is committed to `main` and thoroughly tested locally + +2. Run the [Create Release](https://github.com/ClickHouse/click-ui/actions/workflows/create-release.yml) workflow from `main`: + - Select `stable` or `latest` as the release type + - **Enable `skip_prerelease`** (checkbox in the workflow inputs) + - Confirm the release type and branch name + +3. Review the PR carefully (there is no pre-release validation) + +4. Squash and merge when confident + +The commit message will include a `[skip-prerelease]` marker for audit purposes. After release, verify the fix in production immediately and prepare/update a proper maintenance release if needed. + +> [!WARN] +> In the scenario where you skip the release-cycle and a maintenance branch's already exist, you may be interested in updating it by cherry-picking any critical changes, e.g. made a stable/latest release for `v1.6.0` from `main` which might contain changes not reflected in maintenance branch `chore/v1.6.0`. From d9501734b35a2dc88b43f12c947d6425bb8582d4 Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 10:31:22 +0100 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20=F0=9F=A4=96=20add=20skip-prerelea?= =?UTF-8?q?se=20support=20in=20generate=20and=20verify=20release=20commit?= =?UTF-8?q?=20msg=20scripts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .scripts/bash/generate-release-commit-message | 7 ++++++- .scripts/bash/verify-release-commit | 13 ++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.scripts/bash/generate-release-commit-message b/.scripts/bash/generate-release-commit-message index 31985928d..fa45ce940 100755 --- a/.scripts/bash/generate-release-commit-message +++ b/.scripts/bash/generate-release-commit-message @@ -14,6 +14,7 @@ fi VERSION="$1" RELEASE_TYPE="$2" +SKIP_PRERELEASE="${3:-false}" if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then echo "👹 Oops! Invalid version format: '$VERSION'" @@ -28,4 +29,8 @@ if [[ ! "$RELEASE_TYPE" =~ ^(latest|rc|test|stable)$ ]]; then exit 1 fi -echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE})" +if [[ "$SKIP_PRERELEASE" == "true" ]]; then + echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE}) [skip-prerelease]" +else + echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE})" +fi diff --git a/.scripts/bash/verify-release-commit b/.scripts/bash/verify-release-commit index 9035b02ee..c8ad8091b 100755 --- a/.scripts/bash/verify-release-commit +++ b/.scripts/bash/verify-release-commit @@ -13,7 +13,7 @@ fi COMMIT_MSG="$1" -RELEASE_PATTERN='^chore: 🤖 release v([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?) \((latest|rc|test|stable)\)( \(#[0-9]+\)| #[0-9]+)?$' +RELEASE_PATTERN='^chore: 🤖 release v([0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?) \((latest|rc|test|stable)\)( \[skip-prerelease\])?( \(#[0-9]+\)| #[0-9]+)?$' if [[ -z "$COMMIT_MSG" ]]; then echo "👹 Oops! Commit message is empty" @@ -50,14 +50,21 @@ if [[ ! "$COMMIT_MSG" =~ $RELEASE_PATTERN ]]; then exit 1 fi -if [[ "$COMMIT_MSG" =~ ^chore:\ 🤖\ release\ v([0-9.a-zA-Z-]+)\ \((latest|rc|test|stable)\) ]]; then +if [[ "$COMMIT_MSG" =~ ^chore:\ 🤖\ release\ v([0-9.a-zA-Z-]+)\ \((latest|rc|test|stable)\)(.*)$ ]]; then VERSION="${BASH_REMATCH[1]}" RELEASE_TYPE="${BASH_REMATCH[2]}" + SUFFIX="${BASH_REMATCH[3]}" + + if [[ "$SUFFIX" =~ \[skip-prerelease\] ]]; then + SKIP_PRERELEASE="true" + else + SKIP_PRERELEASE="false" + fi else echo "🦖 Skip! Failed to extract version and release type" exit 1 fi -echo "${VERSION} ${RELEASE_TYPE}" +echo "${VERSION} ${RELEASE_TYPE} ${SKIP_PRERELEASE}" exit 0 From 784e587ab3d9f64ce52ba25fb067f4d5aa41287d Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 11:14:24 +0100 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20correct=20github=20wa?= =?UTF-8?q?rning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/package-release.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/package-release.md b/docs/package-release.md index 78e7aa03a..0df1985be 100644 --- a/docs/package-release.md +++ b/docs/package-release.md @@ -285,5 +285,5 @@ Follow these steps: The commit message will include a `[skip-prerelease]` marker for audit purposes. After release, verify the fix in production immediately and prepare/update a proper maintenance release if needed. -> [!WARN] +> [!WARNING] > In the scenario where you skip the release-cycle and a maintenance branch's already exist, you may be interested in updating it by cherry-picking any critical changes, e.g. made a stable/latest release for `v1.6.0` from `main` which might contain changes not reflected in maintenance branch `chore/v1.6.0`. From c28946e23784ea766102f1cd8339ae7275c47d7e Mon Sep 17 00:00:00 2001 From: Helder Oliveira Date: Mon, 13 Apr 2026 11:24:15 +0100 Subject: [PATCH 7/7] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20generate=20and?= =?UTF-8?q?=20verify=20commit=20msg=20use=20term=20skip=5Fprerelease?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release-publisher.yml | 4 ++-- .scripts/bash/generate-release-commit-message | 14 ++++++++++---- .scripts/bash/verify-release-commit | 10 ++++++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release-publisher.yml b/.github/workflows/release-publisher.yml index 0684e1090..c264ce137 100644 --- a/.github/workflows/release-publisher.yml +++ b/.github/workflows/release-publisher.yml @@ -35,7 +35,7 @@ jobs: # WARNING: This is coupled with generate release commit # if you need to modify, apply the changes accordingly - # Script outputs "VERSION RELEASE_TYPE" on success (e.g., "1.2.3 latest") + # Script outputs "VERSION RELEASE_TYPE [skip_prerelease]" on success (e.g., "1.2.3 latest" or "1.2.3 latest skip_prerelease") if OUTPUT=$(.scripts/bash/verify-release-commit "$COMMIT_MSG"); then VERSION=$(echo "$OUTPUT" | awk '{print $1}') RELEASE_TYPE=$(echo "$OUTPUT" | awk '{print $2}') @@ -65,7 +65,7 @@ jobs: echo "🤖 Current branch is $CURRENT_BRANCH" echo "🤖 Maintenance branch is $MAINTENANCE_BRANCH" - if [[ "$CURRENT_BRANCH" == "main" ]] && [[ "${{ steps.verify-merge.outputs.skip_prerelease }}" != "true" ]]; then + if [[ "$CURRENT_BRANCH" == "main" ]] && [[ "${{ steps.verify-merge.outputs.skip_prerelease }}" != "skip_prerelease" ]]; then if git ls-remote --exit-code --heads origin "$MAINTENANCE_BRANCH" >/dev/null 2>&1; then echo "⚠️ WARNING: Maintenance branch '$MAINTENANCE_BRANCH' already exists. Are you trying to update an existing pre-release version?" echo "💡 Please checkout the branch $MAINTENANCE_BRANCH and create the release from there to ensure proper version line maintenance, please!" diff --git a/.scripts/bash/generate-release-commit-message b/.scripts/bash/generate-release-commit-message index fa45ce940..79488103e 100755 --- a/.scripts/bash/generate-release-commit-message +++ b/.scripts/bash/generate-release-commit-message @@ -1,9 +1,10 @@ #!/bin/bash # Generate standardized release commit message -# Usage: generate-release-commit-message -# Example: generate-release-commit-message 1.2.3 latest -# Output: chore: 🤖 release v1.2.3 (latest) +# Usage: generate-release-commit-message [skip_prerelease] +# Example: generate-release-commit-message 1.2.3 latest true +# Output: chore: 🤖 release v1.2.3 (latest) [skip-prerelease] +# Note: skip_prerelease only applies to stable/latest releases if [[ $# -lt 2 ]]; then echo "👹 Oops! Missing arguments" >&2 @@ -30,7 +31,12 @@ if [[ ! "$RELEASE_TYPE" =~ ^(latest|rc|test|stable)$ ]]; then fi if [[ "$SKIP_PRERELEASE" == "true" ]]; then - echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE}) [skip-prerelease]" + if [[ "$RELEASE_TYPE" == "stable" || "$RELEASE_TYPE" == "latest" ]]; then + echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE}) [skip-prerelease]" + else + echo "⚠️ Warning: skip_prerelease has no effect on ${RELEASE_TYPE} releases" >&2 + echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE})" + fi else echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE})" fi diff --git a/.scripts/bash/verify-release-commit b/.scripts/bash/verify-release-commit index c8ad8091b..d8662b6c7 100755 --- a/.scripts/bash/verify-release-commit +++ b/.scripts/bash/verify-release-commit @@ -3,7 +3,7 @@ # Verify that a commit message matches the expected release format # Usage: verify-release-commit # Returns: 0 if valid, 1 if invalid -# On success: outputs "VERSION RELEASE_TYPE" (e.g., "1.2.3 latest") +# On success: outputs "VERSION RELEASE_TYPE [skip_prerelease]" (e.g., "1.2.3 latest" or "1.2.3 latest skip_prerelease") # On failure: outputs error messages to stderr only if [[ $# -lt 1 ]]; then @@ -57,14 +57,16 @@ if [[ "$COMMIT_MSG" =~ ^chore:\ 🤖\ release\ v([0-9.a-zA-Z-]+)\ \((latest|rc|t if [[ "$SUFFIX" =~ \[skip-prerelease\] ]]; then SKIP_PRERELEASE="true" - else - SKIP_PRERELEASE="false" fi else echo "🦖 Skip! Failed to extract version and release type" exit 1 fi -echo "${VERSION} ${RELEASE_TYPE} ${SKIP_PRERELEASE}" +if [[ "$SKIP_PRERELEASE" == "true" ]]; then + echo "${VERSION} ${RELEASE_TYPE} skip_prerelease" +else + echo "${VERSION} ${RELEASE_TYPE}" +fi exit 0