Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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."
Expand Down Expand Up @@ -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."
Expand All @@ -249,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
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/release-publisher.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ 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}')
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
Expand All @@ -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 }}" != "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!"
Expand Down
19 changes: 15 additions & 4 deletions .scripts/bash/generate-release-commit-message
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#!/bin/bash

# Generate standardized release commit message
# Usage: generate-release-commit-message <version> <release_type>
# Example: generate-release-commit-message 1.2.3 latest
# Output: chore: 🤖 release v1.2.3 (latest)
# Usage: generate-release-commit-message <version> <release_type> [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
Expand All @@ -14,6 +15,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'"
Expand All @@ -28,4 +30,13 @@ if [[ ! "$RELEASE_TYPE" =~ ^(latest|rc|test|stable)$ ]]; then
exit 1
fi

echo "chore: 🤖 release v${VERSION} (${RELEASE_TYPE})"
if [[ "$SKIP_PRERELEASE" == "true" ]]; then
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
17 changes: 13 additions & 4 deletions .scripts/bash/verify-release-commit
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Verify that a commit message matches the expected release format
# Usage: verify-release-commit <commit_message>
# 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
Expand All @@ -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"
Expand Down Expand Up @@ -50,14 +50,23 @@ 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"
fi
else
echo "🦖 Skip! Failed to extract version and release type"
exit 1
fi

echo "${VERSION} ${RELEASE_TYPE}"
if [[ "$SKIP_PRERELEASE" == "true" ]]; then
echo "${VERSION} ${RELEASE_TYPE} skip_prerelease"
else
echo "${VERSION} ${RELEASE_TYPE}"
fi

exit 0
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
29 changes: 29 additions & 0 deletions docs/package-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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.

> [!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`.
Loading