OSSのCD方法、悩みますよね。すべて「cd-tools」で解決!
この記事では、別の記事で振り返り記事を書いた自作OSScd-toolsについて、その使い方を説明していきます。
振り返り記事はこちら
使い方
セットアップ
インストール
一応インストールから説明します。npmで話を進めますが、yarnやpnpmなどを用いている方は適宜読み替えてください。
インストール手順は2通りあります。どちらでも構いません。
個人開発をたくさんする方なら以下(yarnやpnpmなどを用いている方は適宜読み替えてください)。
> npm install -g cd-tools
チーム開発でcd-toolsを使うという方は各リポジトリで以下を実行してリポジトリで管理するのがよいでしょう。
> npm install -D cd-tools
グローバルにインストールした場合は以下。
> cd-tools <command>
リポジトリにインストールした場合は以下でcd-toolsのコマンドを実行できます。
> npx cd-tools <command>
実行環境構築
READMEに記載しています。
一応こちらにも記載すると、Node.js(v20以上)、GitHub CLIが必要です。各自公式ドキュメントを参照してください。
また、GitHub CLIはインストール後、以下コマンドでログインする必要があります。
> gh auth login
コマンド実行
一応ヘルプコマンドも実装しています。
# 以下の実行結果はすべて同じ
# cd-tools
# cd-tools -h
# cd-tools --help
> cd-tools help
Usage: cd-tools <command>
Commands:
init Initialize cd-tools configuration
start-pr Start a new release PR
push-pr Update versions and create/update PR
end-pr Finalize release and merge PR
ヘルプコマンドの出力にあるように、cd-toolsで使うコマンドはたったの4つです。
それぞれについて解説していきます。
initコマンド
初期設定のコマンドです。
具体的には以下を行います。
- cd-toolsの設定ファイル(
.cdtools/config.json
)をデフォルトの設定で生成する - プロジェクトをリリースする予定のレジストリを対話式でユーザーに選択してもらう
- Github Actionsで各プロジェクトをリリースするためのymlを生成する
本当は設定ファイルもnpm init
みたいに対話式で最初からユーザー最適化されたjsonを生成したかったのですが、とりあえずMVP段階では要件から削りました。
実行画面は以下のような感じです。
レジストリを選択
init完了
それでは、生成されたファイルについてそれぞれ具体的に見ていきましょう。
少し長いですが、もちろんすべて理解する必要はありません。必要に応じて読んでください。
.cdtools/config.json
デフォルトで生成されるのは以下です。
今のところjsonSchemaもありませんが、直近で対応する予定です。
さて、それぞれのフィールドについて解説していきます。
versioningStrategy
モノレポにおけるバージョニング戦略を選択します。
fixed
またはindependent
のenumです。自分が知っているバージョニング戦略がこの2つでしたが、もし他にもあれば教えていただけると嬉しいです。
fixed
はモノレポのプロジェクトすべてのバージョンを統一するバージョニング戦略です。大半のモノレポはこのバージョニング戦略の認識です。
具体的には、以下の例を考えます。
- モノレポのプロジェクトとして
project-a
(v1.0.0),project-b
(v1.0.0),project-c
(v1.0.0)がある -
project-a
がproject-b
に依存している
このとき、project-a
のみに差分を持つminor update(v1.0.0→v1.1.0)がされるとproject-b
,project-c
も同様にv1.1.0へ更新されます。
このバージョニング戦略を採用しているOSSは例えば以下などがあります(多分。git tagだけ見て判断してます)。
independent
はリリースするプロジェクトと、リリースする差分に対しての依存を持つプロジェクトのみがリリースされます。また、プロジェクト自身に差分がなく、依存関係のみに差分がある場合は必ずpatch updateとなります。
fixed
の時と同様の例で考えると、independent
の場合はpackage-b
がv1.0.1でリリースされ、package-c
はリリースされません。
このバージョニング戦略を採用しているOSSは例えば以下などがあります。
versionTags
リリースしたいtagの一覧を設定します。
tagというのは1.0.0-rc.0
や1.0.0-canary.0
などのrc,canaryの部分のことです。
1.0.0
などのtagなし(俗にいうstableリリース)は「stable」として予約語で登録しています。
それぞれ、versionSuffixStrategy
とnext
(optional)というフィールドを設定できます。
versionSuffixStrategy
は1.0.0-rc.0
などで、tag名の後ろに付く番号をどのように採番するかを決定するフィールドです。
現状timestamp
とincrement
のenumです。
timestamp
の場合は1.0.0-rc.20250722135520
のように、YYYYMMDDhhmmss形式のtimestampをsuffixとして付けます。
increment
の場合は、リリースのたびにgit tagをfetchしてきて、リリースする予定のバージョン、tagの最新の番号を取得して、その番号に+1した値をリリースします。
具体的には、ベースバージョンが1.0.0でtagがrcの最新のバージョンが1.0.0-rc.10
だった場合、次は1.0.0-rc.11
をリリースします。
next
は、そのtagをリリースするPRをマージした際にリリースするtagを決定するフィールドです。
例えば一般に、rc(Release Candidate)をリリースして検証した後、そのPRをマージした際にはstableリリースされることを想定されます。そういう時にrc tagのnext
フィールドにstableを設定するとそのようにリリースできます。
projects
プロジェクトを管理します。プロジェクトというのは要するにリリースを分割する単位です。
path
、type
、baseVersion
、deps
、registries
の5つのフィールドがあります。
path
にはそのプロジェクトのルートディレクトリからの相対パスを記載します。
type
にはそのプロジェクトでリリースする予定の言語を記載します。2025/7/22現在ではTypeScriptしかサポートしていませんが、対応言語を増やすのは割と簡単なので順次増やしていく予定です。
baseVersion
にはそのプロジェクトの最新のstableリリースが記載されます。stableリリースのたびに自動で書き換わるので、利用者が触ることはあまりないでしょう。
registries
にはリリース対象のレジストリを記載します。複数記載できるので、npmとjsrに同時にリリースも可能です。
.github/scripts/analyze-workspaces.sh
後述するGithub Actionsのワークフローで用いるシェルスクリプトです。
後ほどstart-pr
コマンドでブランチ情報ファイルというものを生成します。そこにはpushした際に「このpushではこのprojectをこのバージョン、このタグでリリースする予定です」という情報が入っています。
そのファイルを解析して、Github Actionsのワークフローにそれらの情報をmatrixで並列処理できるような形に整形して渡すためのシェルスクリプトです。
デフォルトで生成されるのは以下です。
.github/workflows/release-*.yml
*にはリリース対象のレジストリが入ります。
init
コマンドの際に選択したレジストリ用のリリースymlが生成されます。
先述のブランチ情報ファイルに差分が発生した際に呼び出され、リリースymlはレジストリにpublishするワークフローを並列処理するためのymlです。
今のところnpmとghcr.io(docker)が選択可能です。
デフォルトで生成されるのは以下です(npm版)。
.github/workflows/publish-*.yml
release-*.ymlから呼び出されるymlです。
各レジストリにpublishするための処理が書いてあります。
ここはそこそこ触ることがある人もいるでしょう。もしjsrやGitHub npm registryにpublishしたい人はここを書き換える必要があります。
といっても、10行ほどのnpmにpublishするための処理をしている箇所があるので、そこをそのレジストリ用に書き換えるだけです。
デフォルトで生成されるのは以下です(npm版)。
start-prコマンド
init
コマンドでcd-toolsの初期化を終わらせると、次はstart-pr
でリリース用のブランチを作りましょう。
具体的には以下を行います。
- これから作る予定のブランチでリリースするタグをユーザーに選択してもらう
- リリース用ブランチのブランチ名をユーザーに入力してもらう
- ブランチ情報ファイルを生成する
- リリース用ブランチにcheckoutする
実行画面は以下のような感じです。
リリースタグを選択
ブランチ名を記入
start-pr完了
特別言及することはありませんが、一応以下には言及しておきます。
- ブランチ情報ファイル
- リリース用ブランチ名
ブランチ情報ファイル
{
"tag": "rc",
"parentBranch": "main"
}
こんな形式で生成されます。ファイル名は[選択したタグ名]-[入力したブランチ名(/などは-でescapeされる)].json
となります。
例えばタグとしてrc
を選び、ブランチ名にrelease/1.1.7
を入力したとすると、rc-release-1.1.7.json
というブランチ情報ファイルが生成されます。
tag
はstart-pr
で選択したタグ名ですし、parentBranch
はstart-pr
を実行したブランチです。見たままですね。リリース時にこれらの情報を使います。
リリース用ブランチ名
ユーザーが入力したままのブランチ名にはならないことに注意です。
選択したタグと組み合わせて、[入力したブランチ名]([選択したタグ名])
になります。
例えばタグとしてrc
を選び、ブランチ名にrelease/1.1.7
を入力したとすると、release/1.1.7(rc)
というブランチ名となります。
push-prコマンド
start-pr
でリリース用ブランチを作成し、リリースする修正などをcommitしたら、次はpush-pr
で変更をpushして、PRを作成しましょう。
具体的には以下を行います。
- 変更種別を選択(patch,minor,major,(skip))
-
config.json
のversioningStrategy
によって、複数のプロジェクトに対して1つ1つのプロジェクトに対して種別を選択するか、一括で選択するかが変わる
-
- 各プロジェクトのバージョン管理フィールドを更新する
- ブランチ情報ファイルにリリースする予定のプロジェクトを記載する
- これまでの変更をcommit, pushする
- PRがまだ作られていなければPRを作成する
実行画面は以下のような感じです。
version bumpの種別を選択(versioningStrategyがfixed)
version bumpの種別を選択(versioningStrategyがindependent)
PRのbase branchを選択(PRを作成する場合)
push-pr完了
これも特別言及することはありませんが、一応以下には言及しておきます。
- ブランチ情報ファイルに記載されるリリースする予定のプロジェクトのフィールド
ブランチ情報ファイルに記載されるリリースする予定のプロジェクトのフィールド
{
"tag": "rc",
"parentBranch": "main",
"projectUpdated": {
".": "1.1.7-rc.5"
}
}
こんな感じになります。projectUpdated
というフィールドが追加されます。
オブジェクトで、中にはリリースするprojectのパスとバージョンが載っています。
end-pr
push-pr
で必要な修正などをpushし終わったら、次はPRをマージしましょう。
具体的には以下を行います。
-
config.json
で、現在リリースしているタグにnext
タグが設定されていればそのtagのリリースバージョンを算出する。 - そのリリースバージョンに各プロジェクトのバージョン管理フィールドを更新、commit、pushする
- ブランチ情報ファイルを削除する
- PRをマージする
実行画面は以下のような感じです。
本当にマージしていいか確認
end-pr完了
本当に特別言及することはありません。以上です。
おわりに
長くなりましたが、これさえ読めばcd-toolsについては完璧というくらいにはまとめられたのではないでしょうか。
この記事でcd-toolsいいなと少しでも思った方がいれば嬉しいです。
ぜひcd-toolsを使ってみてください!
Discussion