From 9ac6a61bb9963b3bfde93356099eca81d5e238d6 Mon Sep 17 00:00:00 2001 From: daikiojm Date: Tue, 14 Jul 2026 09:43:06 +0900 Subject: [PATCH] ci(release): align release workflow with bitbank-lab-mcp - Restructure release.yml into 3 jobs (ci gate, npm-publish, github-release) - Trigger on v* tag push and workflow_dispatch instead of local npm version flow - Inject version from tag and sync plugin manifests / agents catalog at publish time - Add prerelease handling (alpha/beta/rc -> npm dist-tag beta, GitHub prerelease) - Add concurrency guard and production environment for publish - Drop scripts.version hook from package.json and update related docs --- .github/workflows/release.yml | 130 ++++++++++++++++++++++++++++------ CHANGELOG.md | 8 +++ CLAUDE.md | 3 +- CONTRIBUTING.md | 5 +- README.md | 4 +- docs/dev/README.md | 2 +- docs/dev/release.md | 95 ++++++++++++++++++------- package.json | 3 +- scripts/sync-version.mjs | 4 +- 9 files changed, 197 insertions(+), 57 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 480b4df..bfa911d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,41 +2,129 @@ name: Release on: push: - tags: - - "v[0-9]+.[0-9]+.[0-9]+" + tags: ['v*'] + workflow_dispatch: + inputs: + tag: + description: 'Tag to release (e.g. v0.5.0)' + required: true + +# Prevent concurrent releases +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: write jobs: - publish: + # ────────────────────────────────────────────── + # 1. CI gate — re-run full checks on tag code + # ────────────────────────────────────────────── + ci: runs-on: ubuntu-latest - permissions: - contents: read - id-token: write steps: - - uses: actions/checkout@v7 + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - - uses: actions/setup-node@v6 + - name: Setup Node + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version-file: '.nvmrc' - registry-url: "https://registry.npmjs.org" + cache: 'npm' # OIDC trusted publishing は npm >= 11.5.1、.npmrc の min-release-age は # npm >= 11.10 が必要(未満だと未知 config 警告が stderr に出て # E2E の「stderr 空」検証を壊す)。両方満たす版に固定する - - run: npm install -g npm@11.18.0 + - name: Pin npm + run: npm install -g npm@11.18.0 + + - name: Install deps + run: npm ci --ignore-scripts - - run: npm ci --ignore-scripts + - name: Lint (Biome) + run: npx biome check cli/ - - run: npx biome check cli/ - - run: npx tsc --noEmit - - run: npx vitest run + - name: Typecheck + run: npx tsc --noEmit - - name: Verify tag matches package.json version + - name: Test + run: npx vitest run + + # ────────────────────────────────────────────── + # 2. Publish to npm + # ────────────────────────────────────────────── + npm-publish: + needs: ci + runs-on: ubuntu-latest + environment: production + permissions: + id-token: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Setup Node + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: '.nvmrc' + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Pin npm + run: npm install -g npm@11.18.0 + + - name: Install deps + run: npm ci --ignore-scripts + + - name: Determine dist-tag + id: dist-tag + run: | + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + if echo "$TAG" | grep -qE '-(alpha|beta|rc)'; then + echo "tag=beta" >> "$GITHUB_OUTPUT" + else + echo "tag=latest" >> "$GITHUB_OUTPUT" + fi + + - name: Set version from tag and sync publish artifacts + run: | + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + VERSION="${TAG#v}" + npm version "$VERSION" --no-git-tag-version + node scripts/sync-version.mjs + npx tsx scripts/gen-agents-catalog.ts + + - name: Publish + run: npm publish --provenance --access public --tag ${{ steps.dist-tag.outputs.tag }} + + # ────────────────────────────────────────────── + # 3. Create GitHub Release + # ────────────────────────────────────────────── + github-release: + needs: npm-publish + runs-on: ubuntu-latest + environment: production + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + fetch-depth: 0 + + - name: Determine release metadata + id: meta run: | - PKG_VERSION=$(node -p "require('./package.json').version") - TAG_VERSION="${GITHUB_REF_NAME#v}" - if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then - echo "Tag $TAG_VERSION does not match package.json $PKG_VERSION" >&2 - exit 1 + TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}" + if echo "$TAG" | grep -qE '-(alpha|beta|rc)'; then + echo "prerelease=true" >> "$GITHUB_OUTPUT" + else + echo "prerelease=false" >> "$GITHUB_OUTPUT" fi - - run: npm publish --provenance --access public + - name: Create GitHub Release + uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1 + with: + tag_name: ${{ github.ref_name || github.event.inputs.tag }} + generate_release_notes: true + prerelease: ${{ steps.meta.outputs.prerelease }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 40167d3..5d2d639 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ ## [Unreleased] +### Changed + +- リリースワークフローを `bitbank-lab-mcp` に揃えた。`npm version ` の + ローカル前提を廃止し、tag push(`v*`)または `workflow_dispatch` で + `release.yml` が CI gate → version 注入・plugin manifest / agents カタログ同期 + → npm publish → GitHub Release 自動作成を実行する。OIDC trusted publisher の + environment は `production` に変更 + ### Added - README: Cursor 節を拡充。導入 2 経路(リポジトリを開くだけ / Plugin として diff --git a/CLAUDE.md b/CLAUDE.md index c09ac2d..411377e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -44,5 +44,6 @@ npx tsx cli/index.ts # CLI 実行 - コミット: `: <概要>`(日本語 OK) - 外部依存最小。`tsx` で直接実行。ビルドステップなし - 開発フェーズ → [`docs/dev/phases.md`](docs/dev/phases.md) -- リリース手順 → [`docs/dev/release.md`](docs/dev/release.md)(`npm version ` 経由で 5 ファイル同期。手動編集禁止) +- リリース手順 → [`docs/dev/release.md`](docs/dev/release.md)(tag push で release.yml が + version 注入・plugin manifest 同期・npm publish・GitHub Release を実行) - Skill 追加 → `.claude/rules/skills.md` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4f7942..e2e606f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,5 +68,6 @@ npx vitest run # テスト ## リリース(メンテナ向け) -npm publish とバージョン同期は `npm version ` 経由で行います(5 ファイルを自動同期、 -**手動編集禁止**)。手順は [docs/dev/release.md](docs/dev/release.md) を参照してください。 +npm publish は tag push で `.github/workflows/release.yml` が起動し、version 注入・ +plugin manifest 同期・agents カタログ再生成を経て publish する。手順は +[docs/dev/release.md](docs/dev/release.md) を参照してください。 diff --git a/README.md b/README.md index 2686186..1c54d7a 100644 --- a/README.md +++ b/README.md @@ -693,7 +693,9 @@ npm run typecheck # 型チェック ### リリース -npm publish 手順とバージョン同期の仕組みは [`docs/dev/release.md`](docs/dev/release.md) を参照。`npm version ` で 5 ファイル一括同期されるので、`package.json` や plugin manifest を手動編集しないこと。 +npm publish 手順は [`docs/dev/release.md`](docs/dev/release.md) を参照。`v*` tag を +push すると release workflow が version 注入・plugin manifest 同期・GitHub Release +作成まで実行する。 ### コントリビューター向けセットアップ diff --git a/docs/dev/README.md b/docs/dev/README.md index acd1165..15d5eb4 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -7,7 +7,7 @@ clone したユーザーは基本的に読む必要はない。 - `phases.md` — 開発フェーズの履歴と TODO - `conventions.md` — メンテナ向けのコード規約メモ -- `release.md` — リリース手順(`npm version ` で 5 ファイル同期) +- `release.md` — リリース手順(tag push → release.yml で version 注入・publish) - `repo-security.md` — GitHub / npm の管理者向け初期セットアップ 配布側ユーザーが参照すべきドキュメントは `docs/customization-guide.md` / diff --git a/docs/dev/release.md b/docs/dev/release.md index 49a7dc2..e5b90f0 100644 --- a/docs/dev/release.md +++ b/docs/dev/release.md @@ -1,49 +1,89 @@ # リリース手順 -`bitbank-lab-cli` の npm publish フロー。 +`bitbank-lab-cli` の npm publish フロー。`bitbank-lab-mcp` と同じ +tag 駆動 + GitHub Actions 多段階パイプライン。 + +## ワークフロー概要 + +`.github/workflows/release.yml` は 3 job で構成される: + +1. `ci` — tag 上のコードで lint / typecheck / test を再実行 +2. `npm-publish` — tag から version を注入し plugin manifest・agents カタログを + 同期してから `npm publish --provenance` +3. `github-release` — GitHub Release を自動作成(リリースノート自動生成) + +トリガー: + +- `v*` tag の push(通常ルート) +- `workflow_dispatch`(手動起動、tag 名を入力) ## バージョン同期 -`package.json` と plugin manifest 5 種(`.claude-plugin/plugin.json` / -`.cursor-plugin/plugin.json` / `.codex-plugin/plugin.json` / -`gemini-extension.json` / `plugin.json`)の 6 ファイルが同じ version を -持つ必要がある。**手動で個別編集しないこと**(同期漏れの温床)。 +publish 時に release workflow が以下を実行する(ローカルでの事前同期は不要): + +1. `npm version --no-git-tag-version` — `package.json` を tag に合わせる +2. `scripts/sync-version.mjs` — plugin manifest 5 種 + ルート `plugin.json` へ転写 +3. `scripts/gen-agents-catalog.ts` — `agents/tool-catalog.json` / + `agents/error-catalog.json` を再生成(`cli_version` を埋め込む) + +対象ファイル(計 6 + 生成物 2): + +- `package.json` +- `.claude-plugin/plugin.json` / `.cursor-plugin/plugin.json` / + `.codex-plugin/plugin.json` / `gemini-extension.json` / `plugin.json` +- `agents/tool-catalog.json` / `agents/error-catalog.json` ルートの `plugin.json` は Antigravity CLI(旧 Gemini CLI)のネイティブ plugin manifest。旧 CLI 互換の `gemini-extension.json` と両置きすることで 新旧どちらの CLI からもリモート install できる。 -`.claude-plugin/marketplace.json` も同じディレクトリにあるが、これは -plugin manifest ではなく marketplace カタログ。plugin の version 同期 -対象外なので `scripts/sync-version.mjs` の targets には入れない -(オプションの `version` フィールドを将来追加する場合も同様)。 +`.claude-plugin/marketplace.json` は marketplace カタログであり version 同期 +対象外(`scripts/sync-version.mjs` の targets に入れない)。 -`npm version ` 実行時に `scripts.version` フック経由で -`scripts/sync-version.mjs` が走り、`package.json` の新 version を -plugin manifest に転写してから commit + tag が作られる。 - -あわせて同フックが `scripts/gen-agents-catalog.ts` を再実行し、 -`agents/tool-catalog.json` / `agents/error-catalog.json`(どちらも -`cli_version` を埋め込む生成物)を新 version で再生成してステージする。 -これらは手書きせず常に再生成する。再生成漏れは x17 ドリフトテストが -CI で検出する(`cli/__tests__/chaos/conventions/x17-agents-catalog-drift.test.ts`)。 +main ブランチ上の `package.json` / plugin manifest は、公開済み npm version と +一致しないことがある(MCP と同様)。npm tarball 内では publish 直前に全て +揃う。 ## 手順 ```bash -npm version patch # 0.1.0 → 0.1.1 (6 ファイル同期 + commit + tag) -git push --follow-tags # tag を含めて push -# tag を push すると .github/workflows/release.yml が起動し、 -# OIDC trusted publishing 経由で `npm publish --provenance` を実行する。 -# 完了後に /tmp で動作確認 (鉄則) -cd /tmp && npx -y bitbank-lab-cli@<新 version> ticker btc_jpy +# 1. CHANGELOG の [Unreleased] を更新して main にマージ + +# 2. tag を作成して push +git tag v0.2.1 +git push origin v0.2.1 + +# tag push で release.yml が起動し、OIDC trusted publishing 経由で +# npm publish + GitHub Release が実行される。 + +# 3. 完了後に /tmp で動作確認 (鉄則) +cd /tmp && npx -y bitbank-lab-cli@0.2.1 ticker btc_jpy ``` +### prerelease + +`-alpha` / `-beta` / `-rc` を含む tag は npm dist-tag `beta` で公開され、 +GitHub Release は prerelease として作成される: + +```bash +git tag v0.3.0-beta.1 +git push origin v0.3.0-beta.1 +``` + +### 手動起動(workflow_dispatch) + +GitHub Actions の Release workflow から手動実行し、tag 名(例: `v0.2.1`)を +指定できる。通常は tag push で十分。 + ### 手動 publish(フォールバック) OIDC が使えない / workflow が失敗した場合の緊急用: ```bash +VERSION=0.2.1 +npm version "$VERSION" --no-git-tag-version +node scripts/sync-version.mjs +npx tsx scripts/gen-agents-catalog.ts npm publish --otp= ``` @@ -55,14 +95,15 @@ provenance 表示が無くなる点に注意。 1. https://www.npmjs.com/package/bitbank-lab-cli/access で "Trusted Publisher" を追加 2. GitHub repo: `bitbankinc/bitbank-lab-cli`、workflow: `release.yml`、 - environment は空でよい -3. アカウント側で 2FA を `auth-and-writes` に設定(手動 publish 時の保険) + environment: `production` +3. GitHub repo に `production` environment を作成(Settings → Environments) +4. アカウント側で 2FA を `auth-and-writes` に設定(手動 publish 時の保険) その他のリポジトリ側初回設定(branch protection / private vulnerability reporting 等)は [`repo-security.md`](repo-security.md) を参照。 `patch` / `minor` / `major` は SemVer に従う。0.x は SemVer 上 minor で -breaking 可なので初期改修は `npm version patch` で増やしていく。 +breaking 可なので初期改修は patch 相当の tag を増やしていく。 ## publish 後の検証 diff --git a/package.json b/package.json index 03b43e7..968cf40 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,7 @@ "lint": "biome check cli/", "lint:fix": "biome check --fix cli/", "format": "biome format --write cli/", - "typecheck": "tsc --noEmit", - "version": "node scripts/sync-version.mjs && tsx scripts/gen-agents-catalog.ts && git add .claude-plugin/plugin.json .cursor-plugin/plugin.json .codex-plugin/plugin.json gemini-extension.json plugin.json agents/tool-catalog.json agents/error-catalog.json" + "typecheck": "tsc --noEmit" }, "dependencies": { "pubnub": "^12.0.0", diff --git a/scripts/sync-version.mjs b/scripts/sync-version.mjs index 13ed6d2..ebe17b5 100755 --- a/scripts/sync-version.mjs +++ b/scripts/sync-version.mjs @@ -1,7 +1,7 @@ #!/usr/bin/env node // Sync version from package.json to plugin manifests. -// Wired into `npm version` lifecycle via scripts.version in package.json, -// so `npm version patch` updates all 6 files in one commit. +// Invoked by .github/workflows/release.yml after `npm version --no-git-tag-version` +// so the published tarball carries matching plugin manifest versions. // Regex (not JSON.parse → stringify) preserves each file's existing // indentation and key order. import { readFileSync, writeFileSync } from "node:fs";