リリース runbook
Crowi 2.0 のリリース手順 — changesets + npm Trusted Publishing(OIDC) + Docker(full/slim/web) + Elasticsearch カスタム image を CI で公開する
このページは Crowi 2.0 のメンテナ向けリリース runbook です。リリースの仕組みは 実装済みですが、実際の publish には 一度きりの外部設定(人手) が前提です。 このページはその外部設定と、通常リリースの流れ、channel 切替(alpha→beta→stable)、 Docker / Elasticsearch image の出し方をまとめます。
リリースは changesets +
npm Trusted Publishing(OIDC) + Docker buildx で自動化されています。
人間の判断は「GO ゲート」= main の Version PR をマージする 1 点だけ です。
push:main で changesets/action が Version PR を自動生成 / 更新し、それを
マージすると release.yml が npm へ publish、続いて Docker image が build+push
されます。
全体像
| フェーズ | トリガ | 担当 |
|---|---|---|
| changeset を貯める | feature を main にマージするたび | 開発者 |
| Version PR 生成 / 更新 | push: main(changesets/action) | CI(自動) |
| GO ゲート | Version PR をマージ | 人間 |
| npm publish(OIDC・provenance 付き) | Version PR のマージ後 | CI(release.yml) |
製品版タグ v<dist-version> 作成・push | publish 成功時のみ | CI(release.yml) |
| 製品版 GitHub Release(集約 release notes) | publish 成功時のみ | CI(release.yml) |
| Docker full / slim / web を multi-arch build+push | publish を伴う Release run の完了 | CI(docker.yml、workflow_run) |
| Elasticsearch カスタム image | 手動(workflow_dispatch) | 人間(Crowi 本体と独立) |
一度きりの手動セットアップ(外部・人手)
以下は CI からは実行できません。初回リリース前に 1 回だけ 手作業で設定します。
1. npm Trusted Publisher(公開 19 パッケージ)
npmjs.com で 公開 19 パッケージそれぞれ に Trusted Publisher を登録します
(repo crowi/crowi + workflow release.yml、必要なら environment)。これにより
長期 NPM_TOKEN 不要・provenance 付きの OIDC publish が成立します。対象:
@crowi/admin-cli
@crowi/api-contract
@crowi/api
@crowi/cli
@crowi/plugin-api
@crowi/plugin-aws
@crowi/plugin-mail-aws-ses
@crowi/plugin-mail-resend
@crowi/plugin-mail-smtp
@crowi/plugin-renderer-crowi-legacy
@crowi/plugin-renderer-emoji
@crowi/plugin-renderer-katex
@crowi/plugin-renderer-plantuml
@crowi/plugin-search-elasticsearch
@crowi/plugin-search-mongo
@crowi/plugin-search-opensearch
@crowi/plugin-storage-aws-s3
@crowi/plugin-storage-local
@crowi/runner2. GitHub: Actions に PR 作成を許可
repo Settings → Actions → General → Workflow permissions で
「Allow GitHub Actions to create and approve pull requests」を ON にします。
これが OFF だと changesets/action が Version PR を自動生成できません。
3. GitHub secret(Docker Hub)
Docker Hub は OIDC 非対応なので、Docker push 用に secret を 2 つ登録します。
| secret | 用途 |
|---|---|
DOCKERHUB_USERNAME | Docker Hub アカウント |
DOCKERHUB_TOKEN | Docker Hub アクセストークン |
4. toolchain(リポジトリ側・設定済み)
OIDC publish の前提は次の組合せです(CI 設定済み・参考情報)。
- pnpm 10.x(OIDC trusted publishing 対応。
pnpm publishが内部で npm CLI に委譲) - pnpm/action-setup@v6(pnpm v11.0.x の OIDC 回帰を避けるため v6.0.6 以上)
- Node 24(同梱 npm CLI ≥ 11.5.1 が OIDC publish の前提)
通常リリース(alpha.N)の流れ
- changeset を貯める。 feature を main にマージするたびに、ユーザー価値 1 単位
ごとに
.changeset/*.mdを追加します(pnpm changeset add)。内部リファクタや docs / chore は changeset 不要です。 - Version PR が自動生成される。
push: mainでchangesets/actionが 貯まった changeset を消費し、版を bump した Version PR を作成 / 更新します (alpha pre mode 中は-alpha.Nが出ます)。 - GO = Version PR をマージ。 PR の差分(版・CHANGELOG)をレビューして マージするのがリリースの GO 判断です。
- npm publish(自動)。 マージで
release.ymlが走り、pnpm changeset publishが OIDC trusted publishing(NPM_TOKEN不要・provenance 付き)で各パッケージを publish します。 - 製品版タグ(自動)。 publish 成功時のみ、独立した製品版タグ
v2.0.0-alpha.N(= 既存v2.0.0-alpha.*の最大 + 1)を作成・push し、dist-versionartifact を upload します。 - 製品版 GitHub Release(自動)。
scripts/aggregate-release-notes.mjsが 今回 publish された全@crowi/*のCHANGELOG.mdから該当バージョン section を集約し、カテゴリ別(core / SDK / plugin / tooling)にまとめた集約 release notes を生成。製品版タグに対してgh release createで 1 個の release ページ を作ります(prerelease かどうかは semver の-有無で自動判定)。changesets/actionが同時に作る per-package release(@crowi/api@<v>等)は それぞれの細かい履歴用に残しつつ、製品版タグ側に「この alpha.N で何が変わったか」 の operator-facing なまとめが立ちます。 - Docker image(自動)。 Release run の完了で
docker.ymlがworkflow_runで発火し、full / slim を multi-arch(amd64 + arm64)で build+push します。
GITHUB_TOKEN が push したタグは 他の workflow の on: push: tags を起動しません
(無限ループ防止のための GitHub の仕様)。このため docker.yml は製品版タグ push では
なく workflow_run(Release の完了) で発火し、Release run が upload した
dist-version artifact の有無で「publish があった run か」を判定します。
publish が無かった(Version PR を作っただけの)run では image を build しません。
製品版(distribution version)モデル
Docker image は npm 各パッケージの版とは 独立した「Crowi ディストリビューション版」 を持ちます。
- 毎リリース必ず +1。 plugin だけの patch リリースでも新しい製品版・新しい image を 出します。「同じタグで中身だけ変わる」immutable tag 原則違反を避けるためです。
- 採番は
v2.0.0-alpha.*git タグの最大 + 1。 npm 側の bump 有無と独立に必ず進みます。 - タグ規則:
- 不変:
crowi/crowi:2.0.0-alpha.N(full)/:2.0.0-alpha.N-slim(slim) - 移動:
:alpha/:alpha-slim(その channel の最新を指す) - web image:
crowi/crowi-web:2.0.0-alpha.N(不変)+ 移動タグ:alpha。Next.js レンダラ専用 image で full/slim の区別はなく 単一 image。packages/web/Dockerfileからdocker.ymlのbuild-webjob が api image と並行に multi-arch でビルド・push します。 - prerelease は
latestを奪いません。latest/latest-slimが v2 を指すのは stable 以降です(下記 channel 切替を参照)。
- 不変:
- 自己記述。 image には OCI ラベル
org.crowi.bundleでバンドルした各@crowi/*の版が 埋め込まれます(「この alpha.N に入っている@crowi/apiは?」をdocker buildx imagetools inspectで即答できます)。
per-plugin の patch リリース
特定 plugin だけを直したい(例: 依存のセキュリティ更新)場合:
- その plugin にだけ changeset を書く(
pnpm changeset addで該当パッケージを選ぶ)。 - 内部依存は
updateInternalDependencies: patchで消費者へ伝播 bump されます (例:@crowi/plugin-awsの更新 →@crowi/plugin-storage-aws-s3/@crowi/plugin-mail-aws-sesも patch)。 - 製品版が +1 され、full / slim image も再ビルド されます。full image は全 plugin を バンドルするため、plugin-only の修正でも image を再ビルドしないと利用者に届きません。 製品版が必ず +1 する設計でこれが保証されます。
運用方針: per-plugin の changeset は 貯めて GO 時にまとめて出す。都度リリースせず、 次の Version PR マージで一括して publish + 新 image を出すのが基本です。
channel の切替(pre-mode の出入り・手動)
alpha → beta → stable の切替だけは手動で、それぞれ PR 1 回 で行います。
alpha → beta
pnpm changeset pre exit
pnpm changeset pre enter betaこの変更(.changeset/pre.json)を PR にしてマージすると、以降の Version PR が
2.0.0-beta.0 から始まります。
beta → stable
pnpm changeset pre exitを PR にしてマージすると pre mode を抜け、stable の版が出ます。
latest が v2 を指すのは stable で初めて です(prerelease は latest を奪わない方針)。
npm の無印 crowi と Docker latest / latest-slim の v2 切替は
feature-crowi-quickstart-package と同期して行います。
製品版タグの形: prerelease では v2.0.0-alpha.N、stable では 4 セグメントの
v2.0.0.0(末尾が dist counter)になります。channel に pre 表記が無くなると
製品版は v<major.minor.patch>.<counter> の形になるためで、想定どおりの挙動です。
Docker 再ビルドの方針
- どのパッケージが上がっても、製品版が +1 され full / slim / web image が再ビルド+新タグ されます。 「Crowi リリース 1 回 = monorepo のあるスナップショット = image 1 セット」が原則です。
- 手動再ビルド が必要な場合は
docker.ymlのworkflow_dispatch(versioninput に 製品版タグ名を指定)で、既存の製品版を再ビルドできます。ビルドのみの Dockerfile/CI 修正を リリースタグを動かさずに 反映したいときはrefinput にビルド元ツリー(例:main)を 渡します(versionが image タグ、refがチェックアウトするツリーを決める)。
Elasticsearch カスタム image の出し方
検索プラグイン用の日本語アナライザ入り ES image(crowi/docker-elasticsearch)は
Crowi 本体のリリースと完全に独立 しています。docker-elasticsearch.yml を
workflow_dispatch(本命)または es-v* タグ push(補助)で回します。
- inputs:
es_version/sudachi_plugin_version/dict_version/variant(both/kuromoji/sudachi)。 - variant とタグ:
:<es>(kuromoji・既定。軽量):<es>-sudachi(kuromoji +analysis-sudachi+ SudachiDict core)- 移動タグ
:9(kuromoji)/:9-sudachi
- multi-arch(amd64 + arm64)で build+push します。
version pinning が必須。 analysis-sudachi は ES の patch version と完全一致 が
要ります。analysis-sudachi v3.6.0 が対応する ES 9.x は
9.0.8 / 9.1.10 / 9.2.8 / 9.3.4 / 9.4.1 です。SudachiDict は core
を既定(リリース日 20260428)にしています。
ES を bump するときは docker-elasticsearch.yml の env 既定 と
elasticsearch/Dockerfile.sudachi の ARG 既定 の 両方 を更新してください
(実行時は CI が --build-arg で明示渡しするため CI が正ですが、Dockerfile 既定は
ローカルビルド用の便宜値で、片方だけ直すと drift します)。
- SudachiDict の取得 は HTTP(S3 website endpoint。HTTPS 非対応)です。再配布 image を
堅くするには、既定の辞書版の既知の sha256 を
DICT_SHA256build-arg に渡すと ダウンロードの integrity を検証できます(既定は空 = 検証なし)。 - ライセンス / 商標: ES は ELv2 で self-host 用カスタム image の再配布が可能です
(マネージドサービスとして第三者提供しない・ライセンスキーを回避しない・Elastic の表記を
削除しない)。商標は nominative use(Elastic 公認に見せない)。upstream の LICENSE / NOTICE と
集約 NOTICE を image に同梱します。詳細は repo の
elasticsearch/README.md/elasticsearch/NOTICEを参照してください。
トラブルシュート
- OIDC publish が通らない(E404 等): まず toolchain(pnpm 10.x +
pnpm/action-setup@v6.0.6++ Node 24)と、npmjs.com 側の Trusted Publisher 設定 (repo / workflow ファイル名が一致しているか)を確認します。それでも通らない場合の フォールバックは、release.ymlの publish ステップをpnpm changeset publishからnpm publish経由のスクリプト に差し替える案です。 - Version PR が生成されない: 「Allow GitHub Actions to create and approve pull requests」が ON か、貯まった changeset が存在するかを確認します。
- Docker image が出ない:
docker.ymlがworkflow_runで発火したか、対象 Release run がdist-versionartifact を upload しているか(= 実際に publish があった run か)を確認します。 publish を伴わない Version PR だけの run では image は build されません。 - npm publish が E422(provenance /
repository.urlis "")で落ちる: provenance 付き publish (NPM_CONFIG_PROVENANCE=true)は、公開@crowi/*の各package.jsonにrepositoryフィールド(monorepo のdirectory付き)が必要です。無いとE422 ... "repository.url" is ""で弾かれます。全パッケージに設定済みですが、新規の公開パッケージを足すときはrepositoryを 必ず入れてください。 - Docker(api) ビルドが
ERR_PNPM_DEPLOY_NONINJECTED_WORKSPACEで落ちる: pnpm 10 でpnpm deployが injected workspace を要求するようになったためです。packages/api/Dockerfileはpnpm deploy --legacyで v10 以前の挙動を維持しています。
関連
- デプロイ構成 — image を api に向ける配線
- セルフホスティング — 自前 runner からの image ビルド
- 検索バックエンドのセットアップ — ES image を使う検索の設定