mcpField
R
run-full-release

run-full-release

github.com/terrylicaクラウド・DevOps193 回インストール今日更新
リポジトリ

run-full-release について

リポジトリの mise リリースパイプラインを実行し、存在しない場合は構築を案内するスキルです。公開可能なパッケージとドキュメント・設定リポジトリを見分け、プロジェクトに応じた手順を組み立てます。

主な機能

  1. 01既存の mise リリースタスクを検出
  2. 02セットアップ前にリポジトリを分類
  3. 03リポジトリに応じたリリースタスクの構築
  4. 04リリース失敗からの復旧方法を案内

活用シーン

  1. 01既存の mise リリースパイプラインを実行
  2. 02パッケージ向けの公開タスクを設定
  3. 03設定リポジトリを origin に同期

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/terrylica/cc-skills --skill run-full-release

インストール後、Claude Code で/run-full-releaseを入力して読み込まれたか確認します。

同梱ファイルreferences/evolution-log.md

詳細

/mise:run-full-release

現在のリポジトリのmiseリリースパイプラインを実行します。存在しない場合は、ブートストラップします。

自己進化型スキル:このスキルは使用を通じて改善されます。指示が誤っている、パラメーターが変化している、または回避策が必要だった場合は、先延ばしにせず、このファイルをすぐに修正してください。実際に再現可能な問題がある場合にのみ更新してください。

ステップ 1:既存のリリースタスクを検出する

mise tasks ls 2>/dev/null | grep -i release

タスクが存在する場合 → ステップ 3:実行に進みます。 タスクが見つからない場合 → ステップ 1b に進みます。

ステップ 1b:足場を構築する前にリポジトリを分類する

すべてのリポジトリが公開可能なパッケージというわけではありません。バージョン管理/公開パイプラインをブートストラップする前に、リポジトリの種類を判断してください。

ls pyproject.toml Cargo.toml package.json setup.py go.mod 2>/dev/null || echo "NO_PACKAGE_MANIFEST"
  • パッケージマニフェストがある(Python/Rust/Node/Go)→ 公開可能なリポジトリです。ステップ 2(バージョン管理+公開パイプラインを構築)に進みます。

  • パッケージマニフェストがなく、既存のリリース基盤もない → ドキュメント/設定/同期リポジトリ(個人用 dotfiles、メモ、または複数マシン間で git 同期される設定リポジトリ)です。バージョン管理や公開の対象はありません。semantic-release を構築しないでください。 この種のリポジトリでは、「リリース」とはorigin への同期です。

    git fetch origin
    git rev-list --left-right --count origin/<branch>...HEAD   # behind  ahead
    [ -z "$(git status --porcelain)" ] || echo "DIRTY — commit or stash first"
    # Only when the user has asked to release/ship (push only on request):
    git push origin <branch>
    git fetch origin && [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/<branch>)" ] && echo "✅ synced — release complete"
    

    behind > 0 の場合は、プッシュする前に(git pull --rebase またはマージで)同期してください。必要に応じて、最小限の release:full を preflight(クリーンな作業ツリー+正しいブランチ+最新状態)→ push → verify(origin == HEAD)として構築できます。バージョン管理/公開フェーズは含めません。ただし、ユーザーが繰り返し可能な同期を望む場合に限ります。それ以外の場合は、上記の単発プッシュだけでリリースは完了です。

    根拠(2026-06-04):複数マシン間でgit同期される設定/ドキュメントリポジトリの claude-sys で実行しました。パッケージマニフェストも .mise.toml も semantic-release もありませんでした。正しい対応は、パイプラインを構築することではなく、git push origin main で早送りし、HEAD == origin を検証することでした。この点は、まず監査する(ステップ 2a のエコシステム確認)ことで明らかになりました。ステップ 1b の明示的なゲートにすることで、公開対象のないリポジトリに公開パイプラインを構築してしまう誤った判断を防げます。

ステップ 2:リリースワークフローをブートストラップする

このステップでは、このリポジトリに合わせたリリースパイプラインを構築します。リポジトリごとに異なるため、テンプレートをそのままコピーしないでください。まず監査し、その後、適切なものを構築してください。

2a. リポジトリを監査する

このリポジトリに必要なものを把握するため、以下をすべて実行してください。

# Ecosystem detection
ls pyproject.toml Cargo.toml package.json setup.py 2>/dev/null

# Existing mise config
cat .mise.toml 2>/dev/null || cat mise.toml 2>/dev/null

# Existing release infra (semantic-release, Makefile, GitHub Actions)
ls .releaserc* release.config.* 2>/dev/null
ls .github/workflows/*release* 2>/dev/null
grep -i release Makefile 2>/dev/null

# Credentials already configured
grep -E 'GH_TOKEN|GITHUB_TOKEN|UV_PUBLISH_TOKEN|CARGO_REGISTRY_TOKEN|NPM_TOKEN' .mise.toml mise.toml 2>/dev/null
2b. 参照実装を読む

cc-skills 独自のリリースタスクを、動作する例として読んでください。コピーするのではなく、適用してください。

ls $HOME/.claude/plugins/marketplaces/cc-skills/tasks/release/

また、$HOME/.claude/plugins/marketplaces/cc-skills/docs/RELEASE.md も読んでください。

2c. tasks/release/ を構築する

このリポジトリで実際に必要なタスクだけを作成してください。5 フェーズのパターンは次のとおりです。

フェーズタスク目的必須?
1. 事前確認preflightクリーンなディレクトリ、認証、ブランチ確認常に
2. バージョン管理versionsemantic-release(またはリポジトリ固有のバージョン管理)常に
3. 公開pypiuv publish またはカスタムスクリプトPython の場合
cratescargo publish --workspace(Rust 1.90 以降)Rust の場合
npmnpm publishNode の場合
4. 検証verifyタグの存在、リリースの存在、成果物の公開状況常に
5. 事後確認postflightクリーンな git 状態、未プッシュなし、ロックファイルのリセット常に

オーケストレーター:full タスクで depends = [...] を使い、各フェーズを連鎖させます。

重要なルール:

  • 認証情報はスクリプトにハードコードせず、.mise.toml の [env] に設定します。
  • ツールのバージョンは .mise.toml の [tools] に設定します。
  • ロックファイルの差分は、preflight と postflight の両方でリセットします(意図的な変更ではなく、ビルド成果物のため)。
  • 利便性のため、--dry と --status のタスクを用意します。
2d. 既知の問題

古くなった cc-skills マーケットプレイスパスのフックエントリが ~/.claude/settings.json に残る:cc-skills の release:preflight フック検証ゲートが、✗ N cc-skills marketplace-path entries found in settings.json で失敗します。原因:以前の Claude Code セッションで読み込まれたフックが、解決済みのマーケットプレイスパスを settings.json に残すことがありますが、プラグインのフックは各プラグインの hooks/hooks.json から自動的に読み込まれます。settings.json に重複を含めるべきではありません。修正は組み込み済みです。./scripts/sync-hooks-to-settings.sh を実行してください(冪等です。漏れたマーケットプレイスパスのエントリのみを削除し、ユーザーが記述したフックには手を加えません)。その後、mise run release:full を再実行します。リリースのたびに再発するため、一度限りの問題ではありません。2026-05-09 のリリース途中に確認済み:4 件のエントリを削除し、再実行は成功しました。

@semantic-release/git による未追跡ファイルの大量検出:v10.x は --exclude-standard を付けずに git ls-files -m -o を実行します。インストール後にパッチを適用します:

find $(npm root -g 2>/dev/null) node_modules \
  -path "*/@semantic-release/git/lib/git.js" 2>/dev/null | while read f; do
  grep -q 'exclude-standard' "$f" || \
    sed -i '' "s/\['ls-files', '-m', '-o'\]/['ls-files', '-m', '-o', '--exclude-standard']/" "$f"
done

semantic-release の部分的な失敗(バージョンは更新されたがタグがない):semantic-release を再実行しないでください。タグと GitHub リリースを手動で作成してから、公開タスクを続行します。

Cargo ワークスペースのロックファイル連鎖更新(version.workspace = true を使う Rust ワークスペース):prepareCmd の perl ベースのバージョン更新は Cargo.toml だけを変更しますが、ワークスペースのバージョンは Cargo.lock 内の各メンバークレートのエントリにも波及します。@semantic-release/git プラグインは assets に記載されたファイルのみをステージするため、明示的な cargo の呼び出しと assets への Cargo.lock の追加がないと、ロックファイルは古いバージョンのままです。症状:release:version の成功後に release:preflight が M Cargo.lock で失敗し、cargo publish がブロックされます。release.config.cjs の修正:

- - "@semantic-release/exec"
  - prepareCmd: |
      perl -i -pe 's/^version = ".*"/version = "${nextRelease.version}"/' Cargo.toml
      cargo update --workspace --offline 2>/dev/null \
        || cargo metadata --format-version=1 --offline >/dev/null 2>&1 \
        || true

- - "@semantic-release/git"
  - assets:
      - Cargo.toml
      - Cargo.lock # ← critical: capture the cascading version bump
    message: "chore(release): ${nextRelease.version} [skip ci]"

--offline により同期はローカルで行われます(レジストリにはアクセスしません)。|| true のフォールバックにより、どちらの cargo コマンドも実行できない場合に prepareCmd がリリースをブロックするのを防ぎます。ロックファイルの同期が必要だった場合は、次の preflight で検出されます。

mise の depends は並列実行されます(release:full の依存関係 [preflight, version]):preflight と version が競合します。version によって作業ツリーが変更された場合(上記のロックファイル連鎖更新など)、version の処理が完了する一方で preflight が処理中に失敗を報告し、release:crates/verify/postflight が実行されないまま、取り消せないタグと GitHub リリースが作成されることがあります。復旧方法:変更された状態を修正してから、残りのフェーズ(release:crates → release:verify → release:postflight)を手動で実行します。別の semantic-release の実行が試みられるため、release:full は再実行しないでください。

crates.io API に対する単純な grep による release:verify の誤検知:if curl ... | grep -q "version" のような検証実装は、API の エラー 応答にも一致します。JSON エラーの詳細テキストには「version」という語が含まれるためです(例:"crate <name> does not have a version <X.Y.Z>")。その結果、実際の cargo publish が失敗していても、すべてのリリース実行で「✓ published on crates.io」と報告されます。複数のバージョンにわたって数日間気付かれない障害が続き、タグ付けされたバージョンが一つも crates.io に存在しないのに verify が成功を報告していたことで発覚しました。修正:成功時にのみ存在する一意の JSON 形式 "num":"<exact-version>" に一致させます(または、run = """ ... """ ブロック内の引用符が TOML のエスケープ規則によって変更されないよう、Python で JSON を解析します)。一致しない場合は、実際の API 応答をログに記録してハードフェイルします。修正例:

RESPONSE=$(curl -s "https://crates.io/api/v1/crates/<crate>/${VERSION}")
PUBLISHED_NUM=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('version',{}).get('num',''))" 2>/dev/null || echo "")
if [[ "$PUBLISHED_NUM" == "$VERSION" ]]; then
    echo "✓ <crate> v${VERSION} confirmed on crates.io"
else
    echo "⚠ <crate> v${VERSION} NOT on crates.io (API returned: '${PUBLISHED_NUM:-error}')"
    echo "  raw: $(echo "$RESPONSE" | head -c 200)"
    exit 1
fi

release:full が crates の公開失敗を握りつぶす:mise run release:crates || { echo "non-fatal" } の形式のオーケストレーター処理は、実際の cargo publish エラーを隠し、見かけ上の成功のまま続行します。上記の verify の誤検知と組み合わさると、複数バージョンの公開漏れが何日も見過ごされます。crates の公開失敗はハードフェイルにする必要があります。オペレーターは原因(トークン、ネットワーク、レジストリのレート制限など)を診断した後、release:crates を手動で実行します。|| でエラーを握りつぶす処理はすべて、ラップせずに呼び出す形式に置き換えてください。 スキーマドリフトゲートのパーサーがインデントされた ) で終了する:awk '... in_table { if ($0 ~ /^[[:space:]]*\)/) { in_table = 0; exit } ... }' のようなパーサーは、複数行の DEFAULT 式を持つ列で、インデントされた単独行に閉じ括弧があると、テーブルの途中で処理を打ち切ります(例:入れ子になった multiIf(\n ...,\n ) や算術式グループの閉じ括弧)。後半の列が検出されず、ライブの CH 側でドリフトが誤って検出されます。ClickHouse のフォーマット規約では、テーブル終端の実際の ) は列 0 に置かれます。正しく処理するには、終了判定を ^\)(先頭の空白なし)に変更してください。

プリプッシュゲートでの SSH ControlMaster の並列実行レース:複数の mise タスクが並列に(depends)SSH 接続を開くと、競合に負けた側が ControlSocket /Users/.../control-host:22 already exists, disabling multiplexing を stderr に出力します。ゲートスクリプトで ssh ... 2>&1 を使って stderr を stdout にマージしている場合、この警告がデータパイプに入り込み、識別子形式の健全性チェックで、存在しない「余分な」エントリーとして誤検出されます。対処方法:列の抽出には SSH の stderr は不要で、実際のエラーは後続で終了コードを明示的に伝播させることで検出できるため、SSH の stderr は /dev/null に送ります。さらに、多層防御として grep -E '^[a-zA-Z_][a-zA-Z0-9_]*$' フィルターを追加し、今後ほかの stderr 経路から出力が漏れても、有効な識別子形式の文字列だけが通るようにします。

べき等な git push がゼロ以外を返す:release:version の後に手動の git push --follow-tags origin main を実行するオーケストレーターは、release:version 内ですでに semantic-release の @semantic-release/git プラグインがプッシュしているため、最新状態のブランチと既存タグを再プッシュすると失敗することがあります。これを成功として扱ってください。プッシュ前に [[ $(git rev-parse HEAD) == $(git rev-parse origin/main) ]] で検出し、git ls-remote --tags origin "refs/tags/$LATEST_TAG" が空を返す場合にのみ最新のタグをプッシュします。そうしないと、実際にはリリースが正常に公開されているのにラッパーがゼロ以外で終了し、成功/失敗の判定が汚染されます。

WIP の .gitignore に対する git stash -u で無視対象ディレクトリが再表示され、プリフライトに失敗する(PII の危険):未コミットの .gitignore の変更が未追跡ディレクトリを無視する目的で含まれている場合、git stash -u は .gitignore をコミット済みの状態に戻します。その結果、これらのディレクトリが 再び無視されなくなり、?? の未追跡ファイルとして表示されます。通常は archive/sessions/ と node_modules/ のみを除外するプリフライトのクリーンツリー判定で、それらのディレクトリが原因で失敗します。また、臨床情報/PII を扱うリポジトリでは、この間、correspondence/、site/、cdanet/ などの機微なディレクトリが誤って git add -A の対象になる危険があります。根本原因は、未コミットの .gitignore が機能開発中の WIP ではなく、不可欠な基盤インフラ だということです。これを stash すると、無視状態が逆転します。対処方法:懸念事項を分けます。.gitignore の整理(および参照先の、秘密情報を含まないデプロイスクリプトなどの関連ファイル)を独立した chore: コミットとしてコミットし、無視ルールを有効なままにしてツリーをクリーンにします。その後、真の機能コードのみをパス指定の git stash push -- <files> で stash します(ディレクトリを再表示させる -u は使いません)。リリース後に git stash pop で機能開発中の WIP を復元します。2026-06-02 に臨床情報/PII を扱うリポジトリで検証済みです。包括的な git stash -u により、PII を含む 3 つのディレクトリとマシン固有の TOML オーバーライドが表示されました。stash を戻し、.gitignore と、それが参照する秘密情報を含まないデプロイスクリプトを個別にコミットしたうえで、機能ファイルをパス指定で stash したところ、プリフライトが成功し、適切な範囲のリリースが行われました。

ステップ 3:実行

ゼロコミットゲート(最初に確認): git log --oneline "$(git describe --tags --abbrev=0)..HEAD" が空で、かつワーキングツリーに変更がない場合、リリース対象はありません。release:full は semantic-release で何も実行しません。HEAD が最新タグと同じであることを報告し、代わりに有用な選択肢を提示してください。mise run release:status(報告)、またはパイプラインのsync と verify フェーズのみ(mise run release:sync && mise run release:verify)を実行して、稼働中のランタイム成果物(マーケットプレイスのクローン、プラグインキャッシュ、インストール済み/有効な一覧、同期済みコマンド)がリリース済みバージョンと完全に一致していることを再確認します。証拠(2026-07-19):リリースから約30分後に cc-skills で実行。タグ以降のコミットはゼロ。オペレーターは sync+verify を選択し、無駄なノーオペレーションのパイプライン実行を行わずに、4つの成果物ストアすべてで39個のプラグインの整合性を確認しました。

# Pre-release sync
git pull origin main

# Check for unpushed commits
git log --oneline @{u}..HEAD

# (cc-skills only) Preemptively prune leaked marketplace-path hook entries.
# This recurs across sessions — see Known Issues. Running this BEFORE
# release:full saves a preflight-fail/retry round trip. No-op if clean.
[[ -x ./scripts/sync-hooks-to-settings.sh ]] && ./scripts/sync-hooks-to-settings.sh

# Ensure GH_TOKEN is in the env — release:preflight checks `[ -n "$GH_TOKEN" ]`
# but many repos (incl. cc-skills) do NOT define it in .mise.toml [env]; auth
# lives in the gh keyring instead. Source it for the run. The Process Storm
# Guard blocks `$(gh auth token)` as a gh-recursion pattern, so the
# `# PROCESS-STORM-OK` escape hatch is REQUIRED here (this is a one-shot
# interactive release step, not a hook/credential-helper — the intended use).
if [ -z "${GH_TOKEN:-}" ]; then
  export GH_TOKEN="$(gh auth token)" && export GITHUB_TOKEN="$GH_TOKEN"  # PROCESS-STORM-OK
fi

# Route by flags
mise run release:full    # default
mise run release:dry     # --dry
mise run release:status  # --status

作業ディレクトリに変更がある場合は、関連する変更をコミットするか、先に WIP をスタッシュしてください。注意:変更に .gitignore が含まれる場合は、重要な変更として扱ってください。スタッシュせず、chore: としてコミットしてください。git stash -u は .gitignore を元に戻し、無視対象だったディレクトリを再び表示させるためです(その結果、プリフライトでそれらのディレクトリが原因で失敗します。PII の危険性があります。既知の問題を参照)。本当の機能コードだけをパス指定してスタッシュしてください:git stash push -- <files>。ロックファイルの差分がある場合はリセットしてください:

git diff --name-only | grep -E '(uv\.lock|package-lock\.json|Cargo\.lock|bun\.lockb)$' | xargs -r git checkout --

実行後の振り返り

このスキルの実行が完了したら、タスクを終了する前に振り返ってください。

  1. 現在地を確認する。 — 編集する前に、この SKILL.md の正式なパスを確認します。
  2. 何が失敗したか? — 原因となった指示を修正します。
  3. 予想以上にうまくいったことは? — 推奨される実践方法に取り入れます。
  4. 何が現状とずれていたか? — 実態と一致しなくなったスクリプト、参照、依存関係を修正します。
  5. 記録する。 — 発生のきっかけ、修正内容、証拠を含めて進化ログに記録します。

先送りしないでください。次回の実行では、あなたが残した状態が引き継がれます。

コメント