diff --git a/.github/workflows/api-inventory-drift.yml b/.github/workflows/api-inventory-drift.yml index 5131b55c6c..9bf2cc580c 100644 --- a/.github/workflows/api-inventory-drift.yml +++ b/.github/workflows/api-inventory-drift.yml @@ -17,6 +17,13 @@ # 個人アカウントに紐づかないため(PAT より事故時の影響が小さい)。 # 未設定なら、このジョブは何もせずスキップする(fork からの PR でも安全)。 # +# 網羅性は二段で見る: +# reconcile.py 実機 url_map ↔ 台帳(この環境で登録されている経路) +# detect_routes.py ソース(AST) ↔ 台帳(config で無効な経路まで含む) +# 前者だけだと、config で無効・プラグイン未導入の経路が台帳から落ちても気付けない。 +# +# ツールそのものの単体テストは api-inventory-tests.yml(Secret も Docker も不要)。 +# # 設置手順: tools/api-inventory/ci/README.md name: API Inventory Drift @@ -209,6 +216,13 @@ jobs: --snapshot /tmp/api_snapshot.new.json \ --summary-only --gate --out /tmp/reconcile.md + # 実機 url_map は「この環境で登録された経路」しか映さない。config で無効・ + # プラグイン未導入・設定値が真のときだけ登録される経路は、API として + # 存在するのに reconcile では見えない。ソースからの検知で二段目を張る。 + python3 $T/detect_routes.py \ + --weko-root "$PWD" --cross-check \ + --summary-only --gate --out /tmp/detect.md + - name: Probe changed endpoints if: always() && steps.cfg.outputs.enabled == 'true' env: @@ -237,6 +251,7 @@ jobs: path: | /tmp/drift.md /tmp/reconcile.md + /tmp/detect.md - name: Comment on PR (counts only) if: always() && steps.cfg.outputs.enabled == 'true' && github.event_name == 'pull_request' @@ -268,6 +283,7 @@ jobs: + '該当箇所はプライベートリポジトリ側の台帳・レポートで確認してください。'; body += read('/tmp/drift.md', 'ベースラインとの差分'); body += read('/tmp/reconcile.md', '台帳との突き合わせ'); + body += read('/tmp/detect.md', 'ソース由来の経路検知'); await github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, diff --git a/.github/workflows/api-inventory-tests.yml b/.github/workflows/api-inventory-tests.yml index 602ee772d4..eaf6ff6260 100644 --- a/.github/workflows/api-inventory-tests.yml +++ b/.github/workflows/api-inventory-tests.yml @@ -19,6 +19,7 @@ on: paths: &paths - 'tools/api-inventory/**' - '.github/workflows/api-inventory-tests.yml' + - '.github/workflows/api-inventory-drift.yml' push: branches: ['**'] paths: *paths diff --git a/tools/api-inventory/ci/api-inventory-tests.yml b/tools/api-inventory/ci/api-inventory-tests.yml index 602ee772d4..eaf6ff6260 100644 --- a/tools/api-inventory/ci/api-inventory-tests.yml +++ b/tools/api-inventory/ci/api-inventory-tests.yml @@ -19,6 +19,7 @@ on: paths: &paths - 'tools/api-inventory/**' - '.github/workflows/api-inventory-tests.yml' + - '.github/workflows/api-inventory-drift.yml' push: branches: ['**'] paths: *paths diff --git a/tools/api-inventory/tests/test_workflows.py b/tools/api-inventory/tests/test_workflows.py new file mode 100644 index 0000000000..8cf35be26e --- /dev/null +++ b/tools/api-inventory/tests/test_workflows.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +"""ワークフローの原本(ci/)と実体(.github/workflows/)がずれていないかを検査する。 + +GitHub Actions が動かすのは `.github/workflows/` 側だけで、`ci/` 側は原本に過ぎない。 +片方だけ直すと、手順書と原本を読んだ人は「その検査は回っている」と思い込む。 +実際に `detect_routes.py` の段が原本にだけ入り、実体の drift ワークフローからは +抜けたまま、ソース由来の経路検知が CI で一度も走っていなかった。 +""" +import os + +import pytest + +from conftest import SCRIPTS + +TOOL = os.path.dirname(SCRIPTS) +CI = os.path.join(TOOL, 'ci') +# リポジトリのルート直下にある(ツールだけ取り出した環境には無い)。 +ROOT = os.path.dirname(os.path.dirname(TOOL)) +WORKFLOWS = os.path.join(ROOT, '.github', 'workflows') + +ORIGINALS = sorted(f for f in os.listdir(CI) if f.endswith('.yml')) + + +def test_原本のワークフローがある(): + assert ORIGINALS, f'{CI} に .yml が無い' + + +@pytest.mark.skipif(not os.path.isdir(WORKFLOWS), + reason='.github/workflows が無い(ツールだけ取り出した環境)') +@pytest.mark.parametrize('name', ORIGINALS) +def test_原本と実体が一致する(name): + actual = os.path.join(WORKFLOWS, name) + assert os.path.isfile(actual), \ + f'.github/workflows/{name} が無い。原本を置いただけでは動かない' + with open(os.path.join(CI, name), encoding='utf-8') as f: + original = f.read() + with open(actual, encoding='utf-8') as f: + assert f.read() == original, \ + f'ci/{name} と .github/workflows/{name} がずれている。' \ + '変更したら両方に反映すること(ci/README.md §2 の 5)'