CI 連携
bca をビルドパイプラインに組み込むためのレシピ集です。bca check コマンドは、現代の CI に必要なあらゆる出力形式(Checkstyle、SARIF、GitLab Code Climate JSON、clang/GCC 警告行、MSVC 警告行)を既に備えており、加えて人間向けの bca report markdown があります。このページは、ユーザーの 目的 から、適切なサブコマンド・フラグ・プラットフォーム連携の組み合わせへの統合マップです。
出力の選び方
以下のマトリクスは、よくある目的ごとに、対応する CI サーフェスへ出力を供給する bca の呼び出し方を対応付けたものです。実行可能な例はリンク先の各セクションにあります。
| 目的 | コマンド + フラグ |
|---|---|
| しきい値リグレッションに対するハードゲート | bca check (自動検出された bca.toml のしきい値を使用) |
| 既存コードベースでしきい値をラチェットする | bca check --baseline .bca-baseline.toml (‡) |
| インライン PR アノテーション(GitHub) | bca check … --report-format clang-warning --no-fail + GCC problem matcher |
| Code Scanning アラート(GitHub) | bca check … --report-format sarif --no-fail + github/codeql-action/upload-sarif |
| マージリクエストウィジェット(GitLab Code Quality) | bca check … --report-format code-climate --no-fail |
| Jenkins / SonarQube への取り込み | bca check … --report-format checkstyle |
| 人間可読な PR/MR コメントまたはダウンロード可能な成果物 | bca report -O markdown --top 20 --strip-prefix "$PWD/" |
| ダッシュボード向けの機械可読アーティファクト | bca metrics --format json --output-dir ./out |
(‡)既存の違反があるコードベースにしきい値を導入する際に推奨される導入パスです。ブートストラップ・リフレッシュ・リタイアのワークフローについてはベースラインのレシピを参照してください。
bca check の出力形式、終了コード(0 はクリーン、2 は違反、1 はツールエラー)、しきい値設定の完全なリファレンスは Check コマンドのページ にあります。Markdown レポートの形式については、Report コマンドのページ と品質レポートのレシピを参照してください。
GitHub Actions
実際の動作例
big-code-analysis は、すべてのプッシュと PR で、以下のレシピを自身のソースに対して実行しています。ワークフローのソースである .github/workflows/pages.yml は、しきい値ゲート、ベースラインのラチェット、両方のレポート形式、そして GitHub Code Scanning への SARIF アップロードを、ワークスペース自身に対してエンドツーエンドで実行します。(SARIF アップロードは同一リポジトリのプッシュと PR でのみ実行されます。アップロードには書き込みスコープのトークンが必要なため、フォークからの PR ではスキップされます。これは clippy の SARIF ジョブとまったく同じ扱いです。)出力は本書と並んで GitHub Pages 上に置かれています:
- HTML ホットスポットレポート: https://dekobon.github.io/big-code-analysis/reports/index.html
- Markdown 版 PR/MR コメント: https://dekobon.github.io/big-code-analysis/reports/report.md
以下のスニペットはそのまま自身のワークフローにコピーできます。記載されている bca のバージョンは、執筆時点で最新の公開リリースです。
リポジトリ内のワークフローは、ピン留めされたリリースをダウンロードするのではなく、現在のチェックアウトから
bcaをビルドしてインストールします。これは、.bca-baseline.tomlが常にそれをゲートするのと同じbcaによって書かれるリポジトリにおいて、後述の GitHub Release からのbcaのインストールで説明する CLI アーティファクトのスキーマ不整合という失敗モードを避けるためです。安定リリース系列を追跡する下流の採用者は、ピン留めされた tarball のパターンを使い続けるべきです。「チェックアウトからビルド」に切り替えるのは、あなたもバイナリと同時に CLI アーティファクトのスキーマを変更している場合だけにしてください。
しきい値ゲート、SARIF、clang-warning マッチャー
既存の 3 つのレシピ、すなわちハードなしきい値ゲート、Code Scanning への SARIF アップロード、インライン PR アノテーション用の clang-warning + GCC problem matcher は、Check コマンドのページにあります。ここで再実装せず、リンク先を利用してください。
GitHub Release からの bca のインストール(推奨)
最も高速で再現性の高いインストール方法は、このリポジトリの GitHub Releases にあるビルド済み tarball です。curl | sha256sum | tar の 1 手順だけで済み、Rust ツールチェーンを必要とせず、実行のたびにバイト単位で同一のバイナリが得られます。バージョンをキーにした actions/cache と組み合わせると、正常パスの再実行ではダウンロード自体をスキップできます:
CLI アーティファクトのスキーマ互換性。 ここでピン留めする
BCA_VERSIONは、リポジトリがコミットするすべての CLI アーティファクト — 最も重要なのは(独自のversionフィールドを持つ).bca-baseline.tomlとbca.tomlマニフェスト — のスキーマバージョンをサポートしている必要があります。より新しいbca(より新しいスキーマバージョンを持つもの)が書いたベースラインファイルは、古いbcaでは読み込めず、ゲートはbaseline version N is not supported by this bcaというエラーで失敗します。mainを追跡している場合や、より新しいbcaでローカルにベースラインを再生成した場合は、新しいスキーマに対応したリリースへピン留めし直すか、ベースラインを書いたのと同じコミットを指すbcaのcargo install --gitビルドに切り替えてください(後述のcargo installの代替手段を参照)。互換性の契約は STABILITY.md に記録されています。
env:
BCA_VERSION: "2.0.0"
BCA_TARGET: "x86_64-unknown-linux-gnu"
# リリースの SHA256SUMS ファイルにある big-code-analysis-${BCA_VERSION}-${BCA_TARGET}.tar.gz の sha256。
# BCA_VERSION と合わせて更新してください。
BCA_SHA256: "a205fff13108d0f8c679a062e352ba8468109c4adfdd8c9e3567cf5fcc99c3d5"
steps:
# キャッシュキーには必ず BCA_SHA256(と BCA_TARGET)を含めてください。
# キーに sha256 が含まれていないと、バージョンを上げずに公開チェックサムを
# ローテーションした場合、キャッシュヒット時に古いバイナリが返され、
# インストールステップの `sha256sum --check`(キャッシュミス時のみ実行)を
# 黙ってバイパスしてしまいます。同じワークフローを複数の `runs-on` で
# 実行する場合は、BCA_TARGET を含めることが重要です。
- name: Cache bca binary
id: bca-cache
uses: actions/cache@v5
with:
path: ~/.local/bin/bca
key: bca-${{ runner.os }}-${{ env.BCA_TARGET }}-${{ env.BCA_VERSION }}-${{ env.BCA_SHA256 }}
- name: Install bca from GitHub Releases
if: steps.bca-cache.outputs.cache-hit != 'true'
run: |
set -euo pipefail
stage="big-code-analysis-${BCA_VERSION}-${BCA_TARGET}"
tarball="${stage}.tar.gz"
url="https://github.com/dekobon/big-code-analysis/releases/download/v${BCA_VERSION}/${tarball}"
mkdir -p "$HOME/.local/bin"
curl -fsSL --proto '=https' --tlsv1.2 -o "/tmp/${tarball}" "$url"
echo "${BCA_SHA256} /tmp/${tarball}" | sha256sum --check --strict -
tar -xzf "/tmp/${tarball}" -C /tmp
install -m 0755 "/tmp/${stage}/bca" "$HOME/.local/bin/bca"
rm -rf "/tmp/${tarball}" "/tmp/${stage}"
- name: Prepend ~/.local/bin to PATH
run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
利用可能な BCA_TARGET の値(runs-on に一致するものを選択してください): x86_64-unknown-linux-gnu、x86_64-unknown-linux-musl、aarch64-unknown-linux-gnu、aarch64-unknown-linux-musl、aarch64-apple-darwin、x86_64-pc-windows-msvc、aarch64-pc-windows-msvc。Windows のアセットは .tar.gz ではなく .zip を使用します。bca-web バイナリは同じアーカイブ内で bca と一緒に配布されます。
代替手段: ビルド済みバイナリ対応アクション経由の cargo install
ランナーから github.com に到達できないが crates.io には到達できる場合(エアギャップ環境、カスタムミラー)、次の 2 つのアクションは、ビルド済みバイナリが公開されていないときに透過的に cargo install へフォールバックします — その代償はコールドパスでのコンパイル時間です。どちらも GitHub Releases のアセットと同じ crates.io リリースにピン留めするため、CLI アーティファクトのスキーマ互換性の警告はここでもそのまま当てはまります。
最新の crates.io リリースより先の bca が特に必要な場合(例えば、コミットされた .bca-baseline.toml のスキーマが、公開されているどの bca も理解できないほど新しい場合)は、tool: big-code-analysis-cli@<version> や --version の形式を、ベースラインが生成された正確なコミットを対象とする cargo install --git https://github.com/dekobon/big-code-analysis --rev <SHA> --locked big-code-analysis-cli に置き換えてください。これはリポジトリ内の pages.yml ワークフローが(--path によりローカルチェックアウトに対して)行っていることですが、bca 自身のリポジトリのための意図的な回避策であり、下流の採用者に推奨されるデフォルトではありません。
# 選択肢 1: taiki-e/install-action
- name: Install bca
uses: taiki-e/install-action@v2
with:
tool: big-code-analysis-cli@2.0.0
# 選択肢 2: cargo-binstall
- name: Install cargo-binstall
uses: cargo-bins/cargo-binstall@main
- name: Install bca
run: cargo binstall --no-confirm big-code-analysis-cli --version 2.0.0
いずれかのアクションがコンパイルにフォールバックした場合は、2 回目の実行が速くなるように cargo レジストリとインストール済みバイナリをキャッシュしてください:
- name: Cache cargo registry and bca binary
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
~/.cargo/bin/bca
# crates.io のリリースは不変なものとして公開されるため、ここでは
# `<version>` のキーで十分です — ローテーションすべき sha256 はありません。
# (上記の GitHub Releases インストールパスは事情が異なります。再公開された
# リリースアセットはバージョンを共有するため、そのキャッシュキーには sha256 が必要です。)
key: bca-${{ runner.os }}-2.0.0
レポートが実行間で再現可能であり続けるよう、特定のバージョン(crates.io に公開されている big-code-analysis-cli のリリースに一致するもの)にピン留めしてください。バージョンを固定しないインストールでは、メトリクス集計の変更が月曜日に「謎の CI フレーク」として現れます。
Markdown レポートを PR コメントとして投稿する
bca report markdown は PR/MR コメント専用に設計されています。安定したヘッダー構造、ホットスポットごとに 1 行のテーブル、そして --strip-prefix を渡せば短いパスが得られます。marocchino/sticky-pull-request-comment と組み合わせると、プッシュのたびに新しいコメントが積み重なるのではなく、単一のコメントが更新されます:
name: bca-pr-report
on:
pull_request:
branches: [main]
jobs:
report:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Install bca
uses: taiki-e/install-action@v2
with:
tool: big-code-analysis-cli@2.0.0
- name: Generate report
run: |
bca \
report -O markdown \
--paths "$PWD" \
--top 20 \
--strip-prefix "$PWD/" \
--output report.md
- name: Post or update PR comment
uses: marocchino/sticky-pull-request-comment@v2
with:
path: report.md
header: bca-quality-report
同じ Markdown ファイルは、PR コメントに加えてワークフロー実行ページからもダウンロードできるようにしたい場合、ビルドアーティファクトとしてのアップロード(actions/upload-artifact@v7)にも適しています。
ベースライン / ラチェットパターン
bca check --baseline はネイティブのラチェットです。今日時点の違反をコミット済みの TOML ファイルに記録し、リグレッションと新規違反に対してのみ失敗させ、ファイルを時間をかけて縮小していきます。一度ブートストラップしてコミットし、CI をそのファイルに向けます:
# 開発者マシンで一度だけ実行します。両方のファイルをコミットしてください。
bca check --paths src/ \
--write-baseline .bca-baseline.toml
git add bca.toml .bca-baseline.toml
このスニペットは src/ のみからブートストラップします — 単一クレートのライブラリに適した形です。複数クレートのワークスペースについては実際の動作例を参照してください。その .github/workflows/pages.yml は、ベンダリングされた文法、生成されたツリー、テストをカバーするチェックイン済みの除外セットである --exclude-from .bcaignore を使って、リポジトリ全体をスキャンします。
除外リストはワークフロー・レシピ・ブートストラップで共有してください。 除外セットをリポジトリルートの単一ファイル(
.gitignore/.dockerignoreに倣い、慣例として.bcaignore)に置き、すべてのbca呼び出しを--exclude-from .bcaignoreでそのファイルに向けます。--exclude-fromのパターンはインラインの--exclude <GLOB>フラグと和集合され、1 つの除外セットになります —--excludeは一回限りのアドホックな除外用に残してください。ファイル内の空行と#で始まるコメント行はスキップされます。パターンは--exclude引数と同じ./プレフィックスの規約(ウォーカーが出力する形式)に従います。.bcaignoreの編集は--write-baselineによる更新とセットで行ってください — ベースラインのキーは、ウォーカーがどのファイルを訪れるかに敏感です。
- name: Threshold check with baseline
run: |
bca check --paths src/ \
--baseline .bca-baseline.toml
リグレッションした関数(current value > baseline value)は引き続き失敗します。ベースラインにない新規の違反も引き続き失敗します。改善された関数は黙って通過し、次の --write-baseline による更新までベースラインに残ります。
Each surviving violation row is prefixed with a tag so a developer can tell at a glance whether they are looking at a brand-new offender or a known one that has worsened:
[new]— この関数 / メトリクスに対するベースラインエントリがありません。[regr +N%]— 現在値が記録されたベースラインをNパーセント超過しています。特殊形式として、ベースライン値がゼロだった場合は[regr from 0]、リグレッションがベースラインの 100 倍を超える場合は[regr +>9999%]、現在値が NaN の場合は[regr NaN]となります。
The violation rows go to stdout; everything below goes to stderr. See Which stream for the full split.
After the per-violation rows, stderr carries a per-file rollup footer with the format <path>: <count> violations (worst: <metric> = <value> vs limit <limit> at L<start>), sorted by violation count descending. This is intended to be the first thing a reader looks at: which file has the most problems, and which metric is the loudest in that file. Pass --no-summary to suppress the footer for tooling that reads the merged streams.
対処しやすい失敗出力
以下の 4 つのサブセクションは、bca check の失敗出力を「違反行の羅列」から CI を意識した表現のスタックへと変えます。この PR のどのファイルがしきい値に触れたか(--since / --changed-only)、インラインのファイル diff アノテーション(--github-annotations)、レンダリングされたステップサマリーのダイジェスト($GITHUB_STEP_SUMMARY)、そしてコピー&ペーストしても安全な修復ブロックです。それぞれ独立しているので、CI サーフェスごとに自由に組み合わせられます。組み合わせた実例はこのグループの最後にあります。
差分対応モード(--since / --changed-only)
PR やプッシュで開発者が最初に抱く疑問はたいてい、ツリー全体の違反リストではなく、この変更に含まれる自分のファイルのうちどれが しきい値に触れたのか、です。2 つのフラグがそれに答えます:
--since <ref>はファイル別フッターを、「Files in this range:」セクション(<ref>とHEADの間で変更されたファイルにある違反)と、それに続く「Other offenders:」(それ以外すべて)に分割します。違反ごとの行は変更されないため、grep を前提とした既存のツールはそのまま動作し続けます。--changed-onlyは、変更されたファイル群の外にあるファイルの違反を完全に除外します。簡潔さが求められる PR ゲートに使用してください。
- uses: actions/checkout@v4
with:
# `--since origin/<base>` はマージベースを解決します。デフォルトの
# `fetch-depth: 1` チェックアウトではその ref に到達できません。`0` を
# 指定すると全履歴を取得するため、差分ベースが解決できます。
fetch-depth: 0
- name: 差分対応フッター付きのしきい値チェック
run: |
bca check --paths . --exclude-from .bcaignore \
--baseline .bca-baseline.toml \
--since "origin/${{ github.base_ref }}"
--since を省略すると、bca は次の優先順位で環境から差分ベースを自動検出します。
BCA_DIFF_BASE— 明示的にオーバーライドするための手段です。ローカルシェルや GHA 以外の CI ランナーから自動検出を模倣するために使用します。GITHUB_BASE_REF— GitHub Actions がpull_requestイベントで設定します。origin/<value>に展開されます。対応するgit fetchはランナー側の責任です。GITHUB_EVENT_BEFORE— GitHub Actions がpushイベントで、プッシュ前の HEAD の SHA に設定します。すべてゼロの SHA(強制プッシュや新規ブランチ)はシグナルなしとして扱われます。
自動検出の失敗(git がない、ref が解決できない、git チェックアウトではない)は、--changed-only なしでは致命的ではありません。bca は警告を表示し、従来どおりのツリー全体のフッターにフォールバックします。--changed-only を指定した場合、同じ失敗は致命的になります。設定を誤った CI がすべての違反を抑制して黙って合格扱いになることを防ぐためです。
"Files in this range:" バナーには、解決されたベースとそれを導いたシグナルが表示されるため、CI ログの読者はゲートが期待どおりの ref を捕捉したことを確認できます。
Files in this range (diff base: origin/main via GITHUB_BASE_REF):
./src/a.rs: 1 violation (worst: cyclomatic = 11 vs limit 2 at L1)
Other offenders:
./src/b.rs: 1 violation (worst: cyclomatic = 11 vs limit 2 at L1)
これは bca diff-baseline とは異なります。bca diff-baseline はディスク上の 2 つのパス間でベースラインファイルを比較し、追加・削除・悪化・改善されたエントリを報告します。--since は 2 つの git ref 間でソースファイルを比較します。
GitHub Actions のインラインアノテーション(--github-annotations)
GHA の UI は ::error file=…,line=…,title=…::msg ワークフローコマンドをファイル差分ビュー上のインラインアノテーションとして表示します。生のジョブログをスクロールするよりはるかに見つけやすい方法です。bca check は、3 状態の --github-annotations <auto|always|never> に従って違反ごとに 1 件ずつ出力します。auto(デフォルト)は $GITHUB_ACTIONS == "true"(すべての GHA ワークフローステップで設定されます)のときに有効化し、always は常に有効にし、never はステップ内でも抑制します(ワークフローが bca check を 2 回実行し、片方の実行だけからアノテーションを得たい場合に便利です)。引数なしの --github-annotations は always を意味します。
アノテーションは既存の違反ごとの人間向けストリームに重ねて出力され、両方が出力されます。GitHub のステップあたり 10 エラーという UI クォータを使い切らないよう、アノテーションはメトリクスごとに 10 件までに制限され、超過分は 1 行の ::error::N more <metric> violations not shown にまとめられるため、件数は常に確認できます。
- name: インラインアノテーション付きのしきい値チェック
run: |
bca check --paths . --exclude-from .bcaignore \
--baseline .bca-baseline.toml
# `--github-annotations` フラグは不要です — GHA では自動的に有効になります。
上記の --since と組み合わせると、アノテーションが違反者リスト全体ではなく PR 内のファイルを指すようになります。
ステップサマリーの Markdown ダイジェスト($GITHUB_STEP_SUMMARY)
GitHub Actions は $GITHUB_STEP_SUMMARY を公開しています。これは Markdown ファイルへのパスで、内容を書き込むとジョブ UI にそのステップのサマリービューとして表示されます。bca check は、この環境変数が設定されているとき、または --summary-file <path> が明示的に渡されたときに、ファイル別ロールアップ表、メトリクス別の件数内訳、value / limit 比による上位 10 件の違反者を含むダイジェストを追記します。--summary-file never は、$GITHUB_STEP_SUMMARY が設定されていてもダイジェストを抑制します。
ダイジェストは HTML コメントマーカー(<!-- bca-step-summary-begin --> / <!-- bca-step-summary-end -->)で囲まれているため、リトライされたステップは前のブロックを(積み重ねるのではなく)置き換えます。3 回リトライしても、最新のダイジェストがちょうど 1 つに収束します。マーカーの外側の内容(同じステップ内で先に他のツールが書き込んだサマリーなど)は保持されます。
- name: ステップサマリーダイジェスト付きのしきい値チェック
run: |
bca check --paths . --exclude-from .bcaignore \
--baseline .bca-baseline.toml
# フラグは不要です — GHA では `$GITHUB_STEP_SUMMARY` が自動的に設定されます。
ローカルユーザーは --summary-file <path> でダイジェストを任意の Markdown ファイルに書き出せます。入力が空(クリーンな実行)でも "✓ No threshold violations." ブロックが書き込まれるため、ステップサマリーからゲートが実行されたことを明確に確認できます。
修復フッター(常時有効)
ゲートが違反を検出すると、bca check は stderr に(さらに上記のステップサマリーダイジェスト内にも)末尾の --- next steps --- ブロックを出力します。
--- next steps ---
* Detailed reports: bca-reports artifact at https://github.com/<owner>/<repo>/actions/runs/<run-id>
* To refresh baseline: bca check --paths . --exclude-from .bcaignore --write-baseline .bca-baseline.toml
* Adoption guide: https://dekobon.github.io/big-code-analysis/recipes/baselines.html
このベースライン更新用の呼び出しは、ゲートで解決された --paths、--exclude、--exclude-from、--config、--baseline をそのまま反映するため、失敗した CI ログを初めて読む人でもそのままコピー&ペーストできます。アーティファクト URL は $GITHUB_REPOSITORY と $GITHUB_RUN_ID の両方が存在するとき(GHA では常に真)に導出されます。ローカル実行では指し示すべきアップロードが存在しないため、代わりに bca report を実行して詳細ビューをローカルで確認することを提案します。
Suppress the block with --no-remediation for tooling that reads the merged streams; a plain bca check | ... pipeline never sees it.
集中的なリファクタリングの後に更新します。
bca check --paths src/ \
--write-baseline .bca-baseline.toml
git diff .bca-baseline.toml # ファイルは縮小していくはずです
変更のないツリーに対して --write-baseline を 2 回実行するとバイト単位で同一の出力が生成されるため、偽の差分は違反者が実際に変化したときにのみ現れます。採用フローの全体、PR レビューのヒューリスティクス、抑制の合成規則についてはベースラインのレシピを参照してください。
すべてを組み合わせる
上記の 4 つのフラグは組み合わせて使えます。PR ゲートのワークフローで推奨される呼び出しは次のとおりです。
- uses: actions/checkout@v4
with:
# `--since origin/<base>` はマージベースを解決します。デフォルトの
# `fetch-depth: 1` ではその ref に到達できません。`0` を指定すると
# 全履歴を取得するため、差分が解決できます。
fetch-depth: 0
- name: しきい値ゲート(差分対応 + GHA UX)
run: |
bca check --paths . --exclude-from .bcaignore \
--baseline .bca-baseline.toml \
--since "origin/${{ github.base_ref }}"
# `--github-annotations` や `--summary-file` フラグは不要です。
# どちらも `$GITHUB_ACTIONS == "true"` と `$GITHUB_STEP_SUMMARY` から
# 自動的に有効になります。末尾の修復ブロックも自動的に
# 出力されます。
失敗した PR で得られるもの:
- Per-violation rows on stdout — same shape as the legacy gate, so existing grep tooling keeps working.
- ファイル別ロールアップフッター —
Files in this range:(PR で変更されたファイル)がOther offenders:の前に列挙されるため、開発者は自分の変更分を最初に確認できます。 - インライン GHA アノテーション — ファイル差分ビュー上に表示され、メトリクスごとに 10 件で打ち切られ、超過分はまとめて表示されます。
- ステップサマリーパネル — レンダリングされた Markdown ダイジェスト(ファイル別ロールアップ、メトリクス別内訳、比率による上位 10 件の違反者)を表示します。
- 末尾の修復ブロック — アーティファクト名を示し、そのまま使える
--write-baseline更新コマンドを表示し、ベースラインのレシピへリンクします。
調整ノブ:
| フラグ | 効果 | デフォルト |
|---|---|---|
--since <ref> | フッターを分割。省略時は環境から自動検出 | オフ。BCA_DIFF_BASE / GITHUB_BASE_REF / GITHUB_EVENT_BEFORE により自動検出 |
--changed-only | 差分外の違反を完全に除外 | オフ |
--github-annotations <auto\|always\|never> | ::error file=…::msg ワークフローコマンドを出力(引数なしのフラグ = always) | auto は $GITHUB_ACTIONS == "true" のとき有効化。never で無効化 |
--summary-file <path\|auto\|never> | Markdown ダイジェストを追記。never で無効化 | auto は $GITHUB_STEP_SUMMARY を検出 |
--no-remediation | 末尾の --- next steps --- ブロックを抑止 | 失敗時にブロックを出力 |
GHA の外で bca check を実行するローカルユーザーにとって、デフォルトの挙動に変化はありません。環境からのシグナルなしに自動有効化される機能は 4 つのうち 1 つもありません。GHA での体験をローカルでプレビューするには次のようにします。
GITHUB_ACTIONS=true GITHUB_STEP_SUMMARY=/tmp/bca-summary.md \
BCA_DIFF_BASE=main \
bca check --paths . --exclude-from .bcaignore \
--baseline .bca-baseline.toml
cat /tmp/bca-summary.md
GHA 以外の CI(GitLab、Buildkite、Jenkins)では、ランナーが公開する環境変数を設定する(またはフラグを明示的に渡す)ことで、同じ出力経路が動作します。
マージベースに対する違反者数の差分(暫定策)
(ポリシー上の理由などで)ベースラインファイルをコミットできないチーム向けのより粗い近似として、2 つの Checkstyle ドキュメント(マージベース上のものと PR ヘッド上のもの)の <error> 要素を数え、件数が増えたら失敗させる方法があります。
- name: マージベースに対する違反者の差分を計算
run: |
set -euo pipefail
BASE="$(git merge-base origin/main HEAD)"
git worktree add /tmp/base "$BASE"
bca check --paths /tmp/base \
--report-format checkstyle \
--output /tmp/base.xml \
--no-fail
BASE_COUNT=$(grep -c "<error" /tmp/base.xml || true)
bca check --paths "$PWD" \
--report-format checkstyle \
--output /tmp/head.xml \
--no-fail
HEAD_COUNT=$(grep -c "<error" /tmp/head.xml || true)
echo "Offenders: base=$BASE_COUNT head=$HEAD_COUNT"
if [ "$HEAD_COUNT" -gt "$BASE_COUNT" ]; then
echo "::error::Offender count grew from $BASE_COUNT to $HEAD_COUNT"
exit 1
fi
これは違反の件数を数えるだけで、その同一性は追跡しません。違反している関数の名前を変えてもリグレッションとして検出されず、ある違反者を改善しつつ別の違反者を悪化させると差し引きゼロになります。上記のネイティブなベースラインフローの方が厳密に高精度であり、推奨されるアプローチです。
セルフスキャンしきい値ゲート(CI ゲートのローカルミラー)
CI のしきい値ゲートはプッシュ後にしか作動しないため、リファクタリングが気付かないうちにメトリクスを限界値の先へ押し出していた場合には手遅れです。big-code-analysis リポジトリの Makefile は、CI ゲート(.github/workflows/pages.yml の Threshold gate ステップ)をローカルでミラーする 4 つのターゲットを公開し、さらに各限界値の 95% に第 2 の段階を追加して、ハードゲートが作動する 1〜2 コミット前に接近を検出できるようにしています。
make self-scan # ハードゲート。bca.toml のしきい値の 100%
make self-scan-headroom # ソフトゲート。デフォルト 95%(BCA_HEADROOM)
make self-scan-write-baseline # ハードしきい値でベースラインを更新
make self-scan-write-baseline-headroom # ソフトしきい値でベースラインを更新
パス選択、.bcaignore の除外セット、関数ごとのしきい値、循環的複雑度の ? ポリシー、ベースラインファイルは、すべてリポジトリルートの bca.toml マニフェストにあり、bca はこれを自動的に発見します。ハード段階は CI が実行するものとまったく同じです。展開すると、引数なしのチェック(パス / しきい値 / ベースラインのフラグなし — マニフェストが供給します)になります。
cargo run --quiet --release -p big-code-analysis-cli -- check
両段階は同じ bca.toml のしきい値と同じ .bca-baseline.toml を使用します。ソフト段階は、各しきい値に BCA_HEADROOM を掛けた上でハード段階のレシピを実行するだけです。どちらもクリーンなら 0、しきい値違反があれば 2、ツールエラーなら 1 で終了します。ソフト段階は助言的なものではなく本物のゲートなので、make self-scan-headroom を || true で包まないでください。2 つのゲートターゲット(self-scan、self-scan-headroom)は make pre-commit、make ci、.pre-commit-config.yaml に組み込まれています。これらのチェーンはハード段階をソフト段階より先に実行するため、真のリグレッションは常に限界値接近の警告より先に報告されます。2 つの write-baseline ターゲットは副作用を伴うため、意図的に組み込まれていません。
BCA_HEADROOM=0.90 make self-scan-headroom は帯域を広げ、BCA_HEADROOM=0.99 は最後の 1% まで狭めます。ソフト段階が作動したときは、make self-scan-write-baseline-headroom(すべての違反者をスケール後のしきい値で記録します — ハード段階の違反者の厳密な上位集合です)でベースラインに違反者を取り込みます。
このパターン(CI をミラーするハード段階 + 早期警告帯としてのソフト段階、どちらも同じベースラインでラチェット)はプロジェクトに依存しません。ローカルしきい値ゲートのレシピには、基礎となる原則、そのまま使える Makefile / just / package.json のスケルトン、しきい値をスケールするヘルパースクリプトが記載されており、同じワークフローを自分のリポジトリでも採用できます。汎用レシピは上記の Makefile と同じ BCA_* 環境変数名を使うため、BCA_HEADROOM=0.90 のようなオーバーライドは両方でまったく同じように機能します。
GitLab CI
完全な .gitlab-ci.yml の例
以下のジョブは bca をインストールし、しきい値チェックを実行して Code Climate JSON(MR の Code Quality ウィジェット用)、Checkstyle XML、Markdown レポートを生成し、それらをアーティファクトとしてアップロードします。
GitHub Actions セクションの CLI アーティファクトのスキーマ互換性に関する注意がここでも当てはまります。
BCA_VERSIONのピンは、リポジトリにコミットするすべての CLI アーティファクトのスキーマバージョンをカバーしなければなりません。
stages:
- quality
variables:
BCA_VERSION: "2.0.0" # 公開済みの big-code-analysis-cli リリースにピン留め
BCA_TARGET: "x86_64-unknown-linux-gnu"
# リリースの SHA256SUMS ファイルに記載された
# big-code-analysis-${BCA_VERSION}-${BCA_TARGET}.tar.gz の sha256。BCA_VERSION と一緒に更新します。
BCA_SHA256: "a205fff13108d0f8c679a062e352ba8468109c4adfdd8c9e3567cf5fcc99c3d5"
bca-quality:
stage: quality
image: debian:stable-slim
cache:
# GitHub Actions のスニペットと同じキー形式です。BCA_VERSION を
# 上げるとキャッシュは自動的に無効化されます。
key: "bca-$BCA_VERSION"
paths:
- .cache/bca/
before_script:
- apt-get update -qq && apt-get install -y --no-install-recommends ca-certificates curl tar
- |
set -euo pipefail
install -d "$CI_PROJECT_DIR/.cache/bca" "$HOME/.local/bin"
if [ ! -x "$CI_PROJECT_DIR/.cache/bca/bca" ]; then
stage="big-code-analysis-${BCA_VERSION}-${BCA_TARGET}"
tarball="${stage}.tar.gz"
url="https://github.com/dekobon/big-code-analysis/releases/download/v${BCA_VERSION}/${tarball}"
curl -fsSL --proto '=https' --tlsv1.2 -o "/tmp/${tarball}" "$url"
echo "${BCA_SHA256} /tmp/${tarball}" | sha256sum --check --strict -
tar -xzf "/tmp/${tarball}" -C /tmp
install -m 0755 "/tmp/${stage}/bca" "$CI_PROJECT_DIR/.cache/bca/bca"
rm -rf "/tmp/${tarball}" "/tmp/${stage}"
fi
install -m 0755 "$CI_PROJECT_DIR/.cache/bca/bca" "$HOME/.local/bin/bca"
export PATH="$HOME/.local/bin:$PATH"
script:
- bca
check
--paths "$PWD"
--report-format code-climate
--output gl-code-quality-report.json
--no-fail
- bca
check
--paths "$PWD"
--report-format checkstyle
--output bca-checkstyle.xml
--no-fail
- bca
report -O markdown
--paths "$PWD"
--top 20
--strip-prefix "$PWD/"
--output bca-report.md
# しきい値ゲートは別に実行するため、上記のアーティファクトは失敗時にも
# 公開されます。終了コード 2 = 少なくとも 1 件のしきい値超過。
- bca check --paths "$PWD"
artifacts:
when: always
reports:
codequality: gl-code-quality-report.json
paths:
- gl-code-quality-report.json
- bca-checkstyle.xml
- bca-report.md
この例に関する補足です。
- 最初の 2 回の
bca check … --no-fail呼び出しはアーティファクト用に違反者を収集します。最後のbca check(--no-failなし)が合否を決めるゲートです。3 回の実行はすべて同じしきい値設定を使うため、アーティファクトは常にゲートの判定と一致します。 artifacts:when: alwaysにより、パイプラインが赤のときでも — まさに最も必要になる場面ですが — すべてのアーティファクトをダウンロードできます。artifacts:reports:codequalityは Code Climate JSON を GitLab の MR Code Quality ウィジェットに直接接続します。フィールドごとの意味は下記の Code Quality ウィジェットのセクションを参照してください。
GitLab Code Quality ウィジェット
GitLab の第一級の Code Quality 体験(MR 差分上のインライン指摘、MR 概要ページのサマリー)は Code Climate JSON を読み取ります。bca check は --report-format code-climate によりこれをネイティブに出力するため、統合は 1 行で済みます。
code_quality:
stage: quality
script:
- bca check --paths "$CI_PROJECT_DIR"
--report-format code-climate
--output gl-code-quality-report.json
--no-fail
artifacts:
when: always
reports:
codequality: gl-code-quality-report.json
paths:
- gl-code-quality-report.json
重大度の帯は、各メトリクスが設定されたしきい値をどれだけ超えているか(value / limit 比。値が低いほど悪い保守容易性指数系では反転)から導出されます: ≤ 1.5× → minor、≤ 2× → major、≤ 4× → critical、> 4× → blocker。ウィジェットは fingerprint で検出結果を重複排除します。bca は path \0 function \0 metric を(行番号も値も含めずに)ハッシュ化するため、変更による行ずれを生き延びた違反は、パイプライン実行をまたいで同じウィジェットエントリに集約されます。
生成されたレポートをローカルで検証するには次のようにします。
jq 'all(.[]; has("description") and has("check_name")
and has("fingerprint") and has("severity")
and has("location"))' gl-code-quality-report.json
# → true
jq '[.[] | .severity] | unique' gl-code-quality-report.json
# → ["info","minor","major","critical","blocker"] の部分集合
Markdown レポートを MR 限定コメントとして投稿
Markdown レポートを MR ノートとして添付する(GitHub の PR コメントレシピの GitLab 版)には、プロジェクトアクセストークンと Notes API を使用します。
bca-mr-comment:
stage: quality
image: alpine:3
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
needs: ["bca-quality"]
before_script:
- apk add --no-cache curl jq
script:
- |
BODY=$(jq -Rs '.' < bca-report.md)
curl --fail --silent --show-error \
--request POST \
--header "PRIVATE-TOKEN: $CI_BCA_BOT_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"body\": $BODY}" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
CI_BCA_BOT_TOKEN は api スコープを持つプロジェクトアクセストークンです。このジョブは bca-quality に依存するため、実行前に Markdown アーティファクトが揃っています。
Jenkins / SonarQube
Jenkins(Warnings Next Generation プラグイン経由)と SonarQube(Generic Issue インポーター経由)は、どちらも Checkstyle 4.3 XML を直接読み取ります。同じ呼び出しが両方に使えます。
bca check --paths src/ \
--report-format checkstyle \
--output report.checkstyle.xml
report.checkstyle.xml を、既存の Jenkins の Record Issues / SonarQube の External Issues ステップに接続してください。Checkstyle ライターは違反者がいないときも空の(整形式の)ドキュメントを出力するため、どちらのツールもクリーンな実行を特別扱いする必要はありません。ライターのスキーマの詳細は check コマンドのページを参照してください。
汎用的な CI ガイダンス
以下はプロバイダーを問わず当てはまります。
bcaは特定のバージョンにピン留めしてください。cargo install --versionとcargo binstall --versionはどちらもbig-code-analysis-cliの公開クレートバージョンを受け付けます。バージョンを固定しないインストールでは、メトリクス計上の変更が月曜日に「不可解な CI の揺らぎ」として現れます。CLI アーティファクトのスキーマ(ベースライン、しきい値)がリポジトリにコミットしているファイルと一致するバージョンにピン留めしてください — インストールセクションのスキーマ互換性に関する注意を参照してください。--jobsのデフォルトは有効 CPU 数です。 このフラグはavailable_parallelism()に従います — Linux では cgroup / cpuset / クォータを考慮し、macOS / Windows では OS の CPU 数を使います — ので、CI ランナーであらゆるレシピに--jobs "$(nproc)"を通す必要はもうありません。--jobs 1はデフォルトではなく、デバッグ用のノブとして残っています。bca report markdownには常に--strip-prefix "$PWD/"を渡してください。 そうすればパス列は、ワークスペースパスが異なるランナー間でも同一になります。これがないと、2 つのレポートの差分は/home/runner/work/...と/builds/group/project/...のノイズに支配されます。bca.tomlはリポジトリルートに置いてください —Cargo.toml/pyproject.toml/package.jsonと同じ場所です。bcaはこれを自動的に発見するため、引数なしのbca checkがコミット済みのしきい値、パス、ベースラインを読み込みます。これをソースコードとして扱い、しきい値の緩和はコードレビューで審査してください。- 終了コードの契約。
bca checkは、クリーンなら0、しきい値違反があれば2、ツールエラー(不正な設定、未知のメトリクス、読み取れないパス)なら1で終了します。1をツールエラー専用に予約することで、CI は「関数が複雑になりすぎた」と「アナライザーがクラッシュした」を区別できます。--exit-codes=tieredを渡す(またはbca.tomlに[check] exit_codes = "tiered"を設定する)と、違反の場合を重大度で分割できます:2は新規違反者のみ、3はリグレッションのみ、4は両方、5はハード限界も同時に超えた--tier=soft違反です。tiered の終了コードはオプトインで、デフォルトは0/1/2のままです。すべての失敗状態は非ゼロのままなので、exit != 0 → fail型のラッパーはそのまま機能します — 明示的に$? -eq 2を検査するツールだけが2-5に広げる必要があります。 - ソース内の抑制マーカーを尊重し、監査には
--no-suppressを使ってください。 デフォルトのbca checkはbca: suppress/bca: suppress-fileマーカーを尊重します。--no-suppressを渡すとそれらを無視するため、監査者は生の違反者リストを確認できます。