最終更新:
Changesets実践ガイド: モノレポでのバージョン管理とリリース自動化
Changesets実践ガイド
Changesetsは、モノレポでのバージョン管理とリリースプロセスを自動化するツールです。Turborepo、pnpm Workspace、Yarnなどと組み合わせて使用できます。
本記事では、Changesetsの実践的な使い方、チーム運用、CI/CD統合、自動リリースの実装方法を解説します。
Changesetsとは
主な機能
- 変更のトラッキング - パッケージの変更を記録
- セマンティックバージョニング - 自動的にバージョンを計算
- CHANGELOG生成 - 変更履歴を自動生成
- 依存関係の管理 - 関連パッケージのバージョンも更新
- 自動リリース - CI/CDでの自動公開
なぜChangesetsなのか
// 従来の方法(Lerna)
// - 全パッケージを同時にバージョンアップ
// - 柔軟性が低い
// - CHANGELOGが自動生成されない
// Changesets
// - パッケージごとに独立したバージョン管理
// - 変更内容を明示的に記録
// - 自動的にCHANGELOG生成
// - 依存関係を自動解決
セットアップ
インストール
# モノレポのルートで実行
npm install -D @changesets/cli
# または
pnpm add -D @changesets/cli
# 初期化
npx changeset init
プロジェクト構造
my-monorepo/
├── .changeset/
│ ├── config.json # Changesets設定
│ └── README.md # チーム向けガイド
├── packages/
│ ├── ui/
│ │ ├── package.json
│ │ └── CHANGELOG.md # 自動生成
│ ├── utils/
│ │ ├── package.json
│ │ └── CHANGELOG.md
│ └── core/
│ ├── package.json
│ └── CHANGELOG.md
├── package.json
└── pnpm-workspace.yaml
設定ファイル
// .changeset/config.json
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
詳細な設定:
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
// CHANGELOG生成方法
"changelog": [
"@changesets/changelog-github",
{
"repo": "your-org/your-repo"
}
],
// 変更をコミットするか
"commit": false,
// 常に一緒にバージョンアップするパッケージ
"fixed": [
["@myorg/ui", "@myorg/theme"]
],
// バージョンを連動させるパッケージ
"linked": [
["@myorg/react-*"]
],
// npm公開時のアクセス設定
"access": "public",
// ベースブランチ
"baseBranch": "main",
// 内部依存関係の更新方法
"updateInternalDependencies": "patch",
// バージョン管理から除外
"ignore": ["@myorg/examples", "@myorg/docs"],
// プライベートパッケージも含めるか
"privatePackages": {
"version": true,
"tag": false
}
}
基本的なワークフロー
1. 変更を加える
# 機能を開発
cd packages/ui
# コード変更...
# バグ修正
cd packages/utils
# バグ修正...
2. Changesetを作成
# ルートで実行
npx changeset
# または
pnpm changeset
インタラクティブなプロンプト:
🦋 Which packages would you like to include?
◯ changed packages
◉ @myorg/ui
◯ @myorg/utils
◉ @myorg/core
🦋 Which packages should have a major bump?
◯ all packages
◯ @myorg/ui
◉ @myorg/core
🦋 Which packages should have a minor bump?
◉ all packages
◉ @myorg/ui
◯ @myorg/core
🦋 Please enter a summary for this change:
Add new Button component with variants
🦋 === Summary of changesets ===
major: @myorg/core
minor: @myorg/ui
Is this correct? (Y/n)
生成されたChangeset:
<!-- .changeset/happy-pandas-jump.md -->
---
"@myorg/ui": minor
"@myorg/core": major
---
Add new Button component with variants
- Added primary, secondary, and ghost button variants
- Improved accessibility with ARIA labels
- Breaking: Changed button API to accept variant prop
3. バージョンアップ
# バージョンを更新
npx changeset version
# 実行されること:
# 1. package.jsonのversionを更新
# 2. CHANGELOGを生成
# 3. Changesetファイルを削除
# 4. 依存関係を自動更新
結果:
// packages/ui/package.json
{
"name": "@myorg/ui",
- "version": "1.2.0",
+ "version": "1.3.0"
}
// packages/core/package.json
{
"name": "@myorg/core",
- "version": "2.1.0",
+ "version": "3.0.0"
}
// packages/app/package.json (依存関係も自動更新)
{
"dependencies": {
- "@myorg/ui": "^1.2.0",
+ "@myorg/ui": "^1.3.0",
- "@myorg/core": "^2.1.0",
+ "@myorg/core": "^3.0.0"
}
}
CHANGELOG:
<!-- packages/ui/CHANGELOG.md -->
# @myorg/ui
## 1.3.0
### Minor Changes
- abc123: Add new Button component with variants
- Added primary, secondary, and ghost button variants
- Improved accessibility with ARIA labels
## 1.2.0
...
4. リリース
# ビルド
pnpm run build
# npmに公開
npx changeset publish
# Gitタグを作成
git push --follow-tags
チーム運用
プルリクエスト運用
## プルリクエストのルール
1. 変更を加えたら必ず Changeset を作成
2. Changeset の内容はレビュー対象
3. バージョンアップは自動化
## Changesetの書き方
### 良い例 ✅
```markdown
---
"@myorg/ui": minor
---
Add DatePicker component
- Support for date range selection
- Built-in validation
- Accessible keyboard navigation
悪い例 ❌
---
"@myorg/ui": patch
---
Updates
CI/CDでの自動化
GitHub Actions完全版
# .github/workflows/release.yml
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 8
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache
uses: actions/cache@v3
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpm run build
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
publish: pnpm run release
title: "chore: version packages"
commit: "chore: version packages"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish to npm
if: steps.changesets.outputs.published == 'true'
run: |
echo "Published packages:"
echo '${{ steps.changesets.outputs.publishedPackages }}'
package.json スクリプト:
{
"scripts": {
"build": "turbo build",
"changeset": "changeset",
"version": "changeset version",
"release": "pnpm build && changeset publish"
}
}
自動プルリクエスト作成
Changesets GitHub Actionは以下を自動実行:
-
Changesetがある場合:
Version Packagesプルリクエストを作成- マージすると自動的にnpmに公開
-
プルリクエストの内容:
# Version Packages
## @myorg/ui@1.3.0
### Minor Changes
- abc123: Add new Button component
## @myorg/core@3.0.0
### Major Changes
- def456: Refactor API structure
**Breaking**: Changed authentication API
Slack通知
# .github/workflows/release.yml
- name: Notify Slack
if: steps.changesets.outputs.published == 'true'
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "New packages released! 🎉",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Packages published:*\n${{ steps.changesets.outputs.publishedPackages }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
高度な使い方
プレリリース
# プレリリースモードに入る
npx changeset pre enter next
# Changesetを作成
npx changeset
# プレリリースバージョンを生成
npx changeset version
# 例: 1.2.0 → 1.3.0-next.0
# npmに公開
npx changeset publish --tag next
# プレリリースモードを終了
npx changeset pre exit
package.json:
{
"name": "@myorg/ui",
"version": "1.3.0-next.0"
}
インストール:
# プレリリース版をインストール
npm install @myorg/ui@next
# 特定のプレリリース版
npm install @myorg/ui@1.3.0-next.0
固定バージョン
// .changeset/config.json
{
"fixed": [
// 常に同じバージョンを保つパッケージグループ
["@myorg/ui", "@myorg/theme", "@myorg/icons"]
]
}
動作:
# @myorg/ui にだけ変更を加えても
npx changeset version
# すべてのパッケージが同じバージョンになる
# @myorg/ui: 1.2.0 → 1.3.0
# @myorg/theme: 1.2.0 → 1.3.0
# @myorg/icons: 1.2.0 → 1.3.0
リンクバージョン
// .changeset/config.json
{
"linked": [
// メジャーバージョンを連動させる
["@myorg/react-hooks", "@myorg/react-utils"]
]
}
動作:
# @myorg/react-hooks: 2.1.0 → 3.0.0 (major)
# @myorg/react-utils: 2.5.0 → 3.0.0 (自動的にmajor)
カスタムCHANGELOG
GitHub Changelog
npm install -D @changesets/changelog-github
// .changeset/config.json
{
"changelog": [
"@changesets/changelog-github",
{
"repo": "your-org/your-repo"
}
]
}
生成されるCHANGELOG:
## 1.3.0
### Minor Changes
- [#123](https://github.com/your-org/your-repo/pull/123) [`abc123`](https://github.com/your-org/your-repo/commit/abc123) Thanks [@user](https://github.com/user)! - Add new Button component
### Patch Changes
- Updated dependencies [[`abc123`](https://github.com/your-org/your-repo/commit/abc123)]:
- @myorg/theme@1.2.0
カスタムChangelogジェネレーター
// .changeset/custom-changelog.js
const { getInfo } = require('@changesets/get-github-info')
async function getReleaseLine(changeset, type, options) {
const [firstLine, ...futureLines] = changeset.summary
.split('\n')
.map((l) => l.trimEnd())
let returnVal = `- ${firstLine}`
if (futureLines.length > 0) {
returnVal += `\n${futureLines.map((l) => ` ${l}`).join('\n')}`
}
// GitHub情報を追加
if (options && options.repo) {
const { links, user } = await getInfo({
repo: options.repo,
commit: changeset.commit,
})
returnVal += ` (${links.commit})`
if (user) {
returnVal += ` by @${user}`
}
}
return returnVal
}
async function getDependencyReleaseLine(changesets, dependenciesUpdated) {
if (dependenciesUpdated.length === 0) return ''
const changesetLinks = changesets.map((cs) => ` - ${cs.summary}`)
return `- Updated dependencies:\n${changesetLinks.join('\n')}`
}
module.exports = {
getReleaseLine,
getDependencyReleaseLine,
}
// .changeset/config.json
{
"changelog": [
"./.changeset/custom-changelog.js",
{
"repo": "your-org/your-repo"
}
]
}
トラブルシューティング
よくある問題
1. 依存関係が更新されない
// .changeset/config.json
{
// patchではなくminorで更新
"updateInternalDependencies": "minor"
}
2. プライベートパッケージのバージョン管理
// .changeset/config.json
{
"privatePackages": {
"version": true, // バージョンは更新
"tag": false // Gitタグは作らない
}
}
3. 特定のパッケージを無視
// .changeset/config.json
{
"ignore": [
"@myorg/examples",
"@myorg/docs"
]
}
ベストプラクティス
1. Changesetの粒度
<!-- ✅ 良い例: 1つの機能に1つのChangeset -->
---
"@myorg/ui": minor
---
Add DatePicker component
- Support for date range selection
- Built-in validation
<!-- ❌ 悪い例: 複数の機能を1つに -->
---
"@myorg/ui": minor
"@myorg/utils": patch
"@myorg/core": major
---
Various updates
2. セマンティックバージョニング
// Breaking Change → Major
export function oldApi() {} // 削除
export function newApi() {} // 新API
// New Feature → Minor
export function newFeature() {} // 追加
// Bug Fix → Patch
export function bugFix() {} // 修正
3. コミットメッセージ
# Changesetを含むコミット
git add .changeset/happy-pandas-jump.md
git commit -m "feat: add Button component"
# バージョンアップのコミット
git commit -m "chore: version packages"
まとめ
Changesetsを使うことで、以下が実現できます。
主な利点
- 透明性 - すべての変更が記録される
- 自動化 - バージョン管理が自動化
- 柔軟性 - パッケージごとに独立したバージョン
- チーム協調 - プルリクエストベースのワークフロー
- 信頼性 - セマンティックバージョニングの徹底
推奨構成
const idealSetup = {
monorepo: 'Turborepo or pnpm Workspace',
versionManagement: 'Changesets',
ci: 'GitHub Actions',
publishing: 'npm with provenance',
changelog: '@changesets/changelog-github',
}
Changesetsを活用して、効率的でスケーラブルなモノレポ管理を実現しましょう。