Repository navigation
review by AI #256
Description
template-python 0.0.13 批判的レビューレポート
最新ノウハウ(2026年10月時点)に基づく修正事項と、新テンプレートの提案
| 項目 | 内容 |
|---|---|
| 対象 | template-python-0.0.13.zip(36 ファイル。CI/CD 6 ワークフロー、Dockerfile、Makefile、Python パッケージ、テスト、MkDocs ドキュメント、uv.lock 144 パッケージ) |
| レビュー日 | 2026-10-12 |
| 成果物 | 本レポート、および新テンプレート一式 repos/template-python/(全アセット同梱) |
| 方法 | 全ファイルの精読 / uv.lock の依存グラフ解析 / テスト挙動のオフライン再現 / 2026-10-12 時点の一次情報(GitHub Docs・Changelog、各ツールのリリースノート、PyPI)の調査 |
1. エグゼクティブサマリー
1.1 総評
現行テンプレートは「SHA ピン留め」「uv --locked」「import-linter」「zizmor/actionlint」など良い素材を揃えている一方で、品質ゲートとしての正しさとサプライチェーン上の検証可能性に重大な欠陥があり、そのままプロダクションのひな形として配布するのは推奨できません。主な理由は次の 5 点です。
- テストゲートが壊れている: ライブラリのロガーが
propagate=Falseを設定しているため、pytest のcaplog(root ロガーにハンドラを追加する方式)がログを受け取れず、tests/test_core.pyの 3 テストは失敗します。同じ仕組みをオフラインで再現し、捕捉件数 0 件を確認しました(A-1)。 - リリースが誤ったものを公開しうる: プレリリースタグ
v1.2.3-rc.1を push すると、安定版タグ1.2.3とlatestが上書きされます(D-1)。テスト結果を待たずに公開し(D-2)、Docker Hub と GHCR を別々にビルドするため同一バージョンでもダイジェストが一致しません(D-3)。 - 検証可能性(Provenance)が無い: Dockerfile は
uv export --no-hashes→pip installでハッシュ検証を捨てています(C-1)。成果物の来歴証明(Artifact Attestations)、SBOM、イミュータブルリリースもありません(C-5)。 - 「失敗を可視化する」という自らの原則に反している: Trivy は非ブロッキング、zizmor は
--offline --min-severity highのため、オンライン監査と medium 以下の指摘(credential の残留、過剰権限など)を素通りさせます(C-2, C-3)。 - GitHub プラットフォーム機能をほぼ使っていない: ルールセット、必須チェック、CodeQL、依存関係レビュー、シークレットスキャン、Environments、OIDC、Pages の Actions デプロイ、Copilot のリポジトリカスタマイズ(AGENTS.md、セットアップステップ、エージェント、スキル、フック)がありません(I-1, J-1 ほか)。
加えて、2026 年 10 月時点では Python 3.10 が EOL(2026-10-01)、Python 3.15 が GA(2026-10-09)、Actions ランナーから Node 20 が削除(2026-09-23)、MkDocs 1.x は保守停止・Material for MkDocs は保守モード(2027-05-05 まで)、ubuntu-latest が 26.04 へ移行開始(2026-10-19〜) という環境変化があり、テンプレートの前提そのものを更新する必要があります。
1.2 重大指摘(P0/P1 の上位 12 件)
| ID | 重要度 | 指摘 | 影響 |
|---|---|---|---|
| A-1 | P0 | propagate=False により caplog がログを捕捉できず、テスト 3 件が失敗 |
品質ゲートが成立しない |
| D-1 | P0 | プレリリースタグが安定版タグと latest を上書きする |
利用者に RC が配布される |
| C-1 | P0 | コンテナでハッシュ検証なしの pip install |
ロックの改ざん耐性が無効になる |
| D-2 | P1 | タグ push でテストを経ずに公開 | 壊れたコミットを公開しうる |
| D-3 | P1 | レジストリごとに二重ビルドし、ダイジェストが不一致 | 再現性・検証性が失われる |
| C-2 | P1 | zizmor がオフラインかつ high 以上のみ | 権限・認証情報系の指摘を見逃す |
| C-3 | P1 | Trivy が非ブロッキング(Trivy 自体も 2026-03 に侵害事案あり) | 脆弱イメージを公開しうる |
| C-5 | P1 | 来歴証明・SBOM・イミュータブルリリースが無い | 利用者が改ざんを検証できない |
| E-1 | P1 | コンテナが root で実行される | 侵害時の影響範囲が拡大 |
| F-1 | P1 | ライブラリがハンドラ・伝播・レベルを設定する | アプリ側のログ設定を破壊する |
| I-1 | P1 | ルールセット・必須チェック・タグ保護が無い | ゲートを迂回してマージ・公開できる |
| J-1 | P1 | copilot/** を CI 対象にしながら Copilot 用の構成が無い |
エージェントが規約・環境を知らない |
1.3 観点別スコアカード
5 段階評価です(5 = プロダクション水準)。
| 観点 | 現行 | 新テンプレート | 主な改善 |
|---|---|---|---|
| テストの正しさ・網羅性 | 1 | 4 | 回帰テスト、CLI E2E、Hypothesis、ブランチカバレッジ 90% |
| 静的解析 | 3 | 5 | Ruff 34 ルール群、mypy strict に一本化、import-linter 2 契約、deptry |
| CI 設計 | 2 | 5 | 並列ジョブ、ci-success 集約、merge_group、concurrency、OS/Python 行列 |
| サプライチェーン | 2 | 5 | ハッシュ検証、zizmor オンライン監査、pip-audit、依存関係レビュー、Scorecard |
| リリース/CD | 1 | 5 | タグ検証 → CI → attest → ネイティブマルチアーキ → イミュータブルリリース |
| コンテナ | 2 | 4 | 非 root、venv のみコピー、ビルドチェックをエラー扱い、Trivy ブロック |
| アプリ設計 | 2 | 4 | 層分離、型付き設定、JSON ログ、終了コード設計 |
| 開発者体験 | 3 | 5 | Dev Container/Codespaces、uv 単一管理、make check、プロジェクト初期化ツール |
| ドキュメント | 2 | 4 | Zensical(strict)、英日併記、ADR |
| GitHub ガバナンス | 1 | 5 | ルールセット JSON、設定のコード化、Environments、OIDC |
| AI 駆動開発 | 1 | 5 | AGENTS.md、セットアップステップ、エージェント、スキル、フック、MCP |
2. レビューの範囲・方法・前提
2.1 対象
ワークフロー 6 本(test / docker / docker-release / ghcr-release / github-pages / azure-static-web-app)、dependabot.yaml、.pre-commit-config.yaml、.devcontainer/devcontainer.json、.vscode/extensions.json、Dockerfile、.dockerignore、compose.yml、Makefile、pyproject.toml、uv.lock、template_python/(4 モジュール)、scripts/template.py、tests/(3 モジュール)、docs/(4 ページ)、mkdocs.yml、notebooks/templates.ipynb、README.md、LICENSE、.gitignore、.env.template。
2.2 方法
- 精読: 全ファイルを 1 行ずつ確認しました。
- ロック解析:
uv.lockを解析しました(144 パッケージ。うち 69 はnotebookグループ専用で、Python バージョンによる分岐が 3 パッケージ)。 - 挙動の再現: サンドボックスにはネットワークがないため、pytest の
caplogと同じ仕組み(root ロガーへのハンドラ追加)を標準ライブラリで再現し、現行のloggers.py/core.pyで検証しました。 - 最新動向の調査: 2026-10-12 時点の一次情報を調べました(付録 B)。GitHub Actions は新旧テンプレートで使う 22 アクションについて、最新リリースとそのコミット SHA(40 桁)を照合しています。
2.3 重要度の定義
| 重要度 | 定義 |
|---|---|
| P0 (Critical) | 誤った成果物の公開、セキュリティ事故、品質ゲートの無効化に直結する。直ちに修正する |
| P1 (High) | 本番運用・保守で高確率に問題化する。テンプレート配布前に修正する |
| P2 (Medium) | 品質・保守性・開発体験を損なう。次の改訂で修正する |
| P3 (Low) | 改善推奨・衛生事項 |
3. 修正が必要な事項の一覧
P0 が 3 件、P1 が 25 件、P2 が 36 件、P3 が 10 件、合計 74 件です。「対応先」は新テンプレート内のファイルです。詳細は第 4 章を参照してください。
A. テストと品質ゲート
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| A-1 | P0 | propagate=False のため caplog がログを捕捉できず、test_core.py の 3 テストが失敗する |
template_python/loggers.py, tests/test_core.py |
logging_config.py, tests/test_logging_config.py(回帰テスト) |
| A-2 | P1 | load_dotenv() がプロセス環境をテストセッション全体に漏らす。CWD に依存し、アサーション文言も誤っている |
tests/test_settings.py |
tests/conftest.py(autouse の隔離 fixture)、tests/test_config.py |
| A-3 | P1 | CLI(scripts/template.py)が無テストかつカバレッジ対象外 |
pyproject.toml, tests/ |
tests/test_cli.py(CliRunner 9 件 + python -m) |
| A-4 | P2 | ログ文字列だけに依存する弱いアサーション、意味の無い parametrize、未使用の session fixture | tests/test_core.py |
純粋関数の値検証 + Hypothesis |
| A-5 | P2 | カバレッジ閾値なし、ブランチカバレッジ無効、CI にレポートが出ない | pyproject.toml, test.yaml |
fail_under = 90, branch = true, Job Summary, artifact |
| A-6 | P2 | pytest 設定の不備(strict 系なし、警告がエラーにならない、常時 --cov、ログの二重大量出力、pythonpath=['.']) |
pyproject.toml, Makefile |
pytest 9 ネイティブ [tool.pytest] + strict = true |
| A-7 | P2 | 型チェッカー 3 種(mypy、ty、pyrefly)の併用。ty は 0.0.x(beta)をゲートに使っている | Makefile, pyproject.toml |
mypy strict に一本化(ADR-0002) |
| A-8 | P2 | Ruff が E, F, I, UP のみで、ロギングの f-string などを見逃す。ignore=["D203"] は無効な設定 |
pyproject.toml |
34 ルール群を明示的に選択 |
| A-9 | P3 | import-linter 契約が scripts → template_python だけで、ライブラリ内部と外部フレームワークへの依存は無制約 |
pyproject.toml |
layers 契約(exhaustive)+ forbidden 契約 |
B. CI 設計
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| B-1 | P1 | push と pull_request で二重起動、concurrency なし、merge_group 非対応 |
test.yaml, docker.yaml |
ci.yaml |
| B-2 | P1 | 必須チェック用の集約ジョブが無い(行列名を変えるとブランチ保護が壊れる) | test.yaml |
ci.yaml の ci-success |
| B-3 | P2 | setup-uv(python-version 指定)と setup-python で Python を二重にセットアップしている |
3 ワークフロー | setup-uv に一本化 |
| B-4 | P2 | 全ゲートを 1 ジョブで直列実行。docs ビルドと ruff の重複実行 | test.yaml, github-pages.yaml |
lint / workflows / test / docs / package / container の並列実行 |
| B-5 | P2 | sdist/wheel が CI で一度もビルド・検証されない | (なし) | package ジョブ(隔離環境でのスモークテスト) |
| B-6 | P2 | EOL の 3.10 を含み、GA の 3.15 を含まない。Windows/macOS とフリースレッドの検証が無い | test.yaml |
3.12〜3.15、Windows/macOS、3.14t(非ブロッキング) |
| B-7 | P2 | ubuntu-latest は 2026-10-19 から Ubuntu 26.04 へ段階移行するため再現性がない |
全ワークフロー | ubuntu-24.04 に固定 |
| B-8 | P2 | uv のバージョンが 6 か所にハードコードされている | devcontainer, workflows, Dockerfile, README | [tool.uv] required-version を唯一の定義にする |
| B-9 | P2 | actionlint の検証が同一リリースの checksums.txt 頼み。ローカルは別途インストールが必要 | test.yaml, Makefile |
actionlint-py を uv.lock でハッシュ固定 |
| B-10 | P3 | github-pages.yaml に timeout が無く、全ワークフローでジョブ単位の権限が無い |
全ワークフロー | 全ジョブに timeout-minutes と permissions |
C. サプライチェーン・セキュリティ
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| C-1 | P0 | uv export --no-hashes → pip install でハッシュ検証なしにインストールしている |
Dockerfile |
uv sync --locked(ハッシュ検証) |
| C-2 | P1 | zizmor が --offline --min-severity high のため、オンライン監査と medium 以下を見逃す |
Makefile |
オンライン監査 + --min-severity=low + .github/zizmor.yml |
| C-3 | P1 | Trivy が非ブロッキング。2026-03 の Trivy 侵害(GHSA-69fq-xp46-6x23)を踏まえた取得経路の固定も無い | Makefile |
SHA 固定の trivy-action + version: v0.75.0 + fixed HIGH/CRITICAL でブロック |
| C-4 | P1 | CodeQL、依存関係レビュー、シークレットスキャン/プッシュ保護、依存脆弱性監査、Scorecard が無い | (なし) | CodeQL default setup、security.yaml、scorecard.yaml、設定スクリプト |
| C-5 | P1 | Artifact Attestations、SBOM、イミュータブルリリースが無い | リリース系 | actions/attest v4、BuildKit provenance/SBOM、イミュータブルリリース |
| C-6 | P1 | 長期 PAT(Docker Hub)と長期デプロイトークン(SWA)をリポジトリシークレットで全ブランチに公開している | docker-release.yaml, azure-static-web-app.yaml |
GHCR は GITHUB_TOKEN、Docker Hub は Environment 限定、Azure は OIDC |
| C-7 | P2 | Dependabot にグループ化が無く、cooldown は uv だけ | dependabot.yaml |
全エコシステムに cooldown 7 日とグループ化 |
| C-8 | P2 | ワークフロー全体に packages: write / contents: write を付与している |
ghcr-release.yaml, github-pages.yaml |
permissions: {} + ジョブ単位の最小権限 |
| C-9 | P2 | contents: write のトークンを persist-credentials 既定(true)のまま checkout に残している |
github-pages.yaml |
全 checkout で persist-credentials: false |
| C-10 | P2 | 原作者の Google Analytics ID がハードコードされ、利用者の閲覧データが第三者へ送られる | mkdocs.yml |
解析設定を削除 |
| C-11 | P2 | 設定の全量を INFO ログに出力し、SecretStr を使っていない |
scripts/template.py |
SecretStr、秘匿表示のテスト、config コマンド |
D. リリース / CD
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| D-1 | P0 | v1.2.3-rc.1 が :1.2.3 と :latest を上書きする |
docker-release.yaml, ghcr-release.yaml |
metadata-action type=pep440 + latest=auto |
| D-2 | P1 | テスト結果を待たずにタグから公開する | 同上 | release.yaml で再利用 CI を needs |
| D-3 | P1 | レジストリごとに別ビルドし、ダイジェストが不一致になる | 同上 | 1 回ビルドし、同一ダイジェストをミラー |
| D-4 | P1 | パッケージ版(0.0.1)とタグ(v0.0.13)が乖離。GIT_TAG / GIT_REVISION は未使用 |
pyproject.toml, Dockerfile |
verify ジョブ(タグ = uv version)、OCI ラベル |
| D-5 | P1 | GitHub Release(ノート・成果物)を作らない | (なし) | gh release create --generate-notes + .github/release.yml |
| D-6 | P2 | QEMU のセットアップなしで arm64 をビルドしている(エミュレーション前提で遅い) | 同上 | ネイティブ amd64/arm64 → ダイジェストのマージ |
| D-7 | P2 | mkdocs gh-deploy --force で gh-pages ブランチへ force push(旧方式、並行制御なし) |
github-pages.yaml |
actions/deploy-pages + github-pages 環境 |
| D-8 | P2 | SWA ワークフローに単一値の matrix と Python の二重セットアップがある | azure-static-web-app.yaml |
docs-azure-swa.yaml(OIDC) |
| D-9 | P3 | docs のビルドが strict でなく、リンク切れを検出しない | Makefile |
zensical build --strict |
E. コンテナ
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| E-1 | P1 | USER が無く root で実行される |
Dockerfile |
UID 10001、venv は root 所有で読み取り専用 |
| E-2 | P1 | COPY . . でコンテキスト全体を同梱し、パッケージとしてインストールしていない |
Dockerfile |
非 editable wheel を venv に入れ、venv のみコピー |
| E-3 | P2 | .dockerignore が JS 向けの流用で、インラインコメントによる無効パターンやファイル名の不一致がある |
.dockerignore |
allowlist 方式 |
| E-4 | P2 | bookworm(2026-07-11 に通常サポート終了)を使い、ベースイメージが曖昧 | Dockerfile, devcontainer |
python:3.14-slim-trixie |
| E-5 | P2 | compose が http.server で /app を 0.0.0.0 に公開し、.env が無いと起動しない |
compose.yml |
compose.yaml(read_only、cap_drop、no-new-privileges、required: false) |
| E-6 | P3 | OCI ラベルが無く、GHCR とリポジトリが紐付かない | Dockerfile |
metadata-action のラベル + LABEL |
| E-7 | P3 | GIT_TAG の sed -e s/v//g がすべての v を削除する |
Makefile |
版は uv version から取得 |
F. Python パッケージとアプリ設計
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| F-1 | P1 | ライブラリがハンドラ追加・propagate=False・レベル設定を行う |
loggers.py |
アプリ側の configure_logging()(冪等、JSON 対応) |
| F-2 | P1 | import 時の副作用。各モジュールが import 時に設定を読んで lru_cache する |
core.py, loggers.py |
設定は composition root(CLI)だけが生成する |
| F-3 | P1 | --verbose が __main__ ロガーにしか効かず、basicConfig で二重出力になる |
scripts/template.py |
root に適用 + テスト |
| F-4 | P1 | load_dotenv(override=True) が実環境変数を .env で上書きする |
scripts/template.py |
pydantic-settings の優先順位(環境変数 > .env) |
| F-5 | P2 | flat layout で CLI がパッケージに含まれず、インストールできない | pyproject.toml |
src layout、[project.scripts]、__main__.py |
| F-6 | P2 | 設定の型が弱い(str のログレベル、接頭辞なしの汎用名)。python-dotenv を直接依存にしている |
settings/project.py |
Literal と正規化、TEMPLATE_PYTHON_ 接頭辞、frozen |
| F-7 | P2 | hello --name が name を使わず、stdout に何も出さない。終了コードの設計が無い |
scripts/template.py |
stdout/stderr を分離、終了コード 2 と 78 |
| F-8 | P2 | ログに f-string を使い、「構造化ログ」と称しているのに実体はテキスト | core.py, docs |
% 形式 + JSON フォーマッタ |
| F-9 | P2 | hatchling がバージョン無制約。メタデータ不足(license、classifiers、urls、py.typed) |
pyproject.toml |
uv_build>=0.13.0,<0.14、PEP 639 |
| F-10 | P2 | requires-python >=3.10(2026-10-01 EOL) |
pyproject.toml |
>=3.12(既定は 3.14) |
| F-11 | P3 | コンテナの CMD が python -m template_python.core(デモ用の __main__) |
Dockerfile |
ENTRYPOINT ["template-python"] |
G. 開発者体験
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| G-1 | P1 | devcontainer が dev- タグ(main から生成され上書き更新される開発ビルド)を使い、bookworm で、uv を毎回 pipx で導入している |
devcontainer.json |
3-3.14-trixie + uv イメージ、prebuild 対応 |
| G-2 | P1 | プロジェクト名や作者名(ks6088ts、template-python)が散在し、初期化手段が無い |
全体 | scripts/init_project.py + initialize.yaml |
| G-3 | P2 | make install-deps-docs(exact sync)が開発ツールを削除し、git フックが壊れる |
Makefile |
docs は uv run --only-group docs |
| G-4 | P2 | pre-commit の ruff と uv.lock の ruff が別管理でドリフトする。uv.lock の検査が無い |
.pre-commit-config.yaml |
local フック(uv run --frozen)+ uv lock --check |
| G-5 | P2 | VS Code の推奨拡張が devcontainer と不一致で、診断も重複する | .vscode/, devcontainer |
統一し、mypy 拡張に一本化 |
| G-6 | P3 | ノートブックに実行出力(ANSI、タイムスタンプ)をコミットし、テスト対象外 | notebooks/ |
削除(必要なら nbstripout) |
H. ドキュメント
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| H-1 | P1 | MkDocs 1.x は保守停止、Material for MkDocs は保守モード、static-i18n は凍結 | mkdocs.yml |
Zensical(ADR-0003) |
| H-2 | P2 | 変更履歴のような文言(「Git hooks and deployment workflows are unchanged…」)が残り、同じ説明が 4 か所に重複している | README, docs | ページ責務を整理し、ADR に分離 |
| H-3 | P2 | 事実と異なる記述(「structured logging」、「Surface failures」原則と非ブロッキングのスキャン) | docs | 実装と一致させる |
| H-4 | P3 | site_url と repo_url のオーナーが不一致。作者の SNS リンクが残っている |
mkdocs.yml |
プレースホルダー化 |
I. GitHub ガバナンス
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| I-1 | P1 | ルールセット、必須チェック、タグ保護、CODEOWNERS が無い(テンプレートは設定を複製しない) | (なし) | .github/rulesets/*.json + scripts/configure_repository.py |
| I-2 | P1 | Actions 設定(既定トークン read、SHA ピン必須、PR 承認の禁止)、イミュータブルリリース、PVR を有効化する手順が無い | (なし) | configure_repository.py |
| I-3 | P2 | SECURITY.md、CONTRIBUTING、行動規範、Issue Forms、PR テンプレートが無い | (なし) | 一式を同梱 |
| I-4 | P3 | LICENSE の著作権者が原作者のまま | LICENSE |
プレースホルダー + 初期化スクリプト |
J. AI 駆動開発(GitHub Copilot)
| ID | 重要度 | 指摘 | 対象 | 対応先 |
|---|---|---|---|---|
| J-1 | P1 | copilot/** を CI 対象にしながら AGENTS.md、指示ファイル、copilot-setup-steps.yml が無い |
.github/ |
一式を同梱 |
| J-2 | P2 | エージェントのガードレール(フック)、専門エージェント、スキル、MCP 設定が無い | .github/ |
hooks(テスト付き)、agents、skills、.vscode/mcp.json |
| J-3 | P3 | Copilot コードレビューの自動依頼が構成されていない | (なし) | rulesets/copilot-code-review.json(任意) |
4. 指摘事項の詳細
各項目は「現状 → 問題 → 修正方針 → 新テンプレートでの対応」の順に記載します。
4.A テストと品質ゲート
A-1 (P0) propagate=False で caplog が機能せず、テストが失敗する
現状
# template_python/loggers.py
logger.setLevel(log_level)
logger.propagate = False # ← 親(root)へ伝播させない
if logger.handlers:
return logger
handler = logging.StreamHandler() # ← ライブラリが自前でハンドラを付ける# tests/test_core.py
with caplog.at_level(logging.INFO, logger="template_python.core"):
hello_world()
assert "Hello World" in caplog.text # ← root に届かないので常に空問題
- pytest の
caplogは root ロガーにハンドラを追加して記録を集めます(pytest 公式ドキュメント「The caplog fixture adds a handler to the root logger」)。at_level(logger=...)はレベルを変えるだけです。非伝播ロガーにも対応する PR(logging: also capture logs from non-propagating loggers pytest-dev/pytest#14375)は 2026-09 時点で未マージであり、ロックされている pytest 9.1.1 には含まれていません。 - 同じ仕組みを標準ライブラリで再現すると、
propagate = False、root 側の捕捉件数 0、"Hello World" in caplog.text → Falseになりました。test_hello_world_logs_messageと parametrize された 2 ケースの計 3 件が失敗します。 - ノートブックの出力(2026-05-10)には root 経由の重複行が残っています。伝播を止める変更が後から入り、テストを壊した可能性が高いと考えられます。CI がこれを検出していないなら、ゲートが実際には実行されていないか、結果が見落とされています。
修正方針
- ライブラリは
logging.getLogger(__name__)を使うだけにし、ハンドラ、伝播、レベルには一切触れません。 - ログの構成はアプリケーションの入口で 1 回だけ、冪等に行います。
- 「ライブラリのログが caplog に届くこと」を回帰テストで固定します。
新テンプレートでの対応
src/template_python/logging_config.py:configure_logging()は自分の名前付きハンドラだけを置き換え、caplog などのハンドラには触れません。- JSON Lines 出力に対応しています。
tests/test_logging_config.py::test_library_records_reach_caplog(回帰テスト)。
A-2 (P1) テストが環境変数を汚染し、CWD に依存する
現状
test_settings.py は load_dotenv(dotenv_path=".env.template") を呼びます。これはプロセスの os.environ を書き換えるので、以降の全テストに PROJECT_NAME などが残ります。さらに、相対パスのため pytest を別ディレクトリから実行すると失敗します。アサーションの文言「Default project name should be 'template-python'」も誤りで、実際の既定値は default-project です。
問題
- テストの順序に依存する、再現しにくい不具合の温床になります。
- 開発者の
.envや環境変数がテスト結果を変えてしまいます(非ハーメチック)。
修正方針・新テンプレート
tests/conftest.pyの autouse fixture で、TEMPLATE_PYTHON_*を削除し、tmp_pathへchdirし、テスト後に自前のハンドラを除去します。- 設定のテストは
monkeypatch.setenvとtmp_path / ".env"で行います。 - 優先順位(環境変数 >
.env)、正規化、不正値、秘匿、不変性を個別に検証します(tests/test_config.py、7 件)。
A-3 (P1) CLI が無テストで、カバレッジ対象外
現状
--cov=template_python だけが計測対象で、scripts/template.py は計測もテストもされていません。そのため F-3(--verbose の不具合)や F-7(出力が無い)を検出できません。
修正方針・新テンプレート
CLI をパッケージ内(cli.py)に移し、typer.testing.CliRunner で E2E テストします。
- stdout/stderr の分離、
--version、--verbose、不正入力時の終了コード 2、不正設定時の 78、--helpが設定エラーの影響を受けないこと、秘匿表示を確認します。 python -m template_pythonをサブプロセスで実行します。
A-4 (P2) 弱いアサーションと無意味な parametrize
hello_world() は値を返さず、5 レベルのログを出すだけです。テストは「Hello World という文字列がどこかにあるか」しか見ておらず、DEBUG/INFO の parametrize も結果を区別しません。未使用の setup_session fixture はデッドコードです。
新テンプレートでは、ドメインを純粋関数 build_greeting() にして入出力を検証します。不変条件(前後空白の除去、長さ制限)は Hypothesis のプロパティテストで確認します。
A-5 (P2) カバレッジ閾値なし・ブランチカバレッジ無効
[tool.coverage.report] は show_missing だけで、閾値もブランチ計測もありません。CI はカバレッジを報告も保存もしません。
新テンプレートの設定は次のとおりです。
branch = true、fail_under = 90、exclude_alsoを設定します。- 基準プラットフォーム(Ubuntu、3.14)でのみ計測し、Markdown 表を Job Summary に出力します。
coverage.xmlとjunit.xmlを artifact として保存します。
A-6 (P2) pytest 設定の不備
| 現状 | 問題 | 新テンプレート |
|---|---|---|
[tool.pytest.ini_options] |
pytest 9 のネイティブ TOML ではない | [tool.pytest](pytest ≥ 9) |
| strict 系オプションなし | マーカーの typo や設定ミスが黙殺される | strict = true(strict_config/markers/parametrization_ids/xfail。pytest はロックで固定) |
filterwarnings 未設定 |
非推奨警告が蓄積する | filterwarnings = ["error"] |
addopts = "--cov=..." |
単体実行やデバッグが常に遅くなる | カバレッジは make cov と CI だけで計測 |
log_cli = true + --capture=no -vv |
ログが二重・大量に出てノイズになる | 既定の捕捉を使い、失敗時だけ表示 |
pythonpath = ['.'] |
インストール状態ではなくソースツリーをテストし、パッケージングの欠陥を隠す | src layout + --import-mode=importlib |
A-7 (P2) 型チェッカー 3 種の併用
現状
make lint は mypy strict、ty、pyrefly をすべて実行します。
問題
- 推論や診断の差異により、同じコードに 3 種の抑制コメント(
# type: ignore、# ty: ignore、# pyrefly: ignore)が必要になります。 - 実行時間と更新コストが 3 倍になります。
- ty は 0.0.x(beta、診断の破壊的変更あり)で、ブロッキングゲートには不適です。
新テンプレート
- mypy 2.x strict + pydantic プラグインを唯一のブロッキングゲートにしました(ADR-0002)。
- エディタも同じ mypy(VS Code の mypy 拡張)を使い、Pylance の型検査はオフにして診断を一元化します。
A-8 (P2) Ruff のルール選択が最小限
現状
select = ["E","F","I","UP"] だけで、実際に以下を見逃しています。
- ロギングの f-string(G004)。
subprocess、assert、秘密情報(S)。- バグの温床(B)と pytest スタイル(PT)。
ignore = ["D203"] は D を選択していないため意味がありません。
新テンプレート
- 34 のルール群(A、ASYNC、B、BLE、C4、D(google)、DTZ、E、EM、F、FURB、G、I、ISC、LOG、N、PERF、PGH、PIE、PL、PT、PTH、RET、RSE、RUF、S、SIM、SLF、T10、T20、TID、TRY、UP、W)を明示的に選択しました。
- Ruff 0.16 で既定ルールが 59 から 413 に、0.17 で既定のターゲットが変わったため、明示選択でアップグレード時の揺れを防ぎます。
A-9 (P3) アーキテクチャ契約が弱い
現状
scripts(__init__.py の無い名前空間)→ template_python の 1 契約だけです。ライブラリ内部の層と外部フレームワークへの依存は無制約です。
新テンプレート
- layers 契約:
cli → (config | logging_config) → domain。exhaustive = trueで新規モジュールの層への分類を強制します。 - forbidden 契約:
domainからtyper、pydantic、pydantic_settingsを禁止します(include_external_packages = true)。
4.B CI 設計
B-1 (P1) 二重起動・並行制御なし・マージキュー非対応
現状
test.yaml と docker.yaml は push(main / feature/** / copilot/**)と pull_request(main)の両方で起動します。
問題
- PR ブランチでは同じコミットに対して CI が 2 回走ります。
concurrencyが無いため、追加 push 時に古い実行がキャンセルされません。merge_groupトリガーが無いので、マージキューを有効にすると必須チェックが永久に Pending になります。
新テンプレート
ci.yaml のトリガーは次のとおりです。
pull_request(全ブランチ宛)push(main)merge_groupworkflow_dispatchworkflow_call(リリースから再利用)
concurrency は PR の場合だけ進行中の実行をキャンセルします。
B-2 (P1) 必須チェックの集約ジョブが無い
行列ジョブ名(test (3.13) など)を必須チェックにすると、行列を変えるたびにブランチ保護が壊れます。新テンプレートは ci-success ジョブが全ジョブの結果を検査します(skipped は許容し、failure / cancelled は失敗)。ルールセットはこの 1 つだけを必須にします。
B-3 (P2) Python の二重セットアップ
setup-uv に python-version を渡したうえで actions/setup-python も実行しています(test / azure-static-web-app / github-pages)。新テンプレートは setup-uv だけを使い、Python は .python-version または行列値から uv が取得します。
B-4 (P2) 直列の巨大ジョブと重複実行
現状
make ci-test は format → mypy → import-linter → ruff → ty → pyrefly → actionlint → zizmor → pytest を 1 ジョブで直列に実行します。docs は test.yaml と github-pages.yaml で 2 回ビルドされ、ruff は hooks ジョブでも再実行されます。
新テンプレート
lint / workflows / test(行列)/ docs / package / container を並列ジョブに分けました。ステップ名で失敗箇所が分かり、Ruff は --output-format=github で PR に注釈を付けます。
B-5 (P2) 配布物を一度もビルドしない
wheel/sdist の破損(パッケージデータの欠落、エントリポイントの誤り)は利用者側で初めて発覚します。新テンプレートは package ジョブで uv build --no-sources を実行し、uv run --isolated --no-project --with dist/*.whl template-python --version でインストール済みの状態をスモークテストします。
B-6 (P2) Python 行列が時代遅れ
現状
3.10〜3.14 を対象にしています。3.10 は 2026-10-01 に EOL で、3.15.0 は 2026-10-09 に GA です。Windows/macOS の検証もありません。
新テンプレート
- Ubuntu で 3.12 / 3.13 / 3.14 / 3.15 をブロッキングで実行します(3.15 は pydantic 2.14 が対応済み)。
- Windows 2025 と macOS 26 で 3.14 を実行します。
- フリースレッドの 3.14t は早期警告用で、非ブロッキングです。
- テスト行列は
--no-default-groups --group testで最小限の依存だけを入れ、新しい Python で開発ツールのホイール欠如に巻き込まれないようにしています。
B-7 (P2) ubuntu-latest の暗黙移行
GitHub は 2026-10-19〜11-19 に ubuntu-latest を 26.04 へ段階移行します。新テンプレートは ubuntu-24.04 / ubuntu-24.04-arm / windows-2025 / macos-26 を明示し、移行は計画的に行います。
B-8 (P2) uv バージョンが 6 か所に散在
devcontainer、ワークフロー 4 本、Dockerfile、README に 0.12.19 が書かれています。新テンプレートは pyproject.toml の [tool.uv] required-version = ">=0.13.0,<0.14" を唯一の定義とし、setup-uv はこれを自動で読みます。Dockerfile と devcontainer の uv イメージタグは Dependabot(docker)の更新対象です。
B-9 (P2) actionlint の取得と検証
現状
gh release download で取得したバイナリを、同じリリースの checksums.txt で照合しています。リリース自体が改ざんされた場合は検出できません。ローカルでは別途インストールが必要で、CI とバージョンがずれます。
新テンプレート
actionlint-py(1.7.12.x)を lint 依存グループに加え、uv.lock のハッシュで固定しました。ローカル(make workflows、pre-commit)と CI で同じバイナリを使います。
B-10 (P3) timeout と権限の粒度
github-pages.yaml にタイムアウトがありません。権限はワークフローレベルだけです。新テンプレートは全ジョブに timeout-minutes と permissions を明示し、ワークフローレベルは permissions: {} にしました。
4.C サプライチェーン・セキュリティ
C-1 (P0) ハッシュ検証を捨てたコンテナビルド
現状
RUN uv export --locked --format requirements-txt --no-dev --no-hashes ... --output-file requirements.txt
...
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt問題
uv.lockが持つ配布物ハッシュを--no-hashesで捨てています。インデックスやミラーの改ざん、依存関係混乱(dependency confusion)を検出できません。--upgradeの意図も不明確です。
新テンプレート
uv 公式 Docker ガイドの方式に従います。
uv sync --locked --no-install-project --no-editableで依存だけの層をキャッシュし、続けてプロジェクトを非 editable でインストールします。uv はロックのハッシュを検証します。UV_COMPILE_BYTECODE=1、UV_LINK_MODE=copy、UV_NO_DEV=1、UV_PYTHON_DOWNLOADS=0を設定します。- BuildKit のキャッシュマウントとバインドマウントを使います。
C-2 (P1) zizmor がオフラインかつ high 以上のみ
現状
zizmor --offline --strict-collection --min-severity high . で実行しています。
問題
- オフラインでは impostor-commit(フォーク由来の偽 SHA)、ref-confusion、known-vulnerable-actions が無効です。
- medium 以下の artipacked(認証情報の残留)、excessive-permissions、cache-poisoning などを全て見逃します。実際に
github-pages.yamlはcontents: writeのトークンを checkout に残しています(C-9)。
新テンプレート
- CI では
GH_TOKENを渡してオンライン監査を有効にし、--format=github --min-severity=lowで実行します。 .github/zizmor.ymlで全uses:にハッシュピンを要求します。- pre-commit でもオフライン版を実行します。
- 全ワークフローをこの基準に合わせて設計しました(
run:内での${{ }}展開なし、リリース系ジョブのキャッシュ無効化など)。
C-3 (P1) Trivy が非ブロッキング
現状
aquasec/trivy:0.74.0 image ... は --exit-code が無いため、常に成功します。README は「review its findings before enabling a blocking severity threshold」と自ら認めており、アーキテクチャ文書の原則 8「Surface failures」と矛盾します。
問題
- 修正版があるのに放置された HIGH/CRITICAL の脆弱性を含むイメージを公開できてしまいます。
- Trivy は 2026-03-19 に、公式リリース v0.69.4、trivy-action の 76 タグ、setup-trivy の全タグが改ざんされるサプライチェーン侵害を受けました(GHSA-69fq-xp46-6x23 / CVE-2026-33634)。2026-03-22 には Docker Hub の 0.69.5 / 0.69.6 も改ざんされています。スキャナ自身の取得経路を固定する設計が必須です。
新テンプレート
aquasecurity/trivy-actionをコミット SHA で固定し(v0.36.0、侵害後のリリース)、スキャナ本体もversion: v0.75.0で明示しました。ignore-unfixed: true、severity: CRITICAL,HIGH、exit-code: "1"で、修正版がある重大脆弱性をブロックします。- hadolint はバイナリを sha256 照合したうえで実行します。
C-4 (P1) 標準的なセキュリティ機能の欠落
| 機能 | 現行 | 新テンプレート |
|---|---|---|
| CodeQL(Python + Actions) | 無し | default setup を設定スクリプトで有効化。高度なセットアップ codeql.yaml は CODEQL_ADVANCED=true のときだけ実行(両者は併用不可) |
| シークレットスキャン + プッシュ保護 | 無し | 設定スクリプトで有効化(private リポジトリは GitHub Secret Protection が必要) |
| 依存関係レビュー | 無し | security.yaml(PR、fail-on-severity: moderate。private は CODE_SECURITY=true) |
| 依存脆弱性監査 | 無し | uv export --locked --all-groups → pip-audit --require-hashes --disable-pip(PR、push、週次スケジュール) |
| Dependabot アラート / セキュリティ更新 | 未設定 | 設定スクリプトで有効化(uv は 2025-12-16 からセキュリティ更新に対応) |
| OpenSSF Scorecard | 無し | scorecard.yaml(public のみ) |
| Private vulnerability reporting | 無し | 設定スクリプトで有効化し、SECURITY.md で案内 |
C-5 (P1) 来歴証明・SBOM・イミュータブルリリースが無い
問題
利用者は「このイメージやホイールが、このリポジトリのこのワークフローでビルドされた」ことを検証できません。リリース後のタグ付け替えや資産の差し替えも可能です。
新テンプレート
- wheel/sdist とイメージに
actions/attestv4 で SLSA build provenance を付与します。attest-build-provenanceは v4 からactions/attestのラッパーになり、attest-sbomは非推奨です。 - イメージには BuildKit の
provenance: mode=maxとsbom: trueも付けます(private リポジトリでは既定がminなので明示)。 - GitHub Release を
gh release createで作成します(draft → 資産アップロード → 公開)。イミュータブルリリース(2025-10-28 GA)と互換で、設定スクリプトで有効化します。 - 検証手順(
gh attestation verify、gh release verify/verify-asset)をSECURITY.mdに記載しました。 - Free/Pro/Team の private リポジトリでは Attestations を使えないため、
ATTESTATIONS変数でガードし、失敗させずに運用できるようにしています。
C-6 (P1) 長期資格情報の広範な露出
現状
DOCKERHUB_TOKEN(PAT)と AZURE_STATIC_WEB_APPS_API_TOKEN(長期デプロイトークン)をリポジトリシークレットとして保持し、Environment による保護(承認、タグ限定)がありません。同一リポジトリの任意ブランチのワークフローから参照できます。
新テンプレート
- GHCR へは
GITHUB_TOKENで push します(長期資格情報なし)。 - Docker Hub は任意のミラーで、
dockerhubEnvironment に限定したシークレットを使い、同一ダイジェストをコピーするだけです。 - Azure SWA は
azure/loginの OIDC で一時的にログインし、実行時にデプロイトークンを取得します。GitHub には保存しません。 - PyPI は Trusted Publishing(OIDC、
pypiEnvironment はv*タグのみ)で、PEP 740 attestations が自動付与されます。
C-7 (P2) Dependabot の設定不足
現状
グループ化が無く、毎週エコシステムごとに個別 PR が大量に作られます。cooldown は uv だけで、Actions、Docker、pre-commit は公開直後の版を即座に提案します。devcontainers は対象外です。
新テンプレート
- uv、github-actions、docker(
/と/.devcontainer)、devcontainers、pre-commit(2026-03-10 対応)の全エコシステムにcooldown.default-days: 7を設定しました。 - グループ化、ラベル、Conventional Commits 風の接頭辞を付けます。
- uv は
groups.dependency-type非対応のため、update-typesでグループ化します。 - zizmor の
dependabot-cooldown監査にも適合します。
C-8 / C-9 (P2) 過剰権限と認証情報の残留
ghcr-release.yaml はワークフロー全体に packages: write を付与し、github-pages.yaml は contents: write で、checkout の persist-credentials も既定(true)のままです。新テンプレートはワークフローレベルを permissions: {} とし、ジョブ単位で最小権限を付与し、全 checkout で persist-credentials: false にしています。リポジトリ設定でも GITHUB_TOKEN の既定を read にします。
C-10 (P2) 第三者のアクセス解析 ID がテンプレートに残っている
mkdocs.yml の extra.analytics.property: G-0ZTKFXVQ5K は原作者の Google Analytics です。テンプレートから生成したすべてのドキュメントサイトの閲覧データが第三者に送られます。Cookie 同意やプライバシーポリシー上も問題です。新テンプレートには解析設定を含めません。
C-11 (P2) 設定全量のログ出力と秘匿化の欠如
logger.info(f"Settings from .env: {get_project_settings().model_dump_json(indent=2)}") は、将来 API キーなどを設定に追加した瞬間に秘密をログへ出力します。新テンプレートは秘密を SecretStr で受け、config コマンドは秘匿済み JSON だけを出力します(********** をテストで保証)。Typer は 0.23 からトレースバックにローカル変数を表示しないのが既定になったため、依存の下限を typer>=0.27 にしてこの挙動を担保しています。
4.D リリース / CD
D-1 (P0) プレリリースが安定版タグと latest を上書きする
現状
// docker-release.yaml / ghcr-release.yaml(Set Versions ステップ)
const tag = context.ref.substring(10) // "v1.2.3-rc.1"
const no_v = tag.replace('v', '') // "1.2.3-rc.1"
const dash_index = no_v.lastIndexOf('-')
const no_dash = (dash_index > -1) ? no_v.substring(0, dash_index) : no_v // "1.2.3"tags: |
${{ secrets.DOCKERHUB_USERNAME }}/template-python:${{steps.set_version.outputs.no-dash}} # :1.2.3
${{ secrets.DOCKERHUB_USERNAME }}/template-python:latest # :latest問題
RC/beta を試験公開しただけで、安定版 1.2.3 と latest が RC の中身に置き換わります。GHCR 側も type=semver,value=v<no-dash> と type=raw,value=latest を使っているので同じです。
新テンプレート
- バージョンを PEP 440(例:
v1.3.0rc1)で統一します。 docker/metadata-actionをtype=pep440,pattern={{version}}/{{major}}.{{minor}}とflavor: latest=autoで使います。プレリリースは{{version}}だけを生成し、latestを付けません。type=ref,event=tag(プレリリースにも latest を付ける)は使いません。- GitHub Release もプレリリースとして作成します。
D-2 (P1) テストを経ずに公開する
タグ push を契機にした公開ワークフローに needs もゲートもありません。アーキテクチャ文書自身が「release workflows are delivery mechanisms, not substitutes for the test workflow」と書きながら、両者がつながっていません。新テンプレートの release.yaml は、verify(タグ = uv version --short)→ ci(ci.yaml を workflow_call で再利用)の成功後にだけビルドと公開を行います。
D-3 (P1) レジストリごとに別ビルドしている
問題
Docker Hub 向けと GHCR 向けを別ワークフローでビルドしています。タイムスタンプやベースイメージの更新により、同じ 1.2.3 でもダイジェストが異なるイメージが 2 つ存在することになります。来歴の検証やインシデント時の追跡ができません。
新テンプレート
- amd64/arm64 をネイティブランナーでビルドし、ダイジェストだけで push します。
docker buildx imagetools createでマルチアーキのインデックスとタグを作成します。- インデックスのダイジェストに attestation を付与します。
- Docker Hub は同じダイジェストをコピーするだけです(任意)。
D-4 (P1) バージョンの乖離と未使用のビルド引数
pyproject.toml は version = "0.0.1" のままですが、Git タグは v0.0.13 です。Dockerfile は ARG GIT_REVISION / GIT_TAG を宣言しているのに一切使っていません(ラベルにも環境変数にもならない)。新テンプレートは uv version --bump で版を管理し、タグとの一致をリリース時に強制します。OCI ラベル(source、revision、version、created)は metadata-action で付与します。
D-5 (P1) GitHub Release とリリースノートが無い
コンテナを push するだけで、変更点・成果物・検証手段が利用者に提供されません。新テンプレートは gh release create <tag> dist/* --verify-tag --generate-notes を実行し、イメージのダイジェストをノートに追記します。.github/release.yml のカテゴリ(Breaking / Features / Bug fixes / Security / Docs / Dependencies)で自動生成ノートを整理し、設定スクリプトがラベルを作成します。
D-6 (P2) エミュレーション前提のマルチアーキテクチャ
platforms: linux/amd64,linux/arm64 を指定していますが、setup-qemu-action がありません。GitHub ホストランナーの arm64 は 2026-01-29 から private リポジトリでも標準ランナーとして利用でき、エミュレーションより高速です。新テンプレートは ubuntu-24.04-arm でネイティブにビルドします。
D-7 (P2) 旧方式の Pages デプロイ
mkdocs gh-deploy --force は gh-pages ブランチへ force push する旧方式で、contents: write が必要です。並行制御も環境保護もありません。新テンプレートは actions/configure-pages → upload-pages-artifact → deploy-pages と github-pages 環境を使い、concurrency: pages を設定しています。Pages が有効なとき(has_pages)だけ実行するので、新規リポジトリで赤くなりません。
D-8 / D-9 (P2/P3) SWA ワークフローの不備と非 strict ビルド
単一値の matrix、Python の二重セットアップ、長期トークン(C-6)、strict でない docs ビルドがあります。新テンプレートは任意実行の docs-azure-swa.yaml(OIDC)と zensical build --strict に置き換えました。
4.E コンテナ
E-1 (P1) root 実行
USER 命令が無く、コンテナは root で動作します。新テンプレートでは次のようにしました。
- 数値 UID/GID 10001 の専用ユーザーで実行します(hadolint DL3066 にも適合)。
- venv は root 所有で、アプリから書き換えられません。
- compose では
read_only、cap_drop: [ALL]、no-new-privilegesを既定にしています。
E-2 (P1) コンテキスト全体の同梱と非インストール実行
COPY . . で docs、notebooks、Makefile、scripts などを同梱し、ソースツリーを作業ディレクトリから直接 import して実行しています。新テンプレートは builder ステージでプロジェクトを非 editable の wheel として venv にインストールし、ランタイムには /app/.venv だけをコピーします(ソースもツールも入りません)。
E-3 (P2) 流用された .dockerignore
node_modules、bower_components、*.test.jsなど JavaScript 向けのパターンを含みます。.DS_Store # macOS-specificはインラインコメントが使えないため無効なパターンです。docker-compose.ymlを除外していますが、実ファイルはcompose.ymlです。
新テンプレートは * で全除外し、必要なもの(pyproject.toml、uv.lock、README.md、LICENSE、src)だけを許可する方式にしました。Dockerfile 先頭の # check=error=true により、CopyIgnoredFile などの BuildKit ビルドチェック違反はビルドエラーになります。
E-4 (P2) 旧ベースイメージ
Debian 12 bookworm は 2026-07-11 に通常サポートを終え、LTS のみになっています。新テンプレートは python:3.14-slim-trixie(Debian 13)を使います。python:3.15-slim-trixie は 2026-10-12 時点で RC タグしか公開されていないため、コンテナの既定は 3.14 にしました。
ダイジェストの固定は推奨ですが、本成果物の作成環境では公開ダイジェストを検証できなかったため、タグで固定し Dependabot(docker)で更新する構成にしています。導入時に docker buildx imagetools inspect でダイジェストを付与する手順を 6 章に記載しました。
E-5 (P2) 危険な compose の例
command: ["python", "-m", "http.server", "8000"] は、/app(ソースコード)を 0.0.0.0:8000 で配信します。env_file: .env は必須扱いなので、.env の無い新規クローンでは起動に失敗します。container_name を固定しているためスケールもできません。新テンプレートの compose.yaml は CLI を実行するだけの最小例で、env_file は required: false です。
E-6 / E-7 (P3) OCI ラベルの欠如と GIT_TAG のバグ
org.opencontainers.image.source が無いと、GHCR のパッケージとリポジトリが自動で紐付きません。Makefile の sed -e s/v//g は v1.0.0-dev を 1.0.0-de に壊します。いずれも新テンプレートで解消しました。
4.F Python パッケージとアプリ設計
F-1 (P1) ライブラリがログ構成を所有している
get_logger() は呼び出しのたびにレベルを上書きし、StreamHandler を追加し、伝播を止めます。ライブラリとして組み込まれた場合、アプリケーション側の logging.config.dictConfig やログ基盤への転送(OpenTelemetry など)が効かず、出力の重複や欠落も起きます。Python 公式の Logging HOWTO が推奨するとおり、ライブラリはハンドラを構成しないことが原則です。
新テンプレートでは次のように分担します。
- ライブラリ:
logging.getLogger(__name__)だけを使います。 - アプリ:
cli.pyからconfigure_logging(level, json_format=...)を 1 回呼びます。- テキストまたは JSON Lines で、出力先は stderr です。
extra=のフィールドと例外も JSON 化します。- 何度呼んでも安全です。
F-2 (P1) import 時の副作用
各モジュールが import 時に get_logger(__name__) を通じて get_project_settings() を呼び、lru_cache に保存します。設定は最初に import された時点の環境で固定されます。後から行う load_dotenv() や環境変数の変更は反映されず、テストの実行順にも依存します。
新テンプレートでは、Settings() は CLI のコマンド実行時(_runtime())にだけ生成されます。--help は不正な設定の影響を受けません。
F-3 (P1) --verbose が機能しない
コールバックは logging.basicConfig(level=DEBUG) と、__main__ ロガーのレベル変更しか行いません。template_python.core のロガーは import 時に INFO に固定されているため、ライブラリの DEBUG ログは出ません。さらに basicConfig が root にハンドラを追加するため、出力が二重になる状態も生じます(ノートブックの出力で両方を確認できます)。
新テンプレートでは、--verbose が root を DEBUG にします。test_verbose_flag_enables_debug_logs_on_stderr で保証しています。
F-4 (P1) .env が実環境変数を上書きする
load_dotenv(override=True) は、コンテナや Kubernetes の Secret などで実際に設定された環境変数を .env の値で上書きします。12-factor の優先順位が逆転し、作業ディレクトリに残った .env が本番設定を乗っ取る事故につながります。そもそも pydantic-settings が .env を読むので、python-dotenv の直接利用は不要です。
新テンプレートでは pydantic-settings の既定(環境変数 > .env)だけを使い、テスト(test_environment_variables_override_dotenv)で保証しています。
F-5 (P2) CLI を配布・インストールできない
flat layout で scripts/ はパッケージに含まれず、python scripts/template.py で起動するしかありません。新テンプレートは src layout にし、[project.scripts] template-python = "template_python.cli:app"、__main__.py(python -m template_python)、py.typed を備えます。
F-6 (P2) 弱い設定モデル
現状
project_log_level: strは任意の文字列を受け入れ、不正値は logging の実行時例外になります。- 接頭辞が無く、
PROJECT_NAMEのような汎用名は他ツールと衝突しやすいです。 - 秘密情報の型(
SecretStr)がありません。 python-dotenvを直接依存に持っています。
新テンプレート
Literal型(LOG_LEVEL / LOG_FORMAT / ENVIRONMENT)に大小文字の正規化を組み合わせました。TEMPLATE_PYTHON_接頭辞を付けます(初期化スクリプトで新名称に置換されます)。frozen=True、SecretStr、min_lengthを設定しました。
F-7 (P2) 出力と終了コードの設計
hello --name は name を使わず、stdout に何も出しません(ログだけ)。そのため、シェルスクリプトから結果を受け取れず、テストもできません。
新テンプレートでは次のように整理しました。
- 結果は stdout(
typer.echo)、診断は stderr(ログ)に出します。 - 入力エラーは
typer.BadParameter(終了コード 2)、設定エラーは 78(sysexits の EX_CONFIG)にします。 - ドメインの例外を CLI 層で変換します。
F-8〜F-11 (P2/P3) その他
- F-8: f-string のログは、レベルで捨てられる場合でも文字列を生成します。構造化もできません。新テンプレートは
%形式の引数と JSON フォーマッタを使います。 - F-9:
build-system.requires = ["hatchling"]は無制約で、ビルドの再現性がありません。新テンプレートはuv_build>=0.13.0,<0.14と PEP 639 のlicense = "MIT"/license-filesを使い、classifiers と urls を追加しました。 - F-10:
requires-python >=3.10は EOL の版を含みます。新テンプレートは>=3.12で、PEP 695 構文やtyping.overrideを使えます。既定は 3.14 です。 - F-11: Docker の
CMD ["python", "-m", "template_python.core"]はデモ用の__main__ブロックです。新テンプレートはENTRYPOINT ["template-python"]とCMD ["--help"]にしました。
4.G 開発者体験
G-1 (P1) devcontainer の dev- タグ
mcr.microsoft.com/devcontainers/python:dev-3.13-bookworm の dev- は、devcontainers/images の公式説明では main ブランチから生成される実験的な開発イメージで、インプレース更新されます。チームメンバーごとに環境が変わる恐れがあります。uv も毎回 pipx install しています。
新テンプレートの構成は次のとおりです。
.devcontainer/Dockerfile:mcr.microsoft.com/devcontainers/python:3-3.14-trixieに、CI・本番と同じghcr.io/astral-sh/uv:0.13.0から uv をコピーします。- features:
github-cliとdocker-in-docker(コンテナ関連の make ターゲット用)を入れます。 hostRequirementsを指定します。updateContentCommandで依存を入れます(Codespaces の prebuild 対象)。postCreateCommandで git フックを入れます。
G-2 (P1) テンプレート固有名の散在と初期化手段の欠如
ks6088ts(Makefile の DOCKER_REPO_NAME、mkdocs、README のバッジ、LICENSE)と template-python / template_python が各所に埋め込まれており、置換手順もツールもありません。
新テンプレートでは 2 つの手段を用意しました。
scripts/init_project.py(標準ライブラリのみ、PEP 723 メタデータ付き)が、配布名、パッケージ名、環境変数の接頭辞、オーナー、説明を一括置換し、パッケージディレクトリを改名し、uv.lockを削除します。名前の検証(キーワードや標準ライブラリとの衝突)とドライランも備え、テストがあります。initialize.yamlが、初回 push 時のuv.lock生成と、任意の改名(workflow_dispatchの入力)を GitHub 上で自動化します。
G-3 (P2) docs 用の同期が開発環境を壊す
make install-deps-docs は uv sync --locked --no-dev --group docs です。uv sync は exact モードのため、dev グループ(prek を含む)を venv から削除します。その結果、インストール済みの git フックが実行ファイルを見失い、コミットが失敗します。新テンプレートは docs を uv run --only-group docs(inexact)で実行し、CI では専用ジョブに分けています。
G-4 (P2) フックと CI のバージョンのドリフト
ruff-pre-commit の rev: v0.16.9 と uv.lock の ruff は別々に更新されます。uv.lock の整合チェックはなく、exclude: "generated/.*|artifacts/.*" は存在しないディレクトリを指しています。
新テンプレートでは次のようにしました。
- 汎用フック(pre-commit-hooks。prek がネイティブ実行)はそのまま使います。
- ruff、actionlint、zizmor は
language: system+uv run --frozenで uv.lock の版を使います。 uv lock --checkフックを追加しました。
G-5 (P2) エディタ設定の不一致
.vscode/extensions.json は pyrefly を、devcontainer は ruff と Copilot Chat を推奨しており、一致していません。Pylance と pyrefly の併用で診断も重複します。新テンプレートは両者を統一し(Ruff、mypy、Python、Copilot Chat、GitHub Actions、TOML)、保存時の整形と import 整理を設定しました。
G-6 (P3) ノートブックの実行結果をコミットしている
ANSI エスケープ、実行日時、相対パス(../scripts/template.py)に依存した出力がコミットされており、テストもされていません。新テンプレートでは削除しました。必要な場合は nbstripout 系のフックと一緒に追加してください。
4.H ドキュメント
H-1 (P1) ドキュメント基盤の保守終了
2026-10 時点の状況
| 項目 | 状況 |
|---|---|
| MkDocs 1.x | 18 か月以上リリースがなく、外部コントリビューションも停止 |
| MkDocs 2.0 | プレリリース段階。プラグイン機構が無く、設定は TOML で、移行パスも無い |
| Material for MkDocs | 保守モード。致命的な不具合とセキュリティの修正のみで、2027-05-05 まで |
| mkdocs-static-i18n | 凍結 |
新テンプレート
- Material チームの後継である Zensical を
zensical.tomlで採用しました(ADR-0003)。mkdocs.yml互換で、--strictを備えます。- 0.0.69 は alpha です。2026-11-05 から 0.1.0 系が安定版の位置付けになる予定で、バージョンは
uv.lockで固定されます。
- Zensical はまだ i18n に対応していないため、英語(
docs/)と日本語(docs/ja/)を 1 サイトの別ナビゲーションとして公開します。 - アーキテクチャ判断は ADR(
docs/adr/)として記録します。
H-2〜H-4 (P2/P3)
現状の問題
- README には「Git hooks and deployment workflows are unchanged, and this does not add a pre-deployment gate.」のような PR 説明文の残骸があります。
- import-linter の説明が README、
docs/index、architecture(英日)の計 4 か所に重複しています。 - 「structured logging」と書かれていますが、実装はテキストです。
- 原則「Surface failures」に反してスキャンが非ブロッキングです。
site_url(ks6088ts-labs)とrepo_url(ks6088ts)のオーナーが不一致です。
新テンプレート
ページの責務を分けました(Getting started / Development / Architecture / CI/CD / Security / Releasing / AI / Repository settings)。記述は実装と一致させ、URL はプレースホルダー(your-github-org)にして初期化スクリプトで置換します。
4.I GitHub ガバナンス
I-1 (P1) ルールセット・必須チェック・タグ保護が無い
GitHub のテンプレートリポジトリはファイルしか複製しないため、ブランチ保護などの設定はテンプレートに含められません。現行テンプレートには設定を再現する手段がなく、ゲートを迂回して main へ直接 push したり、任意のユーザーがリリースタグを作成したりできます。
新テンプレートは次の 3 つのルールセット JSON(UI からのインポートにも対応)を同梱し、scripts/configure_repository.py --apply で作成または更新します。
| ルールセット | 内容 |
|---|---|
default-branch.json |
PR 必須(承認 1、CODEOWNERS レビュー、最終 push 後の承認、スレッドの解決、stale レビューの却下)、ci-success 必須(strict)、線形履歴、force push・削除の禁止、squash のみ |
release-tags.json |
refs/tags/v* の作成・更新・削除を admin のみに制限 |
copilot-code-review.json(任意) |
Copilot コードレビューを自動で依頼 |
I-2 (P1) リポジトリ設定のコード化
configure_repository.py は既定でドライランです。各手順は独立しており、プランや可視性の制約で失敗した手順は警告として扱います。テスト付きで、主に次を設定します。
- Actions の既定トークンを read にし、Actions による PR 承認を禁止し、SHA ピン必須ポリシー(
sha_pinning_required、2025-08 導入)を有効にします。 - squash のみでマージし、auto-merge を許可し、マージ後にブランチを削除します。
- Dependabot アラートとセキュリティ更新、シークレットスキャンとプッシュ保護、PVR、CodeQL default setup(extended)を有効にします。
- イミュータブルリリースを有効にします。
- Pages(Actions ソース)を有効にします。
pypiEnvironment を作成し、v*タグからのみデプロイできるようにします。- リリースノート用のラベルを作成します。
I-3 / I-4 (P2/P3) コミュニティ健全性ファイル
新テンプレートには次を同梱しました: SECURITY.md(非公開報告と検証手順)、CONTRIBUTING.md、CODE_OF_CONDUCT.md(Contributor Covenant 2.1 への参照)、Issue Forms(バグ報告と機能要望、ブランク Issue の無効化、セキュリティ報告への誘導)、PR テンプレート、CODEOWNERS。LICENSE はプレースホルダー化し、初期化スクリプトで置換します。
4.J AI 駆動開発(GitHub Copilot)
J-1 (P1) Copilot 用の構成が無い
test.yaml は copilot/** ブランチを CI 対象にしており、Copilot cloud agent(旧 coding agent。2026-04 に名称変更)の利用を想定しています。にもかかわらず、エージェント向けの指示も実行環境の定義もありません。エージェントは毎回、uv の導入方法や品質ゲートを推測することになり、規約違反の PR や CI の失敗を繰り返します。
新テンプレート(2026-10 時点の仕様に準拠)の構成は次のとおりです。
| ファイル | 役割 |
|---|---|
AGENTS.md |
エージェント共通の操作ガイド(cloud agent、コードレビュー、CLI、VS Code が読む)。プロジェクトマップ、コマンド、規約、禁止事項を記載 |
.github/copilot-instructions.md |
リポジトリ全体の指示(レビュー観点の優先順位) |
.github/instructions/*.instructions.md |
パス別の指示(Python、テスト、Actions、ドキュメント)。applyTo はカンマ区切りの文字列 |
.github/workflows/copilot-setup-steps.yml |
cloud agent の実行環境。ジョブ名は copilot-setup-steps、uv sync --locked --all-groups |
.vscode/mcp.json |
GitHub リモート MCP サーバー(VS Code) |
エージェント用のシークレットは「Settings → Secrets and variables → Agents」で管理します(2026-05-08 に copilot 環境から移行)。
J-2 (P2) ガードレールと再利用可能な手順
| 種別 | 新テンプレート |
|---|---|
| フック(CLI と cloud agent) | .github/hooks/policy.json + guard_tool_use.py。preToolUse で force push、--no-verify、curl | sh、rm -rf / 系、uv.lock の直接編集を拒否する。クラッシュすると全ツールが拒否される仕様のため、例外を握りつぶして常に終了コード 0 で返す。テスト 13 件 |
| カスタムエージェント | test-writer(テスト専任)、security-reviewer(読み取り専用ツールのみ) |
| スキル | run-quality-gates、code-review(コードレビューが参照)、add-cli-command、cut-release、update-dependencies |
プロンプトファイル(.prompt.md)は VS Code で非推奨になったため、スキルで実装しています。
J-3 (P3) コードレビューの自動依頼
copilot_code_review ルール(review_on_push)を任意のルールセットとして同梱しました。設定スクリプトの --copilot-review オプションで適用できます。
GitHub Agentic Workflows(gh-aw、2026-06 からパブリックプレビュー)は、コンパイル済みの .lock.yml のコミットが必須です。そのため本テンプレートには同梱せず、導入手順(gh aw add githubnext/agentics/ci-doctor)だけをドキュメントに記載しています。
Activity
ks6088ts commentedon Oct 13, 2026
5. 新テンプレートの設計
5.1 設計原則
pyproject.tomlとuv.lock、uv の版はrequired-version、ローカルと CI のコマンドはMakefileに集約し、版を各所に重複させません。permissions: {}、ジョブ単位の権限、OIDC(Azure、PyPI)、GITHUB_TOKEN(GHCR)を使い、長期シークレットは原則持ちません。CODE_SECURITY、ATTESTATIONS、CODEQL_ADVANCED、PYPI_PUBLISH、DOCKERHUB_IMAGE、AZURE_*)や Pages の有無でガードし、新規リポジトリを赤くしません。5.2 アプリケーション構造
flowchart LR subgraph interface["インターフェース層"] CLI["cli.py<br/>Typer / 構成ルート<br/>終了コード 0・2・78"] end subgraph adapters["アダプタ層(相互依存禁止)"] CFG["config.py<br/>Settings(pydantic-settings)<br/>TEMPLATE_PYTHON_* / .env"] LOG["logging_config.py<br/>configure_logging()<br/>text / JSON Lines → stderr"] end subgraph domain["ドメイン層(フレームワーク非依存)"] DOM["domain/greeting.py<br/>純粋関数・固有例外"] end CLI --> CFG CLI --> LOG CLI --> DOMこの依存方向は import-linter の 2 契約で CI が強制します。layers 契約(
exhaustive = true)と、domainからtyper、pydantic、pydantic_settingsへの依存を禁じる forbidden 契約です。5.3 CI/CD フロー
flowchart TB PR["pull_request / push main / merge_group"] --> CI subgraph CI["ci.yaml(必須チェック: ci-success)"] L["lint<br/>ruff・mypy・import-linter・deptry・prek"] W["workflows<br/>actionlint・zizmor(オンライン)"] T["test 行列<br/>3.12〜3.15 / Win / mac / 3.14t"] D["docs<br/>zensical --strict"] P["package<br/>uv build + スモークテスト"] C["container<br/>hadolint・ビルドチェック・Trivy"] L & W & T & D & P & C --> S["ci-success"] end PR --> SEC["security.yaml<br/>pip-audit・依存関係レビュー"] TAG["git tag vX.Y.Z"] --> V["verify<br/>tag = uv version"] V --> RCI["ci(workflow_call)"] RCI --> B["build<br/>sdist/wheel + attest"] RCI --> IMG["image ×2<br/>amd64 / arm64 ネイティブ<br/>provenance max + SBOM"] IMG --> M["image-manifest<br/>pep440 タグ + attest"] B & M --> GR["GitHub Release<br/>draft → 資産 → 公開(イミュータブル)"] B -.->|PYPI_PUBLISH| PYPI["PyPI(Trusted Publishing)"] M -.->|DOCKERHUB_IMAGE| DH["Docker Hub(同一ダイジェスト)"]5.4 ワークフロー一覧
ci.yamlci-success)security.yamlscorecard.yamlcodeql.yamlCODEQL_ADVANCED=trueのときだけ)release.yamlv*docs.yamldocs-azure-swa.yamlinitialize.yamluv.lock生成と改名(任意) → CI を再実行copilot-setup-steps.yml5.5 ツールチェーン(2026-10-12 時点)
required-version)、uv_build>=0.13.0,<0.14|は独立した兄弟)+ forbidden[tool.pytest]、strict)、Hypothesis、coverage(branch、90%).pre-commit-config.yaml互換)uv auditはまだプレビューのため不採用python:3.14-slim-trixie、uv 0.13.0、hadolint 2.15.1、Trivy 0.75.05.6 旧ファイルから新ファイルへの対応表
.github/workflows/test.yamlci.yamlci-success、merge_group、行列の刷新、package/docs/container を統合.github/workflows/docker.yamlci.yamlの container ジョブdocker-release.yaml+ghcr-release.yamlrelease.yamlgithub-pages.yamldocs.yamlhas_pagesガードazure-static-web-app.yamldocs-azure-swa.yamlsecurity.yaml、scorecard.yaml、codeql.yaml、initialize.yaml、copilot-setup-steps.yml.github/dependabot.yaml.github/dependabot.yml.pre-commit-config.yamluv lock --check、actionlint、zizmor.devcontainer/devcontainer.json.devcontainer/Dockerfile3-3.14-trixie、uv イメージ、features、prebuildDockerfile、.dockerignore、compose.ymlcompose.yaml)Makefilesetup/check/ci/audit/workflows/docs/bump-*などpyproject.tomluv.locktemplate_python/src/template_python/py.typed、__main__scripts/template.pysrc/template_python/cli.pytests/*tests/*(7 モジュール)mkdocs.yml、docs/zensical.toml、docs/(英)、docs/ja/(日)、docs/adr/notebooks/templates.ipynb.env.template.env.examplescripts/init_project.py、scripts/configure_repository.py.github/rulesets/*.json、release.yml、zizmor.yml、CODEOWNERS、Issue Forms、PR テンプレートAGENTS.md、.github/copilot-instructions.md、instructions/、agents/、skills/、hooks/、.vscode/mcp.jsonSECURITY.md、CONTRIBUTING.md、CODE_OF_CONDUCT.md、README.ja.md6. 導入手順
6.1 テンプレートリポジトリとして公開する(初回のみ)
repos/template-python/の内容を新しい GitHub リポジトリへ push し、Settings → General で Template repository を有効にします。uv.lockを生成してコミットします。本成果物の作成環境はインターネットに接続できず、正しいロックを生成できなかったため、ロックファイルは同梱していません。次のどちらかで生成してください。make setupを実行し、uv.lockをコミットします。initialize.yamlがuv.lockを生成・コミットし、CI を再実行します(最初の CI は「uv.lock is missing」で明示的に失敗し、数分後に緑になります)。make check、make docs、make workflows、make docker-build docker-scanをローカルで実行し、問題が無いことを確認します(7 章の未実施項目を解消する作業です)。6.2 テンプレートから新規プロジェクトを作る
GitHub 上だけで改名する場合も、手順 4(ルールセットの適用)より前に実行してください。Initialize workflow は
GITHUB_TOKENで main に直接 push するため、ルールセット適用後は拒否されます。またGITHUB_TOKENはワークフローファイルを変更する push ができないため、ワークフローにはプロジェクト名を一切書かない設計にし、テストで担保しています。6.3 プランや可視性に応じた設定
CODE_SECURITY=trueATTESTATIONS=truemerge_queueを追加(ci.yamlはmerge_group対応済み)6.4 任意機能の有効化
release.yaml、Environmentpypi)を登録し、変数PYPI_PUBLISH=trueを設定dockerhubに変数DOCKERHUB_USERNAMEとシークレットDOCKERHUB_TOKENを設定し、変数DOCKERHUB_IMAGE=docker.io/<user>/<image>を設定azure-static-web-apps)を作成し、AZURE_CLIENT_ID、AZURE_TENANT_ID、AZURE_SUBSCRIPTION_ID、AZURE_RESOURCE_GROUP、AZURE_STATIC_WEB_APP_NAMEを設定CODEQL_ADVANCED=trueを設定切り替え用の変数(
PYPI_PUBLISH、DOCKERHUB_IMAGE、AZURE_STATIC_WEB_APP_NAME、CODE_SECURITY、ATTESTATIONS、CODEQL_ADVANCED)は、リポジトリ(または組織)の変数として設定してください。ジョブのif:は Environment にだけ設定した変数を参照できません。シークレットと Azure の各 ID は Environment に置けます。6.5 リリース
6.6 継続的な運用の推奨
.githubリポジトリなどに置いた版付きの再利用ワークフローへ切り出します。python:3.15-slim-trixieの公開(コンテナの既定を 3.15 に上げるかを判断)。ubuntu-26.04への移行。gh actions-lock、現在はテクニカルプレビュー)の GA。uv auditの正式化(pip-audit から置き換えるか判断)。gh aw add githubnext/agentics/ci-doctor)を試行し、.lock.ymlと合わせてコミットします。7. 検証結果と残る制約
本成果物を作成した環境はインターネットに接続できません。そのため、パッケージの取得が必要な検証(
uv lock、ruff や mypy の実行、Docker ビルドなど)はできていません。ここでは、実施した検証と実施できなかった検証を分けて示します。後者は、テンプレートを GitHub に置いた後の初回 CI とmake checkで確認してください。7.1 実施した検証
.pyのコンパイル、YAML / TOML / JSON のパース、ワークフローのrun:ブロックをbash -nで確認permissions: {}とジョブ単位の最小権限。全ジョブのtimeout-minutes。checkout のpersist-credentials: false。run:内に${{ }}を直接書かない。ci-successが全ジョブをneedsに含むことprint()、ロギング呼び出しでの f-string、モジュール docstring、120 文字超の行zensical.tomlの nav が指す全ページの存在、Markdown の相対リンク切れ、docs/の外を指すリンク(strict ビルドで失敗する)init_project.py、configure_repository.py、Copilot フック、ワークフローに置換対象の名前が無いこと)を、pytest 互換の小さなランナーで-W errorを付けて実行init_project.py acme-billing --owner contosoを実行src、scripts、.github/hooksを走査ghをsubprocessで呼ぶ箇所で、意図どおり(コードに理由を明記)caplogと同じ仕組みを標準ライブラリで再現test_core.pyの 3 件が失敗することを確認(A-01)補足:
7.2 実施できなかった検証(初回 CI で確認)
uv.lockの生成make setupを実行するか、Initialize workflow に任せる(6.1)make check(CI のlintジョブ)make workflows(CI のworkflowsジョブ)make test(CI のtestジョブ)testマトリクスmake docker-build docker-scan、CI のcontainerジョブ、初回リリースmake docs(CI のdocsジョブ)configure_repository.pyをドライランで確認してから--apply7.3 初回に起きうる問題と対処
uv run ruff check --fixで直し、残りは個別に修正するかper-file-ignoresに理由付きで追加。版はuv.lockで固定され、更新は Dependabot の PR の CI で検出されるcache-poisoningなどの判定が版によって変わる.github/zizmor.ymlに理由付きで除外を追加macos-26などが actionlint の既知ラベルにない.github/actionlint.yamlに登録済み。新しいラベルを使うときは追記containerジョブが失敗する.trivyignoreに記録zensical>=0.0.69の下限のみで、uv.lockで固定される。更新時はmake docsで確認。問題があれば Material for MkDocs(2027-05 まで保守)に戻せるactor_id: 5は公式ドキュメントに明記がないbypass_actorsを外して再適用(スクリプトは警告を出して続行)pyproject.tomlのpluginsから外しても型チェックは動くubuntu-latestの 26.04 移行ubuntu-24.04を明示しているので影響しない。26.04 への切り替えは計画的に行う.python-version、イメージ)は 3.14 のまま7.4 本番利用の前に決めておくこと
LICENSEは MIT、著作権者はプレースホルダー。init_project.pyで置換)CODEOWNERSのチーム名と、必須レビュー人数(ルールセット)付録 A. 固定した GitHub Actions(2026-10-12 時点の最新安定版)
すべてコミット SHA(40 桁)で固定し、行末に版のコメントを付けています。現行テンプレートが使っていた 10 アクションの SHA(checkout v7.0.1、setup-python v7.0.0、cache v6.1.0、github-script v9.0.0、Docker 系 4 種、static-web-apps-deploy v1)も、各リリースページの SHA と一致することを確認しました。
setup-uvだけは v10.2.0 から v10.3.0(uv 0.13.0 対応)へ更新しています。3d3c42e5aac5ba805825da76410c181273ba90b11c37ad07a6a961277cf70c0d37d6f313000f5884cf430e030ddbb5b0abf93d22962f4752f3646cd99000827ccba6bdab643e8b6fd33ac0654aef83331e69f48acb82d1966a394da916b4c1698aa569d645bfe0192ca1faeb007ade9deae92b16b8254a0dfc324d3547104276b827a68afc52ff2a11cc49c9368f82528645a54fb793d4d04e342629a3f51346a1d282b36b6f3519aa1f3fc636f609c47dddb29424c54180a607b1449ed407dd24f251e4e9147c8d2d1146689b8cda280b9bc96326124645441f03bcf87e5991a6d7451dcb8d9637bfbc97413f497069dbcb813823bdd20940b903addbd779551569679fdc802804100637a589fabce1cb79ff13a1411302c3c9e263c25d99ce0380d002d59b67737d91b0dced142fd0673e97e23eac54620cfb913e5ce36c25dc37677b2e1c63e2034f94d8a5b11f265b73ba33a641126d1b8aa4d1fa005f4f92df94a3a4c4c9061a947af9992250f3bc2e68ad0754c0b0c11566c9補足:
Azure/static-web-apps-deployには同名のv1ブランチ(HEAD は4d27395…)もあります。SHA で固定すると曖昧さはなくなります。trivy-actionの完全な SHA は第三者ページ 1 件でしか確認できていません(短縮 SHAed142fdは公式リリースページと一致)。CI の zizmor オンライン監査(impostor-commit)が誤りを検出する構成にしています。付録 B. 参照した一次情報(2026-10-12 確認)
GitHub プラットフォーム
gh release create(draft → アップロード → 公開): https://cli.github.com/manual/gh_release_createactions/attestv4): https://github.com/actions/attest / https://docs.github.com/en/actions/concepts/security/artifact-attestationsubuntu-latestの移行: https://github.blog/changelog/2026-09-17-ubuntu-26-generally-available-and-latest-migration/merge_group): https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queuecache-mode: https://github.blog/changelog/2026-09-10-control-github-actions-cache-access-with-cache-mode/GitHub Copilot
Python エコシステム
コンテナ・ドキュメント
dev-タグの意味): https://github.com/devcontainers/images/tree/main/src/python