Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,23 @@ PR ごとに WEKO3 コンテナを起動し、`url_map` のダンプ・台帳と
実データは**プライベートリポジトリ `RCOSDP/weko-secret`** にあり、CI は Secret 経由で取得する。
以降この文書では、そこを単に**プライベートリポジトリ**と呼ぶ。

台帳はブランチごとに内容が違うため、CI は **weko 側と同名のブランチ**を
プライベートリポジトリから探して使う(head → base → 既定ブランチ の順)。
採用されたブランチ名は PR コメントの冒頭に出るので、**件数を読む前にそこを見ること**。
対応ブランチが無い場合は既定ブランチと比較され、コメント冒頭に警告が出る。
その件数は当てにならないので、PASS でも「確認済み」と読まないこと。
詳細: `tools/api-inventory/ci/README.md` §3a

- [ ] **CI が PASS している**、または FAIL の各項目に対処済み
<sub>Secret (`API_INVENTORY_REPO` / `API_INVENTORY_SSH_KEY`) が未設定のリポジトリ、
および fork からの PR では、このジョブは何もせずスキップされる。</sub>

### API を追加・変更した場合(必須)

- [ ] **プライベートリポジトリ側の作業ブランチを、この PR のブランチと同名で切った**
<sub>この PR が `fix/issue62569` → `develop_v2.0.4` なら、プライベート側も
`fix/issue62569` → `develop_v2.0.4`。同名にしておけば台帳 PR が未マージでも
CI がそれを見るので、2つの PR のマージ順を気にしなくてよい。</sub>
- [ ] **プライベートリポジトリ**の `api_snapshot.json` を更新し、対応する PR を出した
```bash
export WEKO_API_INVENTORY_DIR=/path/to/weko-secret
Expand All @@ -48,6 +59,9 @@ PR ごとに WEKO3 コンテナを起動し、`url_map` のダンプ・台帳と

### FAIL したときの対処(要約)

まず PR コメント冒頭の**台帳ブランチ**を見る。警告が出ていれば、件数を追う前に
プライベートリポジトリ側の対応ブランチを用意すること(比較相手が違うので件数に意味がない)。

ジョブが落ちる条件は 3 つある。PR コメントのどのセクションに件数が出ているかで切り分ける。

| 落ちた場所 | 落ちる条件 |
Expand Down
62 changes: 60 additions & 2 deletions .github/workflows/api-inventory-drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# したがって:
# - 台帳(所見・実証結果を含む)とベースラインは **このリポジトリに置かない**。
# プライベートリポジトリ(RCOSDP/weko-secret)から Secret 経由で取得する。
# - 台帳は WEKO3 のブランチごとに内容が違う。既定ブランチを固定で見ると、ブランチ間の
# 経路差がそのまま差分として出続けて形骸化する。PR の head → base → 既定 の順で
# プライベートリポジトリの**同名ブランチ**を探して使う(Resolve inventory ref)。
# - 出力は --summary-only で **件数のみ**。URI や endpoint 名は出さない。
# 明細はプライベートリポジトリ側に置いたレポートで確認する。
#
Expand Down Expand Up @@ -47,13 +50,53 @@ jobs:
echo "::notice::API_INVENTORY_REPO / API_INVENTORY_SSH_KEY が未設定のためスキップします"
fi

# 使う台帳ブランチを決める。存在しない ref を checkout に渡すと落ちるので、
# 先に ls-remote で候補を絞る。
# 1. PR の head ブランチ名 台帳更新 PR が**未マージでも**拾える(順序制約を作らない)
# 2. PR の base ブランチ名 台帳を触らない PR、および両方マージ後の定常状態
# 3. 既定ブランチ 警告を出して続行(件数は当てにならない)
- name: Resolve inventory ref
id: ref
if: steps.cfg.outputs.enabled == 'true'
env:
REPO: ${{ secrets.API_INVENTORY_REPO }}
KEY: ${{ secrets.API_INVENTORY_SSH_KEY }}
HEAD_REF: ${{ github.event.pull_request.head.ref }}
BASE_REF: ${{ github.event.pull_request.base.ref || github.ref_name }}
run: |
set -eu
d=$(mktemp -d); trap 'rm -rf "$d"' EXIT
printf '%s\n' "$KEY" > "$d/key"; chmod 600 "$d/key"
export GIT_SSH_COMMAND="ssh -i $d/key -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new"
# 出るのはブランチ名だけ。鍵も台帳の中身も出ない。
# 認証に失敗したらここで落とす(黙って既定ブランチに落ちるのを防ぐ)。
heads=$(git ls-remote --heads "git@github.com:$REPO.git")
have() { printf '%s\n' "$heads" | awk -v r="refs/heads/$1" '$2==r{f=1} END{exit !f}'; }
pick=''
if [ -n "${HEAD_REF:-}" ] && have "$HEAD_REF"; then
pick="$HEAD_REF"
elif [ -n "${BASE_REF:-}" ] && have "$BASE_REF"; then
pick="$BASE_REF"
fi
if [ -n "$pick" ]; then
echo "ref=$pick" >> "$GITHUB_OUTPUT"
echo "fallback=false" >> "$GITHUB_OUTPUT"
echo "::notice::台帳ブランチ: $pick"
else
echo "ref=" >> "$GITHUB_OUTPUT"
echo "fallback=true" >> "$GITHUB_OUTPUT"
echo "::warning::プライベートリポジトリに ${HEAD_REF:-} / ${BASE_REF:-} のいずれもありません。既定ブランチの台帳と比較します。ブランチ間の経路差がそのまま差分に出るため件数は当てになりません。同名ブランチを作ってください。"
fi

# 台帳・ベースラインをプライベートリポジトリから取得する。
# チェックアウト先は .api-inventory-data/(.gitignore 済み)。
# ref が空文字なら actions/checkout は既定ブランチを取る(上記フォールバック)。
- name: Checkout inventory data (private)
if: steps.cfg.outputs.enabled == 'true'
uses: actions/checkout@v4
with:
repository: ${{ secrets.API_INVENTORY_REPO }}
ref: ${{ steps.ref.outputs.ref }}
ssh-key: ${{ secrets.API_INVENTORY_SSH_KEY }}
path: .api-inventory-data
persist-credentials: false
Expand Down Expand Up @@ -136,15 +179,30 @@ jobs:
- name: Comment on PR (counts only)
if: always() && steps.cfg.outputs.enabled == 'true' && github.event_name == 'pull_request'
uses: actions/github-script@v7
env:
INVENTORY_REF: ${{ steps.ref.outputs.ref }}
INVENTORY_FALLBACK: ${{ steps.ref.outputs.fallback }}
with:
script: |
const fs = require('fs');
const read = (p, title) => {
try { return `\n\n### ${title}\n\n` + fs.readFileSync(p, 'utf8'); }
catch (e) { return `\n\n### ${title}\n\n(生成されませんでした)`; }
};
let body = '## API インベントリ差分(件数のみ)\n\n'
+ '> 明細は公開できないため件数のみ表示しています。'
// どの台帳と比べた件数なのかが分からないと、レビュアは数字を判断できない。
const ref = process.env.INVENTORY_REF;
const fallback = process.env.INVENTORY_FALLBACK;
let body = '## API インベントリ差分(件数のみ)\n\n';
if (fallback === 'true') {
body += '> ⚠️ **プライベートリポジトリに対応ブランチが無いため、既定ブランチの台帳と比較しています。**\n'
+ '> ブランチ間の経路差がそのまま差分として出るので、以下の件数は当てになりません。\n'
+ '> この PR のブランチと同名のブランチをプライベートリポジトリに作ってください。\n\n';
} else if (ref) {
body += `> 台帳ブランチ: \`${ref}\`\n\n`;
} else {
body += '> ⚠️ 台帳ブランチを解決できませんでした(Resolve inventory ref が失敗しています)。\n\n';
}
body += '> 明細は公開できないため件数のみ表示しています。'
+ '該当箇所はプライベートリポジトリ側の台帳・レポートで確認してください。';
body += read('/tmp/drift.md', 'ベースラインとの差分');
body += read('/tmp/reconcile.md', '台帳との突き合わせ');
Expand Down
57 changes: 55 additions & 2 deletions tools/api-inventory/ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ git add -A && git commit -m "chore(ci): API インベントリ差分検知を追
**公開リポジトリにはデータを一切 commit しないこと。** `git status` で `tools/api-inventory/` 配下に
`*.tsv` や `api_snapshot.json` が現れたら、置き場所を間違えている。

また、プライベートリポジトリ側にも **weko と同名のブランチ**を作っておくこと(§3a)。

3 のベースラインは**そのブランチのリビジョンで取り直す**こと。
weko-document に置いてあるものは `d2fdc0e3b`(v2.0.3) 時点なので、
導入先のブランチが進んでいれば差分が出る。
Expand All @@ -133,18 +135,67 @@ weko-document に置いてあるものは `d2fdc0e3b`(v2.0.3) 時点なので、
python3 tools/api-inventory/scripts/snapshot.py \
--out "$WEKO_API_INVENTORY_DIR/api_snapshot.json"
# → プライベートリポジトリ側で commit / PR を作る
# ブランチ名は weko 側の作業ブランチと**同名**にする(§3a)
```

差分は**プライベートリポジトリの `git diff`** に出る。「どの経路が増えたか・認証がどう変わったか」を
レビュアの目に入れる仕組みは維持されるが、見る場所がプライベートリポジトリ側になる。
公開リポジトリの CI は件数だけを報告し、詳細は出さない。

なお PR の CI は「PR ブランチの実機」と「PR ブランチのベースライン」を比べるため、
ベースラインを更新すると差分は 0 になる。**変更の妥当性を見るのは CI ではなくレビュア**で、
なお PR の CI は「PR ブランチの実機」と「**対応するブランチの**ベースライン」を比べるため
(対応の決め方は §3a)、ベースラインを更新すると差分は 0 になる。
**変更の妥当性を見るのは CI ではなくレビュア**で、
CI の役割は「ベースラインを更新せずに API を変えること」を防ぐことにある。

---

## 3a. ブランチの対応(weko ⇔ プライベートリポジトリ)

台帳とベースラインは **WEKO3 のブランチごとに内容が違う**。`develop_v2.0.4` のコードを
`main` の台帳と突き合わせれば、ブランチ間の経路差がそのまま A/B/C/D/E として出る。
件数が常に非ゼロになれば、そこから先は誰も読まなくなる。

**規則: プライベートリポジトリには、weko 側と同名のブランチを作る。**
`develop_v2.0.4` には `develop_v2.0.4`、`fix/issue62569` には `fix/issue62569`。

CI の `Resolve inventory ref` ステップが、次の順で使うブランチを決める。

| 順 | 見るブランチ | 使う場面 |
|---|---|---|
| 1 | PR の **head** ブランチ名 | 台帳更新 PR がまだマージされていない段階。作業ブランチ上の台帳を見る |
| 2 | PR の **base** ブランチ名 | 台帳を触らない PR。および両方がマージされた後の定常状態 |
| 3 | 既定ブランチ | 1・2 のどちらも無い場合。`::warning::` と PR コメント冒頭の警告を出して続行する |

採用したブランチ名は **PR コメントの冒頭に出る**。件数を読む前にそこを見ること。

### なぜ head を先に見るのか

公開リポジトリのコード変更と台帳更新は別 PR になる(§3)。base 同士だけで対応させると、
weko の PR の CI が回る時点で台帳更新はまだプライベートリポジトリの作業ブランチにあり、
`develop_v2.0.4` には入っていない。「プライベート側を先にマージしないと公開側の CI が
通らない」という直列の制約ができてしまう。head を先に見れば、2つの PR を並行して
レビューでき、マージ順にも依存しない。

```
RCOSDP/weko fix/issue62569 ──PR──> develop_v2.0.4
│ 同名で対応する
RCOSDP/weko-secret fix/issue62569 ──PR──> develop_v2.0.4
```

作業ブランチは**両方のリポジトリで同じ名前**にする。台帳を触らない変更なら
プライベート側にブランチを作らなくてよい(2 の base 解決に落ちる)。

### 対応ブランチが無いとき

ジョブは止まらないが、出る件数は当てにならない。新しいリリースラインを切ったら、
プライベートリポジトリ側にも同名ブランチを作り、そのリビジョンでベースラインを
取り直すこと(§2 の 3、§3b)。

FAIL にせず警告に留めているのは、対応ブランチの無いリリースラインで一律にすべての PR が
止まるのを避けるため。**警告が出ている PR の件数を「PASS だった」と読まないこと。**

---

## 3b. ベースラインは CI と同じ環境で作る

`api_snapshot.json` は `meta.packages` にインストール済みパッケージの版を持ち、
Expand Down Expand Up @@ -184,10 +235,12 @@ git push origin v2.0.3
```

タグ名は **WEKO3 側のタグと同じ**にする(`v2.0.3` なら `v2.0.3`)。
ブランチを同名で対応させる(§3a)のと同じ理由で、タグも同名で対応させる。
メッセージには対象コミットの完全な SHA と、その時点の台帳規模・突き合わせ結果を残す。

### バージョンアップ時の流れ

0. プライベートリポジトリに **WEKO3 と同名のブランチ**を作る(§3a)
1. WEKO3 の新バージョンで `install.sh` → `snapshot.py` でベースラインを作り直す
2. `reconcile.py` の差分を 0 にする(新規経路を台帳に追加、消えた経路を整理)
3. `changed_rows.py` が出す行を Phase 2-3 で再確認する
Expand Down
Loading
Loading