ship について
ship は、ブランチ確認やテストからレビュー、バージョンと変更履歴の更新、プルリクエスト手順までを自動化する Claude Code スキルです。フィーチャーブランチから変更をリリースする開発者向けです。
主な機能
- 01ブランチ確認とベースブランチのマージ
- 02ビルド、Lint、テストの実行
- 03カバレッジと計画完了状況の監査
- 04リリース前レビューとスコープ確認
- 05バージョンと変更履歴の更新
- 06コミットとプルリクエストの処理
活用シーン
- 01フィーチャーブランチでリリース確認を実行
- 02バージョンと変更履歴の更新を生成
- 03テストカバレッジと未完了の計画項目を確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ somnio-software/ somnio-ai-tools --skill shipインストール後、Claude Code で/shipを入力して読み込まれたか確認します。
詳細
Ship:完全自動化された Ship ワークフロー
/ship ワークフローを実行しています。これは非対話型の完全自動化ワークフローです。
どの段階でも確認を求めないでください。ユーザーが /ship と指定した場合は、実行してください。
最後に PR の URL を出力してください。
次の場合にのみ停止します:
- ベースブランチにいる場合(中止)
- 自動解決できないマージコンフリクトがある場合(停止して、コンフリクトを表示)
- ブランチ内のテストが失敗した場合(既存の失敗は自動的にブロックせず、原因を調査します)
- リリース前レビューで、ユーザーの判断が必要な ASK 項目が見つかった場合
- MINOR または MAJOR のバージョンアップが必要な場合(確認します。手順 8 を参照)
次の理由では停止しません:
- 未コミットの変更(必ず含めます)
- バージョンアップの選択(自動的に MICRO または PATCH を選びます。手順 8 を参照)
- CHANGELOG の内容(差分から自動生成します)
- コミットメッセージの承認(自動的にコミットします)
再実行時の動作(冪等性):
/ship を再実行すると、「チェックリスト全体をもう一度実行」します。すべての検証手順は実行のたびに実行されます。冪等なのは操作のみです。
- 手順 8:すでに VERSION が更新されている場合、更新はスキップしますが、バージョンは引き続き読み取ります
- 手順 11:すでにプッシュ済みの場合、プッシュコマンドをスキップします
- 手順 12:PR がすでに存在する場合、新しい PR を作成する代わりに本文を更新します
手順 0:プラットフォームとベースブランチを検出する
まず、リモート URL から Git ホスティングプラットフォームを検出します。
git remote get-url origin 2>/dev/null
- URL に "github.com" が含まれている場合 → プラットフォームは GitHub
- それ以外の場合 → 不明(git のネイティブコマンドのみ使用)
この PR のマージ先となるブランチ、またはリポジトリのデフォルトブランチを特定します。
GitHub の場合:
gh pr view --json baseRefName -q .baseRefName— 成功した場合は、その値を使用しますgh repo view --json defaultBranchRef -q .defaultBranchRef.name— 成功した場合は、その値を使用します
git ネイティブのフォールバック:
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'- 失敗した場合:
git rev-parse --verify origin/main 2>/dev/null→mainを使用します - 失敗した場合:
git rev-parse --verify origin/master 2>/dev/null→masterを使用します
すべて失敗した場合は、main を使用します。
検出したベースブランチ名を出力します。以降のすべてのコマンドで、指示にある「ベースブランチ」または <base> を、検出したブランチ名に置き換えます。
手順 1:事前確認
-
現在のブランチを確認します。ベースブランチにいる場合は、中止します:「ベースブランチにいます。フィーチャーブランチから Ship を実行してください。」
-
git statusを実行します(-uallは使用しないでください)。未コミットの変更は必ず含めます。 -
git diff <base>...HEAD --statとgit log <base>..HEAD --onelineを実行し、Ship する内容を把握します。
手順 2:ベースブランチをマージする(テストの前に実施)
マージ後の状態に対してテストを実行できるよう、ベースブランチをフィーチャーブランチにフェッチしてマージします。
git fetch origin <base> && git merge origin/<base> --no-edit
マージコンフリクトがある場合: 単純なコンフリクト(VERSION、CHANGELOG の順序など)であれば、自動解決を試みます。コンフリクトが複雑、または判断が難しい場合は、停止してコンフリクトを表示します。
すでに最新の場合: 何も表示せずに続行します。
手順 3:テストを実行する(マージ後のコードに対して)
プロジェクトのテストおよびビルドのパイプラインを実行します。
pnpm run build 2>&1 | tee /tmp/ship_build.txt
pnpm run lint 2>&1 | tee /tmp/ship_lint.txt
pnpm run test 2>&1 | tee /tmp/ship_tests.txt
すべての処理が完了したら、出力ファイルを読み、成功または失敗を確認します。
テストが失敗した場合: すぐに停止しないでください。テスト失敗の責任範囲を切り分けます。
テスト失敗の担当範囲のトリアージ
テストが失敗するたびに、次の手順を実行します。
-
このブランチで変更されたファイルを取得します。
git diff origin/<base>...HEAD --name-only -
失敗を分類します。
- ブランチ内:失敗したテストファイル、またはそのテスト対象のコードがこのブランチで変更されている場合、または失敗の原因をブランチの差分にある変更までたどれる場合です。
- 既存の可能性が高い:テストファイルもそのテスト対象のコードもこのブランチで変更されておらず、かつ失敗がブランチの変更と無関係な場合です。
- 判断が曖昧な場合は、ブランチ内として扱います。
-
**ブランチ内の失敗への対応:**停止します。 失敗を提示し、先に進まないでください。
-
既存の可能性が高い失敗への対応: AskUserQuestion を使用します。
これらのテスト失敗は既存のものであり、ブランチの変更が原因ではないようです。 [各失敗をファイル名:行番号と簡潔なエラーの説明とともに列挙]
A) 調査して今すぐ修正する B) スキップして、そのままリリースする
すべて成功した場合: 簡潔に件数を記録し、何も表示せずに続行します。
Step 4: テストカバレッジ監査
このステップは、Agent ツールを使用してサブエージェントに実行させます。サブエージェントは新しいコンテキストウィンドウでカバレッジ監査を行います。
サブエージェントへのプロンプト: <base> を置き換えて、次の指示をサブエージェントに渡します。
あなたは、4 層のクリーンアーキテクチャ(domain、application、infrastructure、api)を採用する NestJS モノレポのリリースワークフローにおけるテストカバレッジ監査を実行しています。変更点を確認するため、
git diff <base>...HEADを実行してください。コミットやプッシュはせず、結果の報告のみを行ってください。
差分で変更されたすべてのコードパスを追跡します。変更されたファイルをすべて読みます(差分だけでなく、ファイル全体を読んでください)。 各ファイルについて、すべての分岐(if/else、switch、ガード、早期 return、エラーパス)を通じたデータフローを追跡します。
各分岐を既存のテストと照合します。変更された関数/メソッドごとに、対応する
.spec.tsファイルを検索します。品質を次のように評価します。
- ★★★ エッジケースとエラーパスを含む動作をテスト
- ★★ 正常な動作をテスト(ハッピーパスのみ)
- ★ スモークテスト/存在確認/単純なアサーション
ASCII 形式のカバレッジ図を出力します。
コードパスのカバレッジ =========================== [+] src/application/units/commands/sync-unit.handler.ts ├── [★★★ テスト済み] ハッピーパス — sync-unit.handler.spec.ts:42 ├── [GAP] ユニットが見つからない場合のエラー — テストなし └── [GAP] 部分更新のシナリオ — テストなしカバーされていないパスのテストを作成します(テストフレームワークがある場合)。
- 既存の
.spec.tsファイルを 2~3 個読み、規約に正確に合わせます- 単体テストを作成します。外部依存関係(TypeORM リポジトリ、外部 API)はモックします
- 各テストを実行します。成功した場合は保持します。失敗した場合は一度修正します。それでも失敗する場合は、何も報告せずに削除します。
分析後、最後の行に単一の JSON オブジェクトを出力します。
{"coverage_pct":N,"gaps":N,"diagram":"<markdown diagram>","tests_added":["path",...]}
親プロセスでの処理:
- 最後の行を JSON として解析します。
- PR 本文の
## Test Coverageセクション用に保存します。 - 次を出力します:
Coverage: {coverage_pct}%, {gaps} gaps. {tests_added.length} tests added.
サブエージェントが失敗した場合: 監査を親プロセス内で実行します。
Step 5: リリース前レビュー
テストでは検出できない構造上の問題がないか、差分をレビューします。
-
完全な差分を取得するため、
git diff origin/<base>を実行します。 -
次のレビュー用チェックリストを 2 回に分けて確認します。
Pass 1(重大)— リリース前に必ず修正する項目:
- SQL とデータの安全性: 文字列補間を使用した生の SQL、複数テーブルへの書き込み時にトランザクションがない、UPDATE/DELETE に
WHEREがない、クエリ内のユーザー入力が検証されていない - セキュリティ: シークレットの露出、ファイルやディレクトリが適切に gitignore されていない、エンドポイントに認証ガードがない、サニタイズされていない出力による XSS、CORS の設定ミス
- 破壊的変更: 公開 API エンドポイントの削除/名称変更、レスポンス形式の変更、必須フィールドの削除
Pass 2(INFORMATIONAL)— 修正または記録:
- アーキテクチャ: レイヤー境界の違反(ドメイン層へのフレームワークのインポート)、DTO とエンティティの混在、バレルエクスポートの不足
- エラー処理: インラインの文字列エラーメッセージ(エラー列挙型を使用すべきです)、エラーの握りつぶし、Problem Details 形式の不足
- パフォーマンス: N+1 クエリ、ページネーションの不足、上限のないクエリ、インデックスの不足
- コード品質: デッドコード、孤立したコード、未使用のインポート、ロジックの重複、複雑すぎる条件分岐
信頼度の調整
すべての指摘に信頼度スコア(1~10)を必ず付けてください。
| スコア | 意味 |
|---|---|
| 9-10 | 特定のコードを読んで検証済みです。具体的なバグを実証しています。 |
| 7-8 | パターンとの一致度が高く、正しい可能性が非常に高いです。 |
| 5-6 | 確度は中程度です。誤検知の可能性があります。留保事項を添えて示してください。 |
| 3-4 | 確度が低いため、メインレポートには含めないでください。 |
| 1-2 | 推測です。重大度が P0 の場合にのみ報告してください。 |
指摘の形式:
[SEVERITY] (confidence: N/10) file:line — description
修正優先のフロー
-
各指摘を AUTO-FIX または ASK に分類します。
- AUTO-FIX:デッドコードの削除、未使用のインポート、バレルエクスポートの不足、明らかな書式の修正
- ASK:動作を変更する修正、セキュリティ修正、アーキテクチャ上の判断
-
AUTO-FIX 項目をすべて自動修正します。 修正ごとに1行で出力します。
[AUTO-FIXED] [file:line] Problem → what you did -
ASK 項目が残っている場合は、 1つの AskUserQuestion で提示します。
- 各項目について、重大度、問題、推奨する修正を列挙します。
- 項目ごとの選択肢:A) 修正 B) スキップ
-
すべての修正後:
- 修正を1つでも適用した場合:修正したファイルをコミット(
git add <files> && git commit -m "fix: pre-landing review fixes")し、テストを再実行します(Step 3)。 - 修正を適用しなかった場合:Step 8 に進みます。
- 修正を1つでも適用した場合:修正したファイルをコミット(
-
概要を出力します:
Pre-Landing Review: N issues — M auto-fixed, K asked (J fixed, L skipped)
Step 6: スコープ逸脱の検出
確認事項:ブランチで、明示された内容どおりのものだけを構築しましたか?
-
コミットメッセージを確認します(
git log origin/<base>..HEAD --oneline)。 -
ブランチ名とコミットから明示された意図を特定します。
-
git diff origin/<base>...HEAD --statを実行し、変更されたファイルを意図と照合します。 -
次を検出します。
- スコープクリープ: 明示された意図に関連しない変更ファイル
- 要件漏れ: diff に含まれていない、想定される作業
-
次を出力します。
Scope Check: [CLEAN / DRIFT DETECTED / REQUIREMENTS MISSING] Intent: <1-line summary> Delivered: <1-line summary> -
これはINFORMATIONALであり、ブロック要因にはなりません。続行してください。
Step 7: 計画の完了監査
サブエージェントとして実行します。 現在のブランチに関連するアクティブな計画ファイルを検索します。
サブエージェントへのプロンプト:
ship-workflow の計画完了監査を実行します。ベースブランチは
<base>です。
- 計画ファイルを検索します:
find ~/.claude/plans ~/.gstack/projects -name "*.md" -mmin -1440 2>/dev/null | head -10- 現在のブランチに言及している計画があれば、それを読み、実行可能な項目をすべて抽出します。
- 各項目を
git diff origin/<base>...HEADと照合します。- 次のように分類します:DONE、PARTIAL、NOT DONE、CHANGED。
最終行に JSON を出力します。
{"total_items":N,"done":N,"changed":N,"deferred":N,"summary":"<markdown checklist>"}
親エージェントによる処理:
deferred > 0の場合:AskUserQuestion を使って保留中の項目を提示します。summaryを PR 本文に埋め込みます。- 計画ファイルが見つからない場合は、"No plan file detected." としてスキップします。
ステップ 8:バージョンを更新する(自動判定)
冪等性チェック: VERSION をベースブランチと比較します。
BASE_VERSION=$(git show origin/<base>:VERSION 2>/dev/null || echo "0.0.0.0")
CURRENT_VERSION=$(cat VERSION 2>/dev/null || echo "0.0.0.0")
echo "BASE: $BASE_VERSION HEAD: $CURRENT_VERSION"
if [ "$CURRENT_VERSION" != "$BASE_VERSION" ]; then echo "ALREADY_BUMPED"; fi
ALREADY_BUMPED の場合は、バージョンを更新せず、現在のバージョンを読み取ります。それ以外の場合:
-
VERSIONを読み取ります(4 桁形式:MAJOR.MINOR.PATCH.MICRO)。 -
更新レベルを自動判定します。
- 変更された行数を数えます(
git diff origin/<base>...HEAD --stat | tail -1)。 - MICRO(4 桁目):変更行数が 50 行未満、軽微な調整、設定変更
- PATCH(3 桁目):変更行数が 50 行以上で、機能追加の兆候がない場合
- MINOR(2 桁目):機能追加の兆候が検出された場合(新しいルート、マイグレーション、
feat/ブランチ)は確認を求めます。 - MAJOR(1 桁目):マイルストーンまたは破壊的変更の場合に限り、確認を求めます。
- 変更された行数を数えます(
-
新しいバージョンを算出し、
VERSIONに書き込みます。
ステップ 9:CHANGELOG(自動生成)
-
CHANGELOG.mdのヘッダーを読み取り、書式を確認します。 -
すべてのコミットを列挙します:
git log <base>..HEAD --oneline -
差分全体を読み取ります:
git diff <base>...HEAD -
コミットをテーマ別に分類します(機能、修正、整理、インフラ)。
-
CHANGELOG のエントリーを作成します。
- セクション:
### Added、### Changed、### Fixed、### Removed - 書式:
## [X.Y.Z.W] - YYYY-MM-DD - これまでできなかったことのうち、ユーザーが新たにできるようになったことを最初に記載します。
- セクション:
-
照合します。すべてのコミットが、少なくとも 1 つの箇条書き項目に反映されている必要があります。
ステップ 10:コミットする(後から二分探索できる単位)
-
差分を分析し、変更を論理的なコミットに分類します。
-
コミットの順序(先に行うコミットから順に記載):
- インフラ:マイグレーション、設定変更
- ドメインとアプリケーション:エンティティ、値オブジェクト、ユースケース、サービス(テストを含む)
- インフラの実装:リポジトリ、TypeORM エンティティ(テストを含む)
- API 層:コントローラー、DTO(テストを含む)
- VERSION と CHANGELOG:必ず最後のコミットに含めます。
-
ルール:
- サービスとそのテストファイルは同じコミットに含めます。
- 各コミットは単独で有効である必要があります。インポートが壊れていてはいけません。
- 差分全体が小さい場合(4 ファイル未満にわたる 50 行未満)、1 つのコミットにまとめてもかまいません。
-
コミットメッセージを作成します。
- Skill ツールを使って
/git-commit-formatスキルを呼び出します。 - プロジェクトの慣例に従い、
Co-Authored-Byや AI への帰属を示すトレーラーは絶対に含めません。
- Skill ツールを使って
ステップ 11:検証ゲート
絶対遵守事項:新たな検証の証拠がない状態で、完了を主張してはいけません。
プッシュする前に、ステップ 4~6 の間にコードが変更されていた場合は、再検証します。
-
ステップ 3 のテスト実行後にコードが少しでも変更されていた場合は、テストを再実行します。
pnpm run build && pnpm run lint && pnpm run test -
自己正当化の防止:
- 「もう動くはず」→ 実行します。
- 「以前すでにテストした」→ それ以降にコードが変更されています。もう一度テストします。
- 「些細な変更だ」→ 些細な変更でも本番環境に問題を引き起こします。
ここでテストが失敗した場合: 停止します。プッシュしてはいけません。
ステップ 12:プッシュする
冪等性チェック:
BRANCH_NAME=$(git branch --show-current)
git fetch origin "$BRANCH_NAME" 2>/dev/null
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse "origin/$BRANCH_NAME" 2>/dev/null || echo "none")
echo "LOCAL: $LOCAL REMOTE: $REMOTE"
[ "$LOCAL" = "$REMOTE" ] && echo "ALREADY_PUSHED" || echo "PUSH_NEEDED"
ALREADY_PUSHED の場合はスキップします。それ以外の場合:
git push -u origin "$BRANCH_NAME"
ステップ 13:PR を作成する
冪等性チェック:
gh pr view --json url,number,state -q 'if .state == "OPEN" then "PR #\(.number): \(.url)" else "NO_PR" end' 2>/dev/null || echo "NO_PR"
オープン中の PR がすでにある場合は、gh pr edit --body "..." を使って PR の本文を更新します。
PR がない場合は作成します。
PR の本文には次の内容を含めます。
## Summary
<Summarize ALL changes. Group commits into logical sections. Every commit
must appear in at least one section.>
## Test Coverage
<Coverage diagram from Step 4, or "All new code paths have test coverage.">
## Pre-Landing Review
<Findings from Step 5, or "No issues found.">
## Scope Drift
<From Step 6, or omit if CLEAN>
## Plan Completion
<From Step 7, or "No plan file detected.">
## Test plan
- [x] TypeScript compilation passes (strict mode)
- [x] ESLint passes
- [x] All Jest tests pass (N tests)
- [x] No regressions in affected modules
PR を作成します。
gh pr create --base <base> --title "<type>(<scope>): <summary>" --body "$(cat <<'EOF'
<PR body from above>
EOF
)"
PR の URL を出力します。
重要なルール
- テストを省略してはいけません。 テストが失敗した場合は停止します。
- 強制プッシュをしてはいけません。 通常の
git pushのみを使用します。 - 些細な確認を求めてはいけません(例:「プッシュしてよいですか?」「PR を作成しますか?」)。
- 必ず VERSION ファイルの 4 桁形式を使用します。
- CHANGELOG の日付形式:
YYYY-MM-DD - 二分探索できるようにコミットを分割します。 各コミットは 1 つの論理的な変更を表します。
- 新たな検証の証拠なしにプッシュしてはいけません。 ステップ 3 のテスト後にコードが変更された場合は、プッシュ前に再実行します。
- プロジェクトの慣例に従い、コミットメッセージに
Co-Authored-Byトレーラーを絶対に含めません。 - 目標は、ユーザーが
/shipと入力した次に目にするものが PR の URL であることです。