Skip to content

lint を ruff に統一し、CI と Dependabot を新設する - #14

Merged
ryuuji merged 2 commits into
masterfrom
chore/ruff-lint
Aug 14, 2026
Merged

lint を ruff に統一し、CI と Dependabot を新設する#14
ryuuji merged 2 commits into
masterfrom
chore/ruff-lint

Conversation

@ryuuji

@ryuuji ryuuji commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Python の lint を autopep8 から ruff に統一し、あわせて .github を新設しました。CALIL org 横断で lint を ruff に寄せる作業の一部です。

なぜこのリポジトリが対象になったか

autopep8 は linter ではありません

autopep8 は formatter であって linter ではないので、このリポジトリにはこれまで lint に相当するものが実質存在しませんでした。 setup.cfgtox.ini も無く autopep8 はデフォルト設定だったので、移植すべき設定もありません。

ruff は formatter(ruff format)と linter(ruff check)の両方を1つで担うので、autopep8 の役割を包含したうえで lint が増えます。

設定

CALIL org 共通の形にしました。

[tool.ruff]
target-version = "py314"
line-length = 120

[tool.ruff.format]
quote-style = "single"

[tool.ruff.lint]
select = ["E", "W", "F", "I", "UP", "B", "SIM", "ASYNC", "RUF100"]
ignore = ["B008"]

ignoreB008 は FastAPI の Depends() を引数の既定値に置くパターンで、このリポジトリでは現在使っていませんが、org 共通の形を崩さないために入れてあります。

select を書かないと危険です。 ruff 0.16.3 のゼロコンフィグ既定は --show-settings で確認すると 413ルール / 38ファミリまで広がっていて、旧来の E4,E7,E9,F ではありません。明示しないと ruff を上げるたびに指摘が増えて CI が突然赤くなります。

main.py の import 構造を手で直しました

ここだけ機械的修正では直せない部分です。もともとこうなっていました。

import json
import codecs

from fastapi import FastAPI
from fastapi.responses import HTMLResponse, ORJSONResponse
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=['*'])


import io
import zipfile
import ndc_parser

import 群の途中に app = FastAPI()app.add_middleware(...) が挟まっていて、その下にさらに import が続く形です(E402 が3件)。

ruff の isort は非 import 文をまたいで import を移動しないので、--fix では直りませんE402 は報告するだけで fix を持ちません)。逆に言えば、自動修正でこの構造が壊れる心配もありません。実際に --diff を取って app = FastAPI()add_middleware の順序が変わらないことを確認したうえで、手で並べ替えました。app の生成と add_middleware の順序関係は変えていません。

ruff check --fix が入れたのは I001(import 順)と SIM117(入れ子の with を1つにまとめる)で、後者は意味が変わりません。--unsafe-fixes は使っていません。

.github がまるごと無かったので新設しました

CI も Dependabot も zizmor も、何もありませんでした。

静的解析ジョブruff check --output-format=github(PR の該当行に注釈が出ます)、ruff format --check、それに読み込み確認です。

読み込み確認は import main です。main.py は import するだけで zips/ を展開して NDC を全件パースするので、これ自体が ndc-parser と FastAPI のスモークテストになります(テストが無いため唯一の実行時チェックです)。手元で実行すると NDC8 が 10,340件、NDC9 が 12,388件でした。

Docker ジョブは本番と同じ gunicorn + UvicornWorker で起動して /ndc9/123 が応答するところまで見ます。Dockerfile が外部認証を必要としない自己完結した構成なので、起動確認まで入れられました。cache-from: type=gha / cache-to: type=gha,mode=max を付けています。

CI 完了 ジョブは、将来ブランチ保護を掛けるときに必須チェックをこれ1つだけ指定すれば済むようにするためのものです。ジョブを増減しても保護の設定が腐りません。

uv sync --frozen はロックのずれを検出しません

新設した CI では --locked を使っています。uv 0.12 のヘルプに、

  • --locked"Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated, uv will exit with an error"
  • --frozen"Instead of checking if the lockfile is up-to-date, uses the versions in the lockfile as the source of truth"

と明記されています。Dockerfile 側は --frozen なので(コメントには「ずれていれば失敗する」と書いてありますが、実際には失敗しません)、ずれの検出はこの CI でしか行われません。

zizmor の設定について

unpinned-uses のポリシーに ndc-dev/* を足しました。CALIL/* も残しているのは、ワークフローを org 間でコピーしても判定が変わらないようにするためです(理由はファイル内のコメントに書いてあります)。

なお actions-security-check.yml は CALIL/workflows の雛形をそのままコピーしていますが、ci.yml には配布元のリポジトリ名を書くコメントを入れていません。 このリポジトリは public なので、private リポジトリを指す記述は避けています。

手元で確認したこと

uv sync --locked                       → 通る
uv run ruff check .                    → All checks passed!
uv run ruff format --check .           → 3 files already formatted
uv run python -c "import main; ..."    → 10340 12388
uvx zizmor@1.28.0 --min-severity low .github/workflows/ → No findings to report
uvx yamllint(key-duplicates)         → 0件

yamllint を回しているのは、重複キーがあると GitHub がワークフロー全体を拒否する(ジョブが1本も作られず failure になり、ログも出ない)のを防ぐためです。PyYAML と zizmor は重複キーを後勝ちで黙って読むので検出できません。

Docker ジョブは手元に docker が無いので検証できていません。この PR の実行が初回検証になります。

変更点

  • pyproject.toml: autopep8>=2.3.2 を削除、devruff>=0.16.3[tool.ruff] 一式を追加
  • Dockerfile: --no-dev のコメントの autopep8 への言及を ruff に修正(--no-dev は元からあるので ruff は本番イメージに入りません)
  • main.py: import 構造を手で修正(E402 3件)、ruff check --fixruff format
  • validate.py: ruff check --fixruff format
  • .github/workflows/ci.yml: 新設
  • .github/workflows/actions-security-check.yml.github/zizmor.yml: 新設
  • .github/dependabot.yml: 新設(uv / github-actions / docker / terraform)

Dependabot 用のラベル(python / github-actions / docker / terraform / Actionsのセキュリティ)は事前に作成済みです。Dependabot は存在しないラベルを作らず黙って無視するので、先に作る必要があります。

関連

Todoist: Python の lint を ruff に統一する(5リポジトリ)

ブランチ保護(必須チェックの設定)は別タスクにしています。現状このリポジトリは保護が無いので、この CI は赤でもマージできます。

🤖 Generated with Claude Code

https://claude.ai/code/session_01BsERiWbzZwB6EdGoyyqcpT

ryuuji and others added 2 commits August 14, 2026 23:40
autopep8 2.3.2 を外して ruff 0.16.3 に統一する。

autopep8 は formatter であって linter ではないため、このリポジトリには
これまで lint に相当するものが実質存在しなかった。設定ファイル
(setup.cfg / tox.ini など) も1つも無く、autopep8 はデフォルト設定
だったので、移植すべき設定も無い。

main.py の import 構造を手で直した。もともと import 群の途中に
app = FastAPI() と app.add_middleware(...) が挟まっていて、その下に
io と zipfile と ndc_parser の import が続く形だった (E402 が3件)。
すべての import を先頭にまとめ、app の生成と add_middleware の
順序関係は変えていない。

ruff check --fix が入れた変更は I001 と SIM117 で、SIM117 は
入れ子の with を1つにまとめるもの。意味は変わらない。
--unsafe-fixes は使っていない。

Dockerfile は --no-dev があるので ruff は既定グループの dev に置いた。
コメントの autopep8 への言及も直した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsERiWbzZwB6EdGoyyqcpT
これまで .github ディレクトリそのものが存在せず、自動検証も依存更新も
まったく動いていなかった。

CI は2ジョブ。静的解析ジョブは ruff check と ruff format --check、
それに読み込み確認。main.py は import するだけで zips を展開して
NDC を全件パースする (NDC8 が 10340件、NDC9 が 12388件) ので、
これが実質のスモークテストになる。テストが無いため唯一の実行時チェック。

Docker ジョブは本番と同じ gunicorn と UvicornWorker で起動して
/ndc9/123 が応答するところまで見る。Dockerfile が外部認証を必要と
しない自己完結した構成なので、起動確認まで入れられる。

uv sync は --frozen ではなく --locked を使う。--frozen はロックの
ずれを検出しないため (uv 0.12 のヘルプに "Instead of checking if the
lockfile is up-to-date" と明記されている)。Dockerfile 側は --frozen
なので、ずれの検出はこの CI でしか行われない。

CI 完了ジョブは、将来ブランチ保護を掛けるときに必須チェックを
これ1つだけ指定できるようにするため。

zizmor.yml の unpinned-uses ポリシーには ndc-dev/* を足した。
CALIL/* も残しているのは、ワークフローを org 間でコピーしても判定が
変わらないようにするため。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsERiWbzZwB6EdGoyyqcpT
@ryuuji
ryuuji merged commit 258d4cc into master Aug 14, 2026
5 checks passed
@ryuuji
ryuuji deleted the chore/ruff-lint branch August 14, 2026 14:46
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