リポジトリ自動化セットアップ
conventional-commits + release-please + CI 自動化の完全なスタックを任意のリポジトリにセットアップします。空のリポジトリでも、既存のコンテンツがあるリポジトリでも動作します。
概要
Shift Left: 問題をできるだけ早期にキャッチします。PR 時に検出された不良なコミットメッセージは数秒の損失で済みますが、同じメッセージがリリースノートに混入すると信頼性を損ないます。検証を上流に移行し、PR タイトルでコミット形式を強制し、CI で設定を検証し、問題が main ブランチに到達する前にキャッチします。
高速化は安全性向上: バッチを小さく、リリース頻度を高くすることでリスクを低減します。3 つの変更を含むリリースは、30 の変更を含むリリースよりもデバッグが容易です。自動リリースはリリースプロセス自体への信頼を構築します。
このスキルは、検証メカニズムをセットアップします。PR タイトル検証により、main へのすべてのマージが意味のあるパース可能なコミットを生成することを保証します。Release-please はそれらのコミットを変更ログ付きの自動リリースに変換します。CI はマージ前に設定とコードの問題をキャッチします。
使用すべき場合
- 新しいリポジトリを開始し、初日からリリース自動化が必要な場合
- 既存のリポジトリに自動バージョン管理や変更ログ生成がない場合
- 手動リリースプロセスや他のリリースツールから移行する場合
- リポジトリに PR タイトル検証と自動ラベリングが必要な場合
使用すべきでない場合
- リポジトリにすでに release-please または同等のものが設定されている場合(最初に確認)
- 互換性のないリリースツールを使用したモノレポ(例:独立したバージョン管理がすでに動作している Lerna)
- リポジトリがフォークであり、アップストリームがリリースプロセスを制御している場合
プロセス
ステップ 1: 設定の収集
ファイルを生成する前に、ユーザーに以下の値を尋ねてください。
| パラメータ | デフォルト | 説明 |
|---|---|---|
PROJECT_NAME | (必須) | ドキュメント用の人間が読めるプロジェクト名 |
INITIAL_VERSION | 0.1.0 | 開始セマンティックバージョン |
RELEASE_TYPE | simple | simple(単一パッケージ)または node / python など |
REPO_LAYOUT | single | single(ルートに1パッケージ)または monorepo(複数パッケージ) |
PACKAGE_PATHS | . | モノレポの場合:packages/api,packages/ui のようなカンマ区切りのパス |
DEPENDABOT_ECOSYSTEMS | github-actions | カンマ区切り:github-actions、npm、pip、cargo など |
DEFAULT_BRANCH | main | リリースをトリガーするブランチ |
適切な RELEASE_TYPE を自動検出:
package.jsonが存在する →nodeを提案setup.pyまたはpyproject.tomlが存在する →pythonを提案Cargo.tomlが存在する →rustを提案- 上記のいずれもない場合 →
simpleを提案
ステップ 2: 既存ファイルの検出
何かを作成する前に、競合を確認してください。
for f in .github/workflows/pull-request.yml .github/workflows/main-branch.yml \
.github/release-please-config.json .release-please-manifest.json \
.github/dependabot.yml .github/pull_request_template.md docs/DEVELOPMENT.md; do
[[ -f "$f" ]] && echo "EXISTS: $f"
done
ファイルが存在する場合は、変更される差分を表示し、上書きする前に確認を求めてください。既存のファイルにはプロジェクト固有のカスタマイズが含まれている可能性があるため、黙って上書きしないでください。
ステップ 3: 設定ファイルの作成
以下の順序でファイルを作成します(依存関係はトップダウン)。
3a. .github/release-please-config.json
単一パッケージ:
{
"release-type": "{{RELEASE_TYPE}}",
"bump-minor-pre-major": true,
"bump-patch-for-minor-pre-major": false,
"initial-version": "{{INITIAL_VERSION}}",
"packages": {
".": {}
}
}
モノレポ: packages をパスごとに1エントリに置き換えます。
{
"packages": {
"packages/api": { "release-type": "node" },
"packages/ui": { "release-type": "node" }
}
}
各モノレポパッケージには独自の release-type が必要です。パッケージごとに異なる場合はユーザーに確認してください。
3b. .release-please-manifest.json
単一パッケージ:
{
".": "{{INITIAL_VERSION}}"
}
モノレポ: パッケージパスごとに1エントリ、それぞれ独自のバージョンを持ちます。
3c. .github/workflows/pull-request.yml
name: Pull Request Validation
on:
pull_request:
types: [opened, edited, synchronize, reopened]
permissions:
pull-requests: write
contents: read
statuses: write
jobs:
validate-pr-title:
name: Validate PR Title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
chore
refactor
test
ci
requireScope: false
subjectPattern: ^[a-z].+$
subjectPatternError: |
The subject "{subject}" found in the pull request title "{title}"
didn't match the configured pattern. Please ensure that the subject
starts with a lowercase character (per conventional commits).
auto-label:
name: Auto Label PR
runs-on: ubuntu-latest
steps:
- name: Label based on PR title
uses: actions/github-script@v8
with:
script: |
const title = context.payload.pull_request.title;
const labelMap = {
'feat': 'enhancement',
'fix': 'bug',
'docs': 'documentation',
'chore': 'chore',
'refactor': 'refactor',
'test': 'test',
'ci': 'ci'
};
for (const [type, label] of Object.entries(labelMap)) {
if (title.startsWith(`${type}:`) || title.startsWith(`${type}(`)) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: [label]
});
break;
}
}
no-ai-attribution:
name: No AI Attribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Scan commit messages and PR body
env:
PR_BODY: ${{ github.event.pull_request.body }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
# Trailer/footer forms only: a commit that merely mentions Claude or
# Anthropic in prose is fine. Human Co-authored-by trailers are fine.
PAT='^[[:space:]]*Co-authored-by:.*(Claude|Anthropic|noreply@anthropic)|Generated with \[?(Claude|Anthropic)'
fail=0
if git log --format='%B' "$BASE_SHA..$HEAD_SHA" | grep -Eiq "$PAT"; then
echo "::error::AI attribution found in a commit message on this branch"
fail=1
fi
if printf '%s' "$PR_BODY" | grep -Eiq "$PAT"; then
echo "::error::AI attribution found in the PR description"
fail=1
fi
[ "$fail" -eq 0 ] && echo "No AI attribution found."
exit $fail
ci-checks:
name: CI Checks
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v6
- name: Validate YAML syntax
run: |
sudo apt-get update && sudo apt-get install -y yamllint
find . -name "*.yml" -o -name "*.yaml" | while read file; do
echo "Checking $file"
yamllint -d "{extends: default, rules: {line-length: disable}}" "$file" || true
done
No AI Attribution は初日からブロックします — 検証する偽陽性の対象がありません(トレーラーとフッター形式のみを照合し、散文は照合しません)。そのため、以下の段階的導入パスは経由しません。
CI チェックの段階的導入パス:
continue-on-error: trueでデプロイ(情報提供、ブロックなし)- 3〜5件の実際の PR でチェックが成功することを確認
continue-on-errorを削除し、ブランチ保護の必須チェックに追加- コードベースの成長に応じてプロジェクト固有のチェック(lint、テスト、ビルド)を追加
どのゲートもスキップできません。 lint に失敗した場合は lint を修正し、ルールを無効にしないでください。テストに失敗した場合はコードを修正し、テストをスキップしないでください。CI に失敗した場合は、その失敗出力をエージェントに渡し、再プッシュする前に修正してください。
3d. .github/workflows/main-branch.yml
name: Release Automation
on:
push:
branches:
- {{DEFAULT_BRANCH}}
permissions:
contents: write
pull-requests: write
jobs:
release-please:
name: Release Please
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
config-file: .github/release-please-config.json
manifest-file: .release-please-manifest.json
update-major-tag:
name: Update Major Version Tag
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- name: Update major version tag
env:
TAG_NAME: ${{ needs.release-please.outputs.tag_name }}
run: |
MAJOR_TAG=$(echo "$TAG_NAME" | sed 's/^\(v[0-9]*\).*/\1/')
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -fa "$MAJOR_TAG" -m "Update $MAJOR_TAG tag to $TAG_NAME"
git push origin "$MAJOR_TAG" --force
3e. .github/dependabot.yml
エコシステムごとに1つの updates エントリを生成します。
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
labels:
- "dependencies"
commit-message:
prefix: "chore"
include: "scope"
commit-message 設定により、Dependabot PR が自動的に conventional commits に準拠するようになります(例:chore(deps): bump actions/checkout from v5 to v6)。
3f. .github/pull_request_template.md
## 変更内容
[変更の詳細を説明 - これは変更ログに含まれます]
## 理由
[変更のコンテキストと動機]
## チェックリスト
- [ ] PR タイトルが conventional commits 形式に従っている(`type: description`)
- [ ] 説明が内容と理由の両方を説明している(内容だけでなく)
- [ ] コード、ログ、バージョン管理にシークレットがない
- [ ] テストがローカルで成功している
「理由」セクションは重要です — 変更された 内容 だけを説明する PR 説明は、差分と重複しています。理由 は、将来の git-blame を有用にするコンテキストを提供します。
3g. .gitignore(欠けている場合)
.gitignore が存在するか確認します。ない場合は、プロジェクトに適したものを作成します。
# 依存関係
node_modules/
# ビルド出力
dist/
build/
.next/
# 環境
.env
.env.local
*.pem
# IDE
.idea/
# OS
.DS_Store
Thumbs.db
検出されたスタックに適応させてください。node_modules/、.env、ビルドアーティファクトは決してコミットしないでください。
3h. docs/DEVELOPMENT.md
以下の内容を含む開発ガイドを生成します。
- ブランチワークフロー — トランクベース開発:短命なフィーチャーブランチ(1〜3日)、迅速にマージ。ブランチ命名:
feature/<desc>、fix/<desc>、chore/<desc>。 - コミット規律 — ブランチ内では自由にコミット(任意の形式)。重要なのは PR タイトルのみです。それがスカッシュマージのコミットメッセージとして main に現れ、変更ログに表示されます。
- PR タイトル形式 — タイプの表:
feat、fix、docs、chore、refactor、test、ci。破壊的変更:feat!:または本文内のBREAKING CHANGE:。 - 変更サイズ — PR あたり約100行を目指します。単一の論理変更では〜300行まで許容。〜1000行以上は分割する必要があります。リファクタリングとフィーチャーワークは分離してください — それらは別の変更です。
- PR 説明 — 最初の行:短く、命令形で、独立して意味が通るもの。本文:何が変わっているか、そして なぜ か。アンチパターン:「バグ修正」、「ファイル更新」、「フェーズ1」。
- 自動チェック — PR タイトル検証(必須、マージをブロック)、自動ラベリング(情報提供)、CI チェック(初期は非ブロッキング、後に必須に移行)。
- リリースプロセス — release-please がリリース PR を作成 → マージ → GitHub リリース + タグ + 変更ログ。バージョン進行:v1.0 未満(
feat→ minor、fix→ patch)vs v1.0 以降(feat→ minor、fix→ patch、BREAKING CHANGE→ major)。 - トラブルシューティング — 一般的な問題:PR タイトル検証の失敗(タイトルを編集)、CI チェックの失敗、マージのブロック(必須ステータスを確認)。
見出しに {{PROJECT_NAME}} を使用します。
ステップ 4: ブランチ保護の推奨事項
ファイル作成後、これらを手動ステップとして提示します(自動適用はしません)。
{{DEFAULT_BRANCH}} に対する推奨 GitHub ブランチ保護設定:
✓ マージ前にプルリクエストを必須にする
✓ ステータスチェック「Validate PR Title」を必須にする
✓ ブランチが最新であることを必須にする
✓ スカッシュマージのみを許可
✓ 線形履歴を必須にする
スカッシュマージの理由: ブランチ履歴(WIP コミット、修正、実験)は PR 内に保持されます。main はクリーンで意味のある線形ログを取得し、すべてのコミットが conventional commit になります。これにより、release-please と git log --oneline が有用になります。
ステップ 5: ワークフローパーミッションの有効化
Release-please は GitHub Actions 経由でプルリクエストを作成するための権限が必要です。これは新しいリポジトリではデフォルトで無効になっており、リリース自動化ワークフローが以下のエラーで失敗します。
GitHub Actions is not permitted to create or approve pull requests.
ユーザーにこの設定を有効にするように指示します。
GitHub リポジトリ → Settings → Actions → General → Workflow permissions:
✓ Read and write permissions(release-please が変更ログコミットをプッシュするために必要)
✓ Allow GitHub Actions to create and approve pull requests(リリース PR のために必要)
このステップは、最初の {{DEFAULT_BRANCH}} へのプッシュ前に完了する必要があります。そうしないと、有効化されるまで release-please はプッシュのたびに失敗します。
ステップ 6: 確認
# YAML 構文の検証
yamllint .github/workflows/*.yml .github/dependabot.yml
# JSON の検証
python3 -c "import json;