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
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -278,13 +278,13 @@ lint-cli: ## CLI 代码检查
typecheck-cli: ## CLI 类型检查
cd cli && bun run typecheck

publish-cli: ## 发布 CLI(patch 版本)- bump + tag + push,触发 CI 自动发布
publish-cli: ## 发布 CLI(patch 版本)- 本地 build+test → 推 release 分支 → 开 PR,合并后手动 tag 触发 CI
./scripts/publish-cli.sh patch

publish-cli-minor: ## 发布 CLI(minor 版本)- bump + tag + push,触发 CI 自动发布
publish-cli-minor: ## 发布 CLI(minor 版本)- 本地 build+test → 推 release 分支 → 开 PR,合并后手动 tag 触发 CI
./scripts/publish-cli.sh minor

publish-cli-major: ## 发布 CLI(major 版本)- bump + tag + push,触发 CI 自动发布
publish-cli-major: ## 发布 CLI(major 版本)- 本地 build+test → 推 release 分支 → 开 PR,合并后手动 tag 触发 CI
./scripts/publish-cli.sh major

db-reset: ## 重置数据库
Expand Down
64 changes: 53 additions & 11 deletions cli/RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

## Overview

CLI releases are fully automated. Running `make publish-cli` on a clean `main` branch bumps the version, commits, creates a `cli-vX.Y.Z` tag, and pushes everything to origin. The GitHub Actions workflow [`release-cli.yml`](../.github/workflows/release-cli.yml) listens for the tag and handles build, test, npm publish, and GitHub Release creation.
CLI releases use a PR-based flow. Running `make publish-cli` on a clean `main` branch:

1. Runs local build-and-test (lint, typecheck, test, build)
2. Computes the next version from the latest `cli-v*` tag
3. Creates a `release/cli-vX.Y.Z` branch with the version bump committed
4. Pushes the branch and opens a PR to `main`

After the PR is merged, you manually tag and push — the tag triggers [`release-cli.yml`](../.github/workflows/release-cli.yml) which builds, publishes to npm, and creates a GitHub Release.

## Prerequisites

Expand All @@ -21,8 +28,9 @@ Configure in GitHub repository → Settings → Secrets and variables → Action

### Local Environment

- `node` and `npm` installed (the script uses `npm version` to bump)
- `git` installed with push access to the repository
- `node` and `bun` installed
- `gh` CLI installed and authenticated (`gh auth login`)
- `git` with push access to the repository
- On the `main` branch with a clean working tree

### Package Configuration
Expand All @@ -40,7 +48,7 @@ In [`cli/package.json`](./package.json):

## Release Process

### One-shot Release
### Step 1: Run the publish script

From the repository root, on a clean `main` branch:

Expand All @@ -52,15 +60,29 @@ make publish-cli-major # major: 0.1.5 -> 1.0.0

[`scripts/publish-cli.sh`](../scripts/publish-cli.sh) performs the following steps:

1. Verify the working tree is clean
2. Require the current branch to be `main`, otherwise abort
1. Verify `gh` CLI is installed and authenticated
2. Verify the working tree is clean and on `main`
3. `git pull --ff-only` from `origin/main`
4. Fetch remote tags and align `package.json` with the latest `cli-v*` tag
5. Compute the new version via `npm version <bump>`
6. Verify the new tag does not exist locally or on origin
7. After interactive confirmation: commit the bump, create the `cli-vX.Y.Z` tag, push both commit and tag to origin
4. Run full local build-and-test (lint, typecheck, test, build)
5. Compute the next version from the latest `cli-v*` tag
6. Verify the tag and release branch don't already exist
7. After interactive confirmation: create release branch, commit version bump, push, and open PR

### Step 2: Merge the PR

Review and merge the PR on GitHub as usual.

### Step 3: Tag and push

After the PR is merged:

```bash
git pull origin main
git tag cli-vX.Y.Z # replace with the actual version
git push origin cli-vX.Y.Z
```

Pushing the tag triggers CI — no further manual action required.
Pushing the tag triggers CI which builds, publishes to npm, and creates a GitHub Release.

### CI Workflow

Expand Down Expand Up @@ -104,6 +126,22 @@ From the Actions UI:
2. Enter an existing tag name matching `cli-vX.Y.Z`
3. Optionally enable skip npm publish

## Error Recovery

The script uses a cleanup state machine. If it fails at different stages:

- **Before push**: release branch is deleted locally, you're returned to `main`
- **After push, before PR**: the script prints recovery instructions (open PR manually or delete the remote branch)
- **After PR opened**: success — no cleanup needed

If you need to manually clean up a failed release:

```bash
git checkout main
git branch -D release/cli-vX.Y.Z # delete local branch
git push origin --delete release/cli-vX.Y.Z # delete remote branch (if pushed)
```

## Troubleshooting

### `releases must be cut from 'main'`
Expand All @@ -118,6 +156,10 @@ Commit or stash local changes first.

The previous release didn't clean up, or someone else released the same version. Check `git tag --list 'cli-v*'` and remote tags, then retry with a higher version.

### `branch release/cli-vX.Y.Z already exists`

A previous release attempt left a stale branch. Delete it locally and/or on origin, then retry.

### npm Publish Fails

- **403 with 2FA message**: `NPM_TOKEN` is not an Automation Token, or bypass 2FA is not enabled — regenerate with the correct type
Expand Down
Loading
Loading