chore: Setup CI workflows for Backend and Frontend#6
Conversation
There was a problem hiding this comment.
Pull request overview
FastAPI(Backend)/ Next.js(Frontend)のモノレポ構成に合わせて、Lint・Build・Test・セキュリティスキャンを自動実行するGitHub Actions CIを整備し、あわせてCI方針のADRを追加するPRです。
Changes:
- Backend向けCI(Poetry install / Ruff lint / Pytest実行)を追加
- Frontend向けCI(npm ci / lint / build)を追加
- 供給網・シークレット・脆弱性のチェック用セキュリティワークフローを追加(SBOM生成+スキャン)
- CI戦略・ツール選定理由をADRとして文書化し、Backendにdev依存(ruff/pytest)を追加
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
backend/pyproject.toml |
開発用依存関係(ruff/pytest)を追加し、Backend CIの実行前提を整備 |
.github/workflows/backend.yml |
Python/Poetry環境でLint・Testを走らせるBackend CIを追加 |
.github/workflows/frontend.yml |
Node/npmでLint・Buildを走らせるFrontend CIを追加(CI向けenv注入含む) |
.github/workflows/security.yml |
Secret scan / SBOM生成 / 脆弱性スキャンのセキュリティゲートを追加 |
.github/decisions/001-ci-strategy.md |
CI戦略・ツール選定(Ruff, npm ci等)の意思決定をADR化 |
.github/workflows/backend.yml
Outdated
| # Decision: Run Pytest even if no tests exist yet (ensure setup works) | ||
| # Reason: Validates that the test runner environment is correctly configured. | ||
| - name: Run Tests | ||
| run: poetry run pytest || echo "No tests found, but runner works" |
There was a problem hiding this comment.
pytest || echo ... だと、テスト失敗(exit code 1など)も成功扱いになってCIが常に通ってしまいます。"テスト未検出(通常 exit code 5) だけ許容"にしたい場合は、exit code を判定して 5 のみ握りつぶす形にしてください。
| run: poetry run pytest || echo "No tests found, but runner works" | |
| run: | | |
| set +e | |
| poetry run pytest | |
| status=$? | |
| set -e | |
| if [ "$status" -eq 5 ]; then | |
| echo "No tests found, but runner works" | |
| exit 0 | |
| fi | |
| exit "$status" |
.github/workflows/security.yml
Outdated
|
|
||
| # 1. Secret Scanning (TruffleHog) | ||
| - name: Secret Scan | ||
| uses: trufflesecurity/trufflehog@main |
There was a problem hiding this comment.
trufflesecurity/trufflehog@main は参照先がブランチのため、上流変更で挙動が変わるサプライチェーンリスクがあります。タグ(例: vX.Y.Z)やコミットSHAに固定して実行内容を不変にしてください。
| uses: trufflesecurity/trufflehog@main | |
| uses: trufflesecurity/trufflehog@v3.88.0 |
.github/workflows/security.yml
Outdated
| base: ${{ github.event.repository.default_branch }} | ||
| head: ${{ github.head_ref }} |
There was a problem hiding this comment.
head: ${{ github.head_ref }} は push イベントでは空文字になるため、push時の差分スキャンが成立しない(失敗/意図しない範囲をスキャンする)可能性が高いです。イベント種別で head/base を出し分け(PRなら head_ref/base_ref、pushなら github.sha と github.event.before 等)にしてください。
| base: ${{ github.event.repository.default_branch }} | |
| head: ${{ github.head_ref }} | |
| base: ${{ github.event_name == 'pull_request' && github.base_ref || github.event.before }} | |
| head: ${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} |
backend/pyproject.toml
Outdated
| fastapi = "*" | ||
| uvicorn = {extras = ["standard"], version = "*"} | ||
|
|
||
| [tool.poetry.group.dev.dependencies] | ||
| ruff = "*" | ||
| pytest = "*" |
There was a problem hiding this comment.
The dependencies fastapi, uvicorn, ruff, and pytest are all specified with version "*", meaning CI and production will always pull the latest unpinned releases from PyPI, which increases the risk of a supply-chain compromise if one of these packages is hijacked. A malicious update could execute arbitrary code in your CI environment (or at runtime for fastapi/uvicorn) and exfiltrate secrets or tamper with build artifacts. Pin these dependencies to vetted versions (e.g., exact or constrained version ranges) and update them deliberately through a controlled process.
.github/workflows/backend.yml
Outdated
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.13" | ||
| cache: "poetry" |
There was a problem hiding this comment.
actions/setup-python の cache: "poetry" は通常 poetry.lock をキーに依存しますが、リポジトリ内に backend/poetry.lock が存在しないためキャッシュが効かず、毎回依存解決が走って再現性も落ちます。poetry.lock をコミットするか、CI側で lock を生成・固定する運用に揃えてください。
| cache: "poetry" |
| - name: Secret Scan | ||
| uses: trufflesecurity/trufflehog@main | ||
| with: | ||
| path: ./ | ||
| base: ${{ github.event.repository.default_branch }} | ||
| head: ${{ github.head_ref }} | ||
| extra_args: --only-verified | ||
|
|
There was a problem hiding this comment.
この workflow は push にも反応しますが、push イベントでは github.head_ref が空になるため head 指定が不正になり Secret Scan が失敗する可能性が高いです。push と pull_request で base/head の指定を分ける(条件分岐する)か、push では before/sha を使う設定に修正してください。
| - name: Secret Scan | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| base: ${{ github.event.repository.default_branch }} | |
| head: ${{ github.head_ref }} | |
| extra_args: --only-verified | |
| - name: Secret Scan (pull_request) | |
| if: ${{ github.event_name == 'pull_request' }} | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| # pull_request イベントでは base_ref/head_ref を使用(なければ default_branch にフォールバック) | |
| base: ${{ github.base_ref || github.event.repository.default_branch }} | |
| head: ${{ github.head_ref }} | |
| extra_args: --only-verified | |
| - name: Secret Scan (push) | |
| if: ${{ github.event_name == 'push' }} | |
| uses: trufflesecurity/trufflehog@main | |
| with: | |
| path: ./ | |
| # push イベントでは before/sha を使用して差分をスキャン | |
| base: ${{ github.event.before }} | |
| head: ${{ github.sha }} | |
| extra_args: --only-verified |
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Install Poetry | ||
| run: pipx install poetry |
There was a problem hiding this comment.
pipx install poetry が常に最新の Poetry を取得するため、将来の Poetry の破壊的変更でCIが突然落ちるリスクがあります。Poetryのバージョンを明示的に固定(例: pipx install poetry==X.Y.Z)するか、公式のセットアップ手順に沿って安定したバージョンを使用してください。
| run: pipx install poetry | |
| run: pipx install "poetry==1.8.3" |
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 |
There was a problem hiding this comment.
TruffleHogがgit差分をスキャンする際、デフォルトのactions/checkout@v4は浅いクローン(shallow clone)を実行するため、github.event.beforeのコミットが存在しない可能性があります。
pushイベント時に正確な差分スキャンを行うため、以下のようにfetch-depthを設定することを推奨します:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # 完全な履歴を取得または、必要最小限の履歴のみを取得する場合:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 2 # 直前のコミットとの比較に十分これにより、baseとheadのSHA参照が常に利用可能になります。
| uses: actions/checkout@v4 | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # TruffleHogの差分スキャン用に完全な履歴を取得 |
.github/workflows/security.yml
Outdated
| - name: Generate SBOM | ||
| uses: anchore/sbom-action@v0 |
There was a problem hiding this comment.
Syft SBOM生成アクションで @v0 というメジャーバージョンのみの指定が使われていますが、これはADRの決定(行42-46)と矛盾しています。
ADRでは「タグやコミットSHAに固定することで、CI実行内容の不変性と再現性を担保する」と記載されており、TruffleHogでは @v3.82.13 のように具体的なバージョンが指定されていますが、ここでは @v0 という曖昧な指定になっています。
@v0 は常に最新のv0.x.xバージョンを指す「浮動タグ」であり、予期しない動作変更のリスクがあります。具体的なバージョン(例:@v0.17.2)に固定することを推奨します。
.github/workflows/security.yml
Outdated
| - name: Vulnerability Scan | ||
| uses: anchore/scan-action@v5 |
There was a problem hiding this comment.
Grype脆弱性スキャンアクションでも @v5 というメジャーバージョンのみの指定が使われていますが、これはADRのセキュリティ方針と矛盾しています。
ADR 001の「5. GitHub Actions Version Pinning」(行41-46)では、アクションのバージョンを具体的なタグに固定することが決定されています。@v5 は浮動タグであり、予期しない動作変更のリスクがあります。
具体的なバージョン(例:@v5.2.0)に固定してください。
| # Decision: Use Ruff for fast linting | ||
| # Reason: Ruff is significantly faster than Flake8/Black and covers both roles. | ||
| - name: Run Lint (Ruff) | ||
| run: poetry run ruff check . | ||
|
|
||
| # Decision: Run Pytest even if no tests exist yet (ensure setup works) | ||
| # Reason: Validates that the test runner environment is correctly configured. | ||
| # Security: Only tolerate exit code 5 (no tests found), fail on actual test failures | ||
| - name: Run Tests | ||
| run: | | ||
| poetry run pytest || EXIT_CODE=$? | ||
| if [ "${EXIT_CODE:-0}" -eq 5 ]; then | ||
| echo "No tests found, but runner works" | ||
| exit 0 | ||
| elif [ "${EXIT_CODE:-0}" -ne 0 ]; then | ||
| echo "Tests failed with exit code $EXIT_CODE" | ||
| exit $EXIT_CODE | ||
| fi |
There was a problem hiding this comment.
Issue #5では「Type Check: mypy .」の実行が要件として記載されていますが、実装されたワークフローには含まれていません。
Pythonの型チェックツール mypy を実行するステップが欠落しています。以下の追加が必要です:
pyproject.tomlの dev dependencies にmypyを追加:
mypy = "^1.0.0"- ワークフローにステップを追加(Lintの後、Testの前が推奨):
- name: Run Type Check (mypy)
run: poetry run mypy .型チェックは実行時エラーの早期発見に重要です。
| push: | ||
| branches: ["main", "develop"] |
There was a problem hiding this comment.
Issue #5ではBackend CIのトリガー条件として「backend/ 配下の変更 or main へのPush」と記載されていますが、実装では branches: ["main", "develop"] となっており、develop ブランチも含まれています。
これは機能追加であり問題ではありませんが、develop ブランチの追加理由がPR説明やADRに記載されていません。Git-Flowなどのブランチ戦略を採用している場合は妥当ですが、明文化されていないため、意図が不明確です。
同様の変更がfrontend.ymlにも存在します。
| poetry run pytest || EXIT_CODE=$? | ||
| if [ "${EXIT_CODE:-0}" -eq 5 ]; then | ||
| echo "No tests found, but runner works" | ||
| exit 0 | ||
| elif [ "${EXIT_CODE:-0}" -ne 0 ]; then |
There was a problem hiding this comment.
テスト実行時のエラーハンドリングロジックに問題があります。poetry run pytest || EXIT_CODE=$? の構文では、pytestが成功(exit code 0)した場合、|| の右側が実行されず、EXIT_CODE 変数が未設定のまま残ります。その後の ${EXIT_CODE:-0} はデフォルト値0を使用するため、結果的には動作しますが、ロジックが複雑で読みにくくなっています。
より明確な実装として、以下の方法を推奨します:
poetry run pytest || EXIT_CODE=$?
EXIT_CODE=${EXIT_CODE:-0}
if [ "$EXIT_CODE" -eq 5 ]; then
echo "No tests found, but runner works"
exit 0
elif [ "$EXIT_CODE" -ne 0 ]; then
echo "Tests failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fiまたは、よりシンプルに:
set +e
poetry run pytest
EXIT_CODE=$?
set -e
if [ "$EXIT_CODE" -eq 5 ]; then
echo "No tests found, but runner works"
exit 0
elif [ "$EXIT_CODE" -ne 0 ]; then
echo "Tests failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi| poetry run pytest || EXIT_CODE=$? | |
| if [ "${EXIT_CODE:-0}" -eq 5 ]; then | |
| echo "No tests found, but runner works" | |
| exit 0 | |
| elif [ "${EXIT_CODE:-0}" -ne 0 ]; then | |
| set +e | |
| poetry run pytest | |
| EXIT_CODE=$? | |
| set -e | |
| if [ "$EXIT_CODE" -eq 5 ]; then | |
| echo "No tests found, but runner works" | |
| exit 0 | |
| elif [ "$EXIT_CODE" -ne 0 ]; then |
| @@ -6,8 +6,16 @@ authors = ["Your Name <you@example.com>"] | |||
|
|
|||
| [tool.poetry.dependencies] | |||
| python = "^3.13" | |||
There was a problem hiding this comment.
Pythonのバージョンを ^3.13 に指定していますが、これは非常に新しいバージョンです(2024年10月リリース)。一方で、CI環境でも python-version: "3.13" を使用しているため一貫性はありますが、以下の点を考慮してください:
- 互換性リスク: Python 3.13は最新バージョンであり、一部のライブラリやツールがまだ完全にサポートしていない可能性があります
- デプロイ環境: 本番環境やDockerイメージでPython 3.13が利用可能であることを確認する必要があります
- 推奨: より安定したPython 3.11または3.12の使用を検討することをお勧めします
もしPython 3.13の特定の機能が必要でない場合は、python = "^3.11" に変更することで、より広範な互換性と安定性が得られます。
| python = "^3.13" | |
| python = "^3.11" |
| - name: Run Lint | ||
| run: npm run lint | ||
|
|
||
| - name: Run Build | ||
| # This checks for type errors and build capability | ||
| run: npm run build |
There was a problem hiding this comment.
Issue #5では「Type Check: npm run type-check (tsc)」の実行が要件として記載されていますが、実装されたワークフローには含まれていません。
Next.jsの build ステップで型チェックは実行されますが、ビルドに時間がかかる場合、型エラーの早期発見のために、以下のように明示的な型チェックステップを追加することを検討してください:
- name: Run Type Check
run: npm run type-checkただし、package.json に type-check スクリプトの追加が必要です:
"type-check": "tsc --noEmit"0cfbb11 to
725235f
Compare
725235f to
18d8983
Compare
| # Backend: Python dependencies | ||
| - package-ecosystem: "pip" | ||
| directory: "/backend" | ||
| schedule: | ||
| interval: "weekly" | ||
| day: "monday" | ||
| time: "09:00" | ||
| open-pull-requests-limit: 5 | ||
| labels: | ||
| - "dependencies" | ||
| - "security" | ||
| commit-message: | ||
| prefix: "chore" | ||
| include: "scope" | ||
|
|
There was a problem hiding this comment.
Backend を Poetry で管理している一方、backend/ に poetry.lock が存在しないため、この Dependabot 設定だと更新PRが作られない/意図通り動かない可能性が高いです。poetry.lock をコミットした上で Dependabot 対応を確認し、必要なら Dependabot が解釈できる形式(lockfile前提や requirements 生成など)に合わせて設定してください。
| # Backend: Python dependencies | |
| - package-ecosystem: "pip" | |
| directory: "/backend" | |
| schedule: | |
| interval: "weekly" | |
| day: "monday" | |
| time: "09:00" | |
| open-pull-requests-limit: 5 | |
| labels: | |
| - "dependencies" | |
| - "security" | |
| commit-message: | |
| prefix: "chore" | |
| include: "scope" |
.github/workflows/security.yml
Outdated
| # Reason: Weekly scan shouldn't block development; track in issues | ||
| - name: Vulnerability Scan | ||
| uses: anchore/scan-action@v5.1.0 | ||
| with: | ||
| sbom: sbom.spdx.json | ||
| fail-build: false | ||
| severity-cutoff: critical | ||
| output-format: table | ||
| continue-on-error: true | ||
|
|
||
| # 4. Create Issue on Vulnerability Detection | ||
| - name: Create Security Issue | ||
| if: failure() |
There was a problem hiding this comment.
anchore/scan-action に fail-build: false を指定しつつ continue-on-error: true にしているため、脆弱性検知時にジョブ全体が failure にならず、直後の if: failure() が成立しない可能性が高いです。その結果、Critical を検知しても Issue 作成が発火しない構成になっています。scan ステップに id を付けて if: steps.<id>.outcome == 'failure' のように判定するか、検知時にステップを failure にする設定(例: fail-build を true にして continue-on-error でジョブは継続)に寄せてください。
.github/workflows/security.yml
Outdated
| with: | ||
| script: | | ||
| const title = `🔒 Security Alert: Critical Vulnerabilities Detected (${new Date().toISOString().split('T')[0]})`; | ||
| const body = `## Weekly Security Scan Results | ||
|
|
||
| Critical vulnerabilities were detected in dependencies. | ||
|
|
||
| **Scan Date**: ${new Date().toISOString()} | ||
| **Workflow Run**: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
|
|
||
| ### Action Required | ||
| 1. Review the workflow logs for detailed vulnerability information | ||
| 2. Update affected dependencies or add exceptions to \`.grype.yaml\` with justification | ||
| 3. Close this issue once resolved | ||
|
|
||
| ### Notes | ||
| - This is a weekly automated scan | ||
| - PRs are checked with lightweight tools (pip-audit/npm audit) | ||
| - Dependabot will create PRs for available updates | ||
| `; | ||
|
|
||
| github.rest.issues.create({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| title: title, | ||
| body: body, | ||
| labels: ['security', 'dependencies'] |
There was a problem hiding this comment.
このままだと脆弱性が継続している場合に、週次実行のたびに同種の Issue が増え続ける運用になりがちです(重複 Issue がノイズ化)。既存の未クローズな同タイトル/ラベルの Issue を検索して再利用(コメント追記や本文更新)するか、日付を含めず固定タイトルにして1件に集約するなど、重複抑制の仕組みを入れるのが安全です。
| # Note: cache removed temporarily until poetry.lock is committed | ||
| # Decision: Generate lock file during CI to avoid commit noise | ||
| # Reason: In early development, lockfile can be generated on-the-fly | ||
|
|
||
| - name: Install Dependencies | ||
| # Decision: Allow poetry to generate lock file if missing | ||
| # Reason: Simplifies workflow when lock file is not yet committed | ||
| run: poetry install --no-interaction --no-root |
There was a problem hiding this comment.
Poetry の lockfile(poetry.lock)が未コミットの状態で poetry install を実行しているため、同じコミットでも実行タイミングによって解決される依存関係が変わり得て、CI結果が非再現になってしまいます。供給網リスク低減のためにも poetry.lock をコミットし、CIでは lockfile 前提でインストール(必要ならキャッシュも復活)する構成に寄せてください。
| # Note: cache removed temporarily until poetry.lock is committed | |
| # Decision: Generate lock file during CI to avoid commit noise | |
| # Reason: In early development, lockfile can be generated on-the-fly | |
| - name: Install Dependencies | |
| # Decision: Allow poetry to generate lock file if missing | |
| # Reason: Simplifies workflow when lock file is not yet committed | |
| run: poetry install --no-interaction --no-root | |
| cache: "poetry" | |
| # Decision: Use Poetry cache based on committed poetry.lock | |
| # Reason: Ensure reproducible installs and reduce supply chain risk | |
| - name: Install Dependencies | |
| # Decision: Install dependencies based on committed poetry.lock | |
| # Reason: Ensure reproducible CI results and reduce supply chain risk | |
| run: poetry install --no-interaction --no-root --sync |
.github/workflows/backend.yml
Outdated
| # Reason: Fast vulnerability check (seconds) without blocking PR | ||
| - name: Security Scan (pip-audit) | ||
| run: | | ||
| poetry run pip install pip-audit |
There was a problem hiding this comment.
pip-audit をCI中に都度 pip install しており、ここもバージョン非固定になっています(上流変更でCIが不安定化/想定外の挙動になり得る)。pyproject.toml の dev 依存に pip-audit を追加してバージョンを固定するか、pipx 等で明示的にバージョン固定した実行方法にしてください。
| poetry run pip install pip-audit | |
| poetry run pip install pip-audit==2.7.3 |
18d8983 to
ce48922
Compare
| ### Detected Issues | ||
| ${grypeFailure ? '- ⚠️ **Critical vulnerabilities** in dependencies (see Grype logs)' : ''} | ||
| ${truffleFailure ? '- 🔑 **Secrets leaked** in repository (see TruffleHog logs)' : ''} | ||
|
|
||
| ### Action Required | ||
| 1. Review the workflow logs for detailed information | ||
| 2. ${grypeFailure ? 'Update affected dependencies or add exceptions to `.grype.yaml` with justification' : ''} | ||
| 3. ${truffleFailure ? 'Remove secrets from repository and rotate compromised credentials immediately' : ''} |
There was a problem hiding this comment.
JavaScriptのテンプレートリテラル内で、条件式が空文字列を返す場合があります(grypeFailureやtruffleFailureがfalseの場合)。これによりissue本文に空行が含まれる可能性があります。より適切な処理として、配列にプッシュして.filter(Boolean).join('\n')で結合するか、条件分岐でテンプレート全体を構築することを推奨します。
| ### 7. Event-Specific Git References in Security Scan | ||
|
|
||
| - **Decision**: `github.head_ref` / `github.event.repository.default_branch` の代わりに、イベント種別に応じた適切なSHA参照を使用する。 | ||
| - **Reason**: | ||
| - `github.head_ref` は push イベントでは空文字になるため、差分スキャンが成立しない。 | ||
| - PR時は `github.event.pull_request.{base,head}.sha`、push時は `github.event.before` / `github.sha` を使用することで、正確な差分スキャンを実現する。 |
There was a problem hiding this comment.
ADRセクション7「Event-Specific Git References in Security Scan」では差分スキャンのためのSHA参照について説明されていますが、実際の実装(security.yml)ではスケジュール実行時にフルリポジトリスキャンを行うため、このセクションは現在の実装と一致していません。このADRセクションを削除するか、実装に合わせて「フルリポジトリスキャン戦略」に更新する必要があります。
| - TruffleHogなどのツールバージョンを固定したため、新機能や修正を取り込むには手動更新が必要。 | ||
| - **PR CI時間が大幅短縮**: 重量級スキャンを週次に移行したことで、PRのCI時間が5分短縮される。 | ||
| - **Dependabotが常時監視**: GitHub標準機能により、CI負荷なしで脆弱性を検出し自動PR作成。 | ||
| - **週次スキャンは追跡**: Grypeの結果はIssueとして記録され、チームで対応を追跡できる。 |
There was a problem hiding this comment.
Consequencesセクションで「週次スキャン」と記載されていますが、実装は日次(daily)スキャンです。「週次スキャンは追跡」という記述を「日次スキャンは追跡」に修正する必要があります。
| name: Security Gatekeeper (Weekly) | ||
|
|
||
| # Decision: Run heavy scans daily during hackathon, not on PR | ||
| # Reason: Syft+Grype takes 3-5min; use Dependabot+built-in tools for PR checks | ||
| # Hackathon ends 2026-02-21, so daily scan ensures coverage throughout the event | ||
| on: | ||
| schedule: | ||
| # Daily at 3:00 AM JST (18:00 UTC previous day) - Review results each morning | ||
| - cron: "0 18 * * *" |
There was a problem hiding this comment.
ワークフロー名「Security Gatekeeper (Weekly)」と実際のスケジュール(daily)が一致していません。名前には「Weekly」と記載されていますが、コメントとcron設定は「daily」になっています。名前を「Security Gatekeeper (Daily)」に変更するか、スケジュールを週次に変更して一貫性を保つ必要があります。
| - **Decision**: 重量級スキャン(Syft+Grype)を週次実行に変更し、PR時は軽量ツールを使用する。 | ||
| - **Reason**: | ||
| - Syft+Grypeは3〜5分かかり、PR体験を損なう。 | ||
| - ビルトインツール(pip-audit / npm audit)は数秒で完了。 | ||
| - Dependabotが常時監視し、自動PR作成。 | ||
| - **3層構造**: | ||
| 1. **Dependabot(常時)**: GitHub標準機能、CI負荷ゼロ、自動PR作成 | ||
| 2. **pip-audit / npm audit(PR時)**: 秒単位、PRをブロックしない(continue-on-error) | ||
| 3. **Syft+Grype(週次)**: 詳細スキャン、結果をIssue化して追跡 |
There was a problem hiding this comment.
ADR文書では「重量級スキャン(Syft+Grype)を週次実行に変更」と記載されていますが、実際のワークフローはdaily(日次)で実行されています。ADRの記述を「日次実行」に更新するか、実装をweeklyに変更して一貫性を保つ必要があります。
| - package-ecosystem: "pip" | ||
| directory: "/backend" |
There was a problem hiding this comment.
Dependabotの設定で「pip」エコシステムを使用していますが、このプロジェクトはPoetryを使用しています。Dependabotは「pip」エコシステムでPoetryプロジェクトも検出できますが、より明示的に「pip」の代わりに「poetry」をサポートするよう設定を検討してください。ただし、現在のGitHub DependabotはPoetryを直接サポートしていないため、「pip」のままで動作するはずですが、pyproject.tomlとpoetry.lockを正しく認識するか確認が必要です。
8d79179 to
26735d7
Compare
Summary: Added comprehensive CI workflows for Backend (FastAPI) and Frontend (Next.js) with security-first approach based on Issue #3. Backend CI (.github/workflows/backend.yml): - Poetry-based dependency management - Ruff linting (fast Rust-based linter) - Pytest with proper exit code handling (only tolerate exit 5 for no tests) - Python 3.13 support Frontend CI (.github/workflows/frontend.yml): - npm ci for reproducible installs - ESLint + Next.js build validation - Mock environment variables for CI builds Security Gatekeeper (.github/workflows/security.yml): - Dependency-only triggers (pyproject.toml, package.json, Dockerfiles) - TruffleHog secret scanning (pinned to v3.82.13) - SBOM generation + Grype vulnerability scan (Critical only) - Support for main/develop branches (Git Flow compatible) - Managed exceptions via .grype.yaml with documented justification - Emergency bypass via skip-security label (admin-only) Security Improvements: - Pin all dependencies to version ranges (no wildcards) - Event-specific SHA refs for accurate diff scanning - Proper pytest exit code handling to catch real failures - Tool versions pinned to prevent supply-chain attacks Documentation: - ADR 001: CI Strategy & Tool Selection - Vulnerability exception config (.grype.yaml) Rationale: - Unpinned dependencies pose supply-chain risk - Early security detection at develop branch saves time - Dependency-only scans optimize CI cost - Documented exceptions enable realistic security posture Close #3
26735d7 to
6a182db
Compare
Summary
Issue #3 に基づき、プロジェクトの技術スタック(FastAPI / Next.js)に合わせたCIワークフローを作成・整備しました。
また、ツール選定の理由やリスクヘッジの方針を明文化するため、ADR(Architecture Decision Record)を追加しました。
Background / Why
Ruffを選んだか、なぜnpm ciを使うかなどの意思決定を将来のメンバーに伝えるため。Changes
.github/workflows/backend.yml: Poetryによる依存関係インストール、RuffによるLint、Pytestによるテスト実行(現在はプレースホルダ).github/workflows/frontend.yml: npm ciによるクリーンインストール、Next.js Build & Lint.github/decisions/001-ci-strategy.md: CI戦略に関するADRbackend/pyproject.toml: 開発用依存関係(ruff, pytest)の追加Security / Risk
NEXT_PUBLIC_API_URLを注入しています。ruffを採用し、CI時間を短縮しつつコード品質を維持します。Related Issue
Close #5