diff --git a/.github/workflows/claude-pr-review.yml b/.github/workflows/claude-pr-review.yml index 61e6099573..c0b29b6f2e 100644 --- a/.github/workflows/claude-pr-review.yml +++ b/.github/workflows/claude-pr-review.yml @@ -10,8 +10,10 @@ # 【このリポジトリは public】 # Secret 名は CLAUDE_CODE_AUTH_TOKEN、CLI が読む環境変数は CLAUDE_CODE_OAUTH_TOKEN。 # - Secret は fork からの PR には渡らない。下の if で同一リポジトリに限定する。 -# - レビュー結果を PR に投稿すると誰でも読める。既定では投稿せず artifact 止まり。 -# POST_TO_PR を true にすると投稿する。 +# - **レビュー結果を PR に投稿する設定にしている(POST_TO_PR=true)。このリポジトリは +# public なので投稿内容は誰でも読める。** 認可の欠落など機微な指摘が出る可能性が +# あるため、公開して差し支えない内容かを運用で見ておくこと。 +# 投稿を止めるには POST_TO_PR を false にする(artifact には残る)。 # # 注: cloud-hosted の `claude ultrareview` は 2026-08 時点でこのアカウントでは # 利用できなかった("Ultrareview is currently unavailable")。ここでは @@ -25,12 +27,12 @@ on: pr_number: description: 'レビュー対象の PR 番号' required: true - # TODO(試行中): 動作確認のため有効化。確認後は workflow_dispatch のみに戻す。 pull_request: branches: ['**'] + types: [opened, synchronize, reopened, ready_for_review] env: - POST_TO_PR: 'false' + POST_TO_PR: 'true' MODEL: 'sonnet' MAX_DIFF_BYTES: '200000' # これを超える差分はレビューしない(分割が必要) @@ -39,7 +41,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 if: github.event_name == 'workflow_dispatch' || - github.event.pull_request.head.repo.full_name == github.repository + (github.event.pull_request.head.repo.full_name == github.repository && + github.event.pull_request.draft == false) permissions: contents: read pull-requests: write @@ -185,9 +188,26 @@ jobs: with: script: | const fs = require('fs'); + const MARK = ''; let body = '(レビュー結果を生成できませんでした)'; try { body = fs.readFileSync('review.md', 'utf8'); } catch (e) {} - await github.rest.issues.createComment({ - issue_number: context.issue.number, owner: context.repo.owner, - repo: context.repo.repo, body: body.slice(0, 60000), + body = MARK + '\n' + body.slice(0, 60000) + + '\n\n差分のみを対象にした自動レビューです。' + + '誤りが含まれることがあります。'; + // 同じ PR に push するたびコメントが増えないよう、既存の1件を更新する + const { data: comments } = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, repo: context.repo.repo, per_page: 100, }); + const mine = comments.find(c => c.body && c.body.includes(MARK)); + if (mine) { + await github.rest.issues.updateComment({ + comment_id: mine.id, owner: context.repo.owner, + repo: context.repo.repo, body, + }); + } else { + await github.rest.issues.createComment({ + issue_number: context.issue.number, owner: context.repo.owner, + repo: context.repo.repo, body, + }); + } diff --git a/tools/api-inventory/ci/claude-pr-review.yml b/tools/api-inventory/ci/claude-pr-review.yml index 61e6099573..c0b29b6f2e 100644 --- a/tools/api-inventory/ci/claude-pr-review.yml +++ b/tools/api-inventory/ci/claude-pr-review.yml @@ -10,8 +10,10 @@ # 【このリポジトリは public】 # Secret 名は CLAUDE_CODE_AUTH_TOKEN、CLI が読む環境変数は CLAUDE_CODE_OAUTH_TOKEN。 # - Secret は fork からの PR には渡らない。下の if で同一リポジトリに限定する。 -# - レビュー結果を PR に投稿すると誰でも読める。既定では投稿せず artifact 止まり。 -# POST_TO_PR を true にすると投稿する。 +# - **レビュー結果を PR に投稿する設定にしている(POST_TO_PR=true)。このリポジトリは +# public なので投稿内容は誰でも読める。** 認可の欠落など機微な指摘が出る可能性が +# あるため、公開して差し支えない内容かを運用で見ておくこと。 +# 投稿を止めるには POST_TO_PR を false にする(artifact には残る)。 # # 注: cloud-hosted の `claude ultrareview` は 2026-08 時点でこのアカウントでは # 利用できなかった("Ultrareview is currently unavailable")。ここでは @@ -25,12 +27,12 @@ on: pr_number: description: 'レビュー対象の PR 番号' required: true - # TODO(試行中): 動作確認のため有効化。確認後は workflow_dispatch のみに戻す。 pull_request: branches: ['**'] + types: [opened, synchronize, reopened, ready_for_review] env: - POST_TO_PR: 'false' + POST_TO_PR: 'true' MODEL: 'sonnet' MAX_DIFF_BYTES: '200000' # これを超える差分はレビューしない(分割が必要) @@ -39,7 +41,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 if: github.event_name == 'workflow_dispatch' || - github.event.pull_request.head.repo.full_name == github.repository + (github.event.pull_request.head.repo.full_name == github.repository && + github.event.pull_request.draft == false) permissions: contents: read pull-requests: write @@ -185,9 +188,26 @@ jobs: with: script: | const fs = require('fs'); + const MARK = ''; let body = '(レビュー結果を生成できませんでした)'; try { body = fs.readFileSync('review.md', 'utf8'); } catch (e) {} - await github.rest.issues.createComment({ - issue_number: context.issue.number, owner: context.repo.owner, - repo: context.repo.repo, body: body.slice(0, 60000), + body = MARK + '\n' + body.slice(0, 60000) + + '\n\n差分のみを対象にした自動レビューです。' + + '誤りが含まれることがあります。'; + // 同じ PR に push するたびコメントが増えないよう、既存の1件を更新する + const { data: comments } = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, repo: context.repo.repo, per_page: 100, }); + const mine = comments.find(c => c.body && c.body.includes(MARK)); + if (mine) { + await github.rest.issues.updateComment({ + comment_id: mine.id, owner: context.repo.owner, + repo: context.repo.repo, body, + }); + } else { + await github.rest.issues.createComment({ + issue_number: context.issue.number, owner: context.repo.owner, + repo: context.repo.repo, body, + }); + } diff --git a/tools/api-inventory/scripts/README.md b/tools/api-inventory/scripts/README.md index cea5f95135..0f2ab33231 100644 --- a/tools/api-inventory/scripts/README.md +++ b/tools/api-inventory/scripts/README.md @@ -148,15 +148,15 @@ python3 tools/api-inventory/scripts/build_checklist.py export WEKO_API_INVENTORY_DIR=/path/to/weko-secret ./install.sh # スタックを起動しておく -tools/api-inventory/scripts/remeasure.sh # 未測定の P0/P1 を測る +tools/api-inventory/scripts/remeasure.sh # 未測定の P1/P2 を測る tools/api-inventory/scripts/remeasure.sh --all-unmeasured # 未測定を全件 tools/api-inventory/scripts/remeasure.sh --nos 607,618 # no を直接指定 -tools/api-inventory/scripts/remeasure.sh --read-only # GET/HEAD のみ(データを変えない) +tools/api-inventory/scripts/remeasure.sh --allow-writes # 書き込み系も測る(データが変わる) ``` -**既定では書き込み系も実測するため実機のデータが変わる。** 著者DB・サイト情報・ -ワークフローの状態などが書き換わるので、使い捨て環境で回すか、終了後に -`./install.sh` で作り直すこと。`--read-only` なら副作用はない。 +**既定は読み取り専用(GET/HEAD のみ)で副作用がない。** 書き込み系まで測るには +`--allow-writes` を明示する。実機のデータ(著者DB・サイト情報・ワークフローの状態)が +書き換わるため、使い捨て環境で回すか、終了後に `./install.sh` で作り直すこと。 反映は `apply_probe_results.py` が行い、**`dynamic_verified` が空の行だけ**を埋める。 既存の実測値(★実証など人手で精査した記述を含む)は残す。差し替えるときは diff --git a/tools/api-inventory/scripts/remeasure.sh b/tools/api-inventory/scripts/remeasure.sh index 7c19ea3db5..4a0c8c64f1 100755 --- a/tools/api-inventory/scripts/remeasure.sh +++ b/tools/api-inventory/scripts/remeasure.sh @@ -1,16 +1,17 @@ #!/usr/bin/env bash # 未測定/指定範囲のエンドポイントを実機で測り直し、台帳に反映する。 # -# ./remeasure.sh # dynamic_verified が空の P0/P1 を測る +# ./remeasure.sh # dynamic_verified が空の P1/P2 を測る # ./remeasure.sh --all-unmeasured # 未測定を全件 # ./remeasure.sh --nos 607,618 # no を直接指定 -# ./remeasure.sh --read-only # GET/HEAD だけ(データを変えない) +# ./remeasure.sh --allow-writes # 書き込み系も測る(実機データが変わる) # # 前提: $WEKO_API_INVENTORY_DIR(台帳) と WEKO スタックが起動していること。 # -# 【注意】既定では書き込み系も実測するため **実機のデータが変わります**。 -# 著者DB・サイト情報・ワークフローの状態などが書き換わるので、 -# 使い捨て環境で回すか、終了後に環境を作り直してください。 +# 既定は **読み取り専用**(GET/HEAD のみ)で副作用がない。 +# 書き込み系まで測るには --allow-writes を明示すること。実機のデータ +# (著者DB・サイト情報・ワークフローの状態など)が書き換わるため、 +# 使い捨て環境で回すか、終了後に環境を作り直すこと。 set -euo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" : "${WEKO_API_INVENTORY_DIR:?台帳の場所を指定してください (export WEKO_API_INVENTORY_DIR=...)}" @@ -20,12 +21,12 @@ WORK="${WORK:-$(mktemp -d)}" mkdir -p "$WORK" TSV="$WEKO_API_INVENTORY_DIR/weko3_api_list.tsv" -SCOPE=p01; WRITES=--allow-writes; NOS="" +SCOPE=p12; WRITES=""; NOS="" while [ $# -gt 0 ]; do case "$1" in --all-unmeasured) SCOPE=all ;; --nos) NOS="$2"; SCOPE=nos; shift ;; - --read-only) WRITES="" ;; + --allow-writes) WRITES=--allow-writes ;; *) echo "不明な引数: $1" >&2; exit 2 ;; esac; shift done @@ -35,7 +36,7 @@ python3 "$HERE/fixtures.py" --out "$WORK/fixtures.json" echo "== 2. 対象の抽出 ==" case "$SCOPE" in - p01) awk -F'\t' 'NR>1 && $25 ~ /^P[01]/ && $16=="-" {print $1}' "$TSV" > "$WORK/nos.txt" ;; + p12) awk -F'\t' 'NR>1 && $25 ~ /^P[12]$/ && $16=="-" {print $1}' "$TSV" > "$WORK/nos.txt" ;; all) awk -F'\t' 'NR>1 && $16=="-" {print $1}' "$TSV" > "$WORK/nos.txt" ;; nos) tr ',' '\n' <<< "$NOS" > "$WORK/nos.txt" ;; esac @@ -56,5 +57,7 @@ python3 "$HERE/reconcile.py" --gate > /dev/null && echo " reconcile: 差分な echo echo "成果物: $WORK/probe.json (明細)" -echo "※ 実機のデータが変わっています。継続利用する場合は fixtures.py が冪等なので" -echo " 再投入で復旧しますが、著者DB等の副作用は残ります。" +if [ -n "$WRITES" ]; then + echo "※ 書き込み系を実測したため実機のデータが変わっています。fixtures.py は冪等ですが" + echo " 著者DB等の副作用は残ります。クリーンな状態が要るなら ./install.sh で作り直してください。" +fi