Skip to content

chore(lint): env名/エラーコードの領域跨ぎ SSoT drift 検知を追加#424

Merged
yusuke0610 merged 3 commits into
mainfrom
chore/lint-env-keys
Jun 28, 2026
Merged

chore(lint): env名/エラーコードの領域跨ぎ SSoT drift 検知を追加#424
yusuke0610 merged 3 commits into
mainfrom
chore/lint-env-keys

Conversation

@yusuke0610

@yusuke0610 yusuke0610 commented Jun 28, 2026

Copy link
Copy Markdown
Owner

概要

領域跨ぎ(BE / FE / infra / local)の SSoT drift を機械検知する scripts/lint-env-keys.sh を新設しました。env 名・エラーコードは言語境界(Python / YAML / TS)上リテラル複製を消せないため、複製を消すのではなく「複製が正本と一致しているか」を検証する方針です。

XR_refacter レビューで唯一残っていた SSoT 弱点(env 名リテラルに自動 drift 検知が無い)への対応です。

検証内容

  1. env 名: backend/app/core/env_keys.py(正本)の定数値が docker-compose.yml の environment にすべて存在するか
    • 起動時内部フラグ APP_BOOTSTRAPPEDentrypoint.sh が export)は COMPOSE_ALLOWLIST で除外
    • 検証方向は env_keys ⊆ compose(compose 側の SQLD_NODE は libsql サイドカー用で env_keys 対象外)
  2. エラーコード: backend/app/core/errors.pyErrorCode 値集合と web/src/constants/errorCodes.tsERROR_CODES が完全一致するか
    • FE 側の Record<ErrorCodeKey,...> 型縛りは FE 内で完結し、BE 起点の追加漏れを拾えないため、それを補完

変更点

  • scripts/lint-env-keys.sh 新設(rg / comm のみに依存)
  • make lint-env-keys ターゲット新設 + lint 集約 + help に追加
  • CI(test.ymltest-backend ジョブ)に「Lint SSoT」ステップを fail-fast で配線(rg はランナープリインストール、nix 非経由)
  • env_keys.py / errors.py の docstring に自動 drift 検知への参照を追記

検証

  • make lint-env-keys: pass(ネガティブテストで偽 env 定数・偽 ErrorCode を注入 → 両 drift を検知し exit 1、revert 後 OK を確認)
  • make lint-backend: pass
  • make codegen-typesweb/src/api/generated.ts: drift なし(docstring 変更は OpenAPI に非伝播)
  • test.yml: valid YAML
  • web / test-backend: 無変更のため未実行(docstring のみの変更で挙動・テストへの影響なし)

Follow-ups(別 PR)

  • Phase 2: infra(cloud_run/main.tf)/ CI の env 突き合わせまで拡張(allowlist 設計を伴う)
  • 姉妹の lint-web-messages.sh の CI 配線も検討余地あり(本 PR で grep 系 lint を CI で走らせる前例ができた)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Added automated checks to catch mismatches between backend environment settings and deployment configuration earlier in CI.
    • Added validation to keep error code values aligned between backend and frontend, reducing the risk of inconsistent error handling.
  • Chores

    • Included the new validation in the main lint workflow, so it runs as part of the standard quality checks.

env_keys.py(正本)の定数が docker-compose.yml に全注入されているか、
errors.py の ErrorCode と errorCodes.ts の ERROR_CODES が一致するかを
scripts/lint-env-keys.sh で機械検証する。言語境界上リテラル複製は消せ
ないため「複製が正本と一致するか」を検証する方針。

- scripts/lint-env-keys.sh 新設(rg/comm のみ依存)
- make lint-env-keys ターゲット + lint 集約に追加
- CI(test.yml の test-backend ジョブ)に fail-fast ステップ配線
- env_keys.py / errors.py の docstring に自動 drift 検知への参照を追記

起動時内部フラグ APP_BOOTSTRAPPED は COMPOSE_ALLOWLIST で除外。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yusuke0610, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 15 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f7fabad-319a-4e43-a3b6-d18236e4a9b3

📥 Commits

Reviewing files that changed from the base of the PR and between 9c364c9 and 8b85754.

📒 Files selected for processing (3)
  • .github/workflows/test.yml
  • Makefile
  • scripts/lint-env-keys.sh
📝 Walkthrough

Walkthrough

A new Bash script scripts/lint-env-keys.sh is added that performs two SSoT drift checks: env key names in env_keys.py vs docker-compose.yml, and ErrorCode identifiers in errors.py vs errorCodes.ts. It is wired into the Makefile as a lint-env-keys target and into the CI test-backend job.

Changes

SSoT Drift Lint

Layer / File(s) Summary
lint-env-keys.sh implementation
scripts/lint-env-keys.sh
New script with strict bash error handling, an allowlist for compose-excluded env vars, env-key drift check against docker-compose.yml, and ErrorCode parity check between errors.py and errorCodes.ts using comm.
Makefile, CI, and source annotations
Makefile, .github/workflows/test.yml, backend/app/core/env_keys.py, backend/app/core/errors.py
lint-env-keys target added to Makefile PHONY, help, and lint dependency; CI test-backend job gains a lint step; env_keys.py and errors.py gain doccomments referencing the script.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A rabbit checks each env and code,
with ripgrep running down the road,
if BE and FE drift apart,
the script will fail — it plays its part.
No drift escapes my watchful eye! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding cross-layer SSoT drift detection for env names and error codes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/lint-env-keys

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

GitHub ランナー(ubuntu-latest)と flake.nix の devshell に ripgrep が
入っておらず、test-backend の Lint SSoT ステップが rg コマンド不在で
落ちていた。抽出を grep -E + sed -E に置き換え PCRE / rg 依存を除去。
ローカル(macOS)・CI(GNU)の両方で動く。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/lint-env-keys.sh`:
- Around line 43-47: The compose key scan in lint-env-keys.sh is too broad
because it collects every uppercase YAML key from docker-compose.yml, so matches
from other services or sections can hide missing backend env vars. Update the
compose_names extraction to limit the rg/parse logic to the backend service’s
environment block only, keeping the rest of the expected_in_compose and
missing_in_compose checks unchanged.
- Around line 42-47: The env-name extraction in the lint script is comparing the
left-hand identifier instead of the actual env string literal, so it can miss
real value changes and flag harmless symbol renames. Update the logic around
env_names/expected_in_compose to parse and compare the quoted env value itself
from the source entries, then keep compose_names and missing_in_compose checks
working off those literal values. Ensure the comparison remains sorted/unique
and still respects COMPOSE_ALLOWLIST.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b387e59-e548-4a97-ab31-631c0734ba00

📥 Commits

Reviewing files that changed from the base of the PR and between 2cddc79 and 9c364c9.

📒 Files selected for processing (5)
  • .github/workflows/test.yml
  • Makefile
  • backend/app/core/env_keys.py
  • backend/app/core/errors.py
  • scripts/lint-env-keys.sh

Comment thread scripts/lint-env-keys.sh Outdated
Comment thread scripts/lint-env-keys.sh Outdated
PR #424 のレビュー指摘 2 件を反映:
- env_keys.py は symbol 名ではなく文字列値(NAME = "VALUE" の VALUE)を
  比較対象にする。symbol だけ rename しても誤検知せず、値だけ変えた drift も
  取りこぼさない
- docker-compose.yml の env 名抽出を api サービスの environment ブロックに
  限定する。全 YAML の大文字キーを拾うと他サービス(libsql の SQLD_NODE 等)の
  名前で検知漏れが起きるため

ネガティブテスト: (a) 他サービスのみに存在する名前, (b) 値のみの drift,
いずれも exit 1 で検知することを確認。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit 2a6df23 into main Jun 28, 2026
17 checks passed
yusuke0610 added a commit that referenced this pull request Jun 28, 2026
* chore(lint): env名/エラーコードの領域跨ぎ SSoT drift 検知を追加

env_keys.py(正本)の定数が docker-compose.yml に全注入されているか、
errors.py の ErrorCode と errorCodes.ts の ERROR_CODES が一致するかを
scripts/lint-env-keys.sh で機械検証する。言語境界上リテラル複製は消せ
ないため「複製が正本と一致するか」を検証する方針。

- scripts/lint-env-keys.sh 新設(rg/comm のみ依存)
- make lint-env-keys ターゲット + lint 集約に追加
- CI(test.yml の test-backend ジョブ)に fail-fast ステップ配線
- env_keys.py / errors.py の docstring に自動 drift 検知への参照を追記

起動時内部フラグ APP_BOOTSTRAPPED は COMPOSE_ALLOWLIST で除外。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(lint): lint-env-keys を ripgrep 非依存にして CI fail を解消

GitHub ランナー(ubuntu-latest)と flake.nix の devshell に ripgrep が
入っておらず、test-backend の Lint SSoT ステップが rg コマンド不在で
落ちていた。抽出を grep -E + sed -E に置き換え PCRE / rg 依存を除去。
ローカル(macOS)・CI(GNU)の両方で動く。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(lint): CodeRabbit 指摘対応(env 値比較 / compose スコープ限定)

PR #424 のレビュー指摘 2 件を反映:
- env_keys.py は symbol 名ではなく文字列値(NAME = "VALUE" の VALUE)を
  比較対象にする。symbol だけ rename しても誤検知せず、値だけ変えた drift も
  取りこぼさない
- docker-compose.yml の env 名抽出を api サービスの environment ブロックに
  限定する。全 YAML の大文字キーを拾うと他サービス(libsql の SQLD_NODE 等)の
  名前で検知漏れが起きるため

ネガティブテスト: (a) 他サービスのみに存在する名前, (b) 値のみの drift,
いずれも exit 1 で検知することを確認。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant