Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Dependabot 設定
# https://docs.github.com/code-security/dependabot/working-with-dependabot/dependabot-options-reference
#
# これまで dependabot.yml が無く、Dependabot alerts 起点のセキュリティ更新しか
# 動いていなかったため、バージョン更新も定期的に回すようにする。
#
# 方針: minor/patch はグループ化して 1 PR にまとめ、major は個別 PR で判断する。
# リリース直後の不具合や yank を踏まないよう cooldown で寝かせてから PR を出す。

version: 2

updates:
# ---------------------------------------------------------------------------
# Python (uv: pyproject.toml + uv.lock)
# ---------------------------------------------------------------------------
- package-ecosystem: "uv"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "python"
commit-message:
prefix: "chore(deps)"
cooldown:
default-days: 7
semver-major-days: 30
groups:
python-minor-patch:
patterns:
- "*"
update-types:
- "minor"
- "patch"

# ---------------------------------------------------------------------------
# GitHub Actions (.github/workflows/)
# ---------------------------------------------------------------------------
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci(deps)"
cooldown:
default-days: 7
groups:
github-actions:
patterns:
- "*"
update-types:
- "minor"
- "patch"

# ---------------------------------------------------------------------------
# Docker ベースイメージ
# タグベースのため semver 単位の cooldown (semver-major-days 等) は指定できない
# ---------------------------------------------------------------------------
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 3
labels:
- "dependencies"
- "docker"
commit-message:
prefix: "build(deps)"
cooldown:
default-days: 7
groups:
container-images:
patterns:
- "*"
update-types:
- "minor"
- "patch"
ignore:
# Python 3.15 のプレリリースは除外し、正式版 3.15 は許可する
- dependency-name: "python"
versions:
- ">= 3.15.a, < 3.15"

# ---------------------------------------------------------------------------
# Terraform (provider / module のバージョン制約)
# ---------------------------------------------------------------------------
- package-ecosystem: "terraform"
directory: "/terraform"
schedule:
interval: "monthly"
time: "09:00"
timezone: "Asia/Tokyo"
open-pull-requests-limit: 2
labels:
- "dependencies"
- "terraform"
commit-message:
prefix: "build(deps)"
cooldown:
default-days: 14
groups:
terraform-providers:
patterns:
- "*"
update-types:
- "minor"
- "patch"
77 changes: 77 additions & 0 deletions .github/workflows/actions-security-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Actionsのセキュリティチェック

# ワークフロー自体に潜むセキュリティ上の問題を zizmor で検査します。
# 対象は .github/ 配下の変更があったときだけです。
#
# 落ちたときの読み方(よく出るもの):
# unpinned-uses サードパーティの uses: をタグでなくコミットSHAで指定してください
# 例) foo/bar@v1 → foo/bar@<40桁SHA> # v1
# artipacked actions/checkout に persist-credentials: false を足してください
# (checkout は既定で書き込み権限つきトークンを .git に残すため)
# excessive-permissions permissions: を必要最小限に絞ってください
# template-injection テンプレート式を run: に直接書かず、env: 経由で渡してください
#
# 個別に許容したい指摘がある場合は、その行に次のコメントを付けられます:
# # zizmor: ignore[ルール名]
#
# 詳細な説明: https://docs.zizmor.sh/audits/

# 注意: このファイルの中に、テンプレート式の記法をリテラルで書かないこと。
# 解説目的でも Actions がそれを式として評価しようとし、ワークフロー全体が
# 起動できなくなる(ジョブが1つも作られず failure になる)。

on:
push:
branches: [master]
paths:
- '.github/**'
pull_request:
paths:
- '.github/**'
workflow_dispatch:

permissions: {}

jobs:
zizmor:
name: zizmor による静的解析
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Run zizmor
id: zizmor
uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2
with:
inputs: .github/workflows/
# SARIF (advanced-security) は finding があっても失敗しないためゲートにならない。
# annotations は zizmor の終了コードをそのまま返すのでゲートとして機能する
advanced-security: false
annotations: true
min-severity: low

- name: 失敗したときの案内
if: failure()
run: |
{
echo "## Actionsのセキュリティチェックで指摘が出ました"
echo ""
echo "上の **Annotations** に、該当する行と理由が出ています。"
echo ""
echo "| ルール | 直し方 |"
echo "|---|---|"
echo "| \`unpinned-uses\` | サードパーティの \`uses:\` をコミットSHAで指定する(例: \`foo/bar@<SHA> # v1\`)|"
echo "| \`artipacked\` | \`actions/checkout\` に \`persist-credentials: false\` を足す |"
echo "| \`excessive-permissions\` | \`permissions:\` を必要な範囲まで絞る |"
echo "| \`template-injection\` | テンプレート式を \`run:\` に直書きせず \`env:\` 経由で渡す |"
echo ""
echo "意図的にその書き方をしている場合は、該当行に \`# zizmor: ignore[ルール名]\` を付けると除外できます。"
echo ""
echo "ルールの詳しい説明: https://docs.zizmor.sh/audits/"
} >> "$GITHUB_STEP_SUMMARY"
125 changes: 125 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
name: CI

# 依存を更新したときに壊れていないかを見るためのチェック。
# Dependabot の PR にもこれが走るので、更新して安全かどうかが分かる。

on:
push:
branches: [master]
pull_request:
workflow_dispatch:

permissions: {}

# 同じブランチで新しい push があったら、古い実行は止める
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
check:
name: 静的解析とスモークテスト
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

# Python 自体も uv が pyproject.toml の requires-python を見て用意する
- name: Setup uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
cache-dependency-glob: uv.lock

# --locked は「uv.lock が pyproject.toml と揃っていること」も検査する。
# --frozen は lock の中身をそのまま使うだけで、ずれを検出しない。
# Dockerfile は --frozen なので、ずれの検出はここでしか行われない。
- name: Install
run: uv sync --locked

# --output-format=github を付けると、PR の該当行に注釈が出る
- name: Lint
run: uv run ruff check --output-format=github .

- name: フォーマットの確認
if: ${{ !cancelled() }}
run: uv run ruff format --check .

# main.py は読み込むだけで zips/ を展開して NDC を全件パースするので、
# import できること自体が ndc-parser と FastAPI のスモークテストになる。
# テストが無いためこれが唯一の実行時チェック。
- name: 読み込み確認
if: ${{ !cancelled() }}
run: uv run python -c "import main; print(len(main.ndc8_items), len(main.ndc9_items))"

docker:
name: Dockerイメージ
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Buildxをセットアップ
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4

- name: イメージをビルド
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
context: .
push: false
load: true
tags: ndc-dev-api:ci
cache-from: type=gha
cache-to: type=gha,mode=max

# 本番と同じ gunicorn + UvicornWorker で実際に応答するところまで見る。
# 起動時に NDC を展開するので、応答までしばらくかかる。
- name: 起動確認 (スモークテスト)
run: |
docker run -d --name ndc-dev-api-ci -p 8080:8080 ndc-dev-api:ci
for i in $(seq 1 30); do
if curl -fsS http://localhost:8080/ndc9/123 -o /dev/null; then
echo "分類項目の応答を確認しました"
exit 0
fi
sleep 2
done
echo "::error::コンテナが起動しませんでした"
docker logs ndc-dev-api-ci
exit 1

- name: コンテナを片付ける
if: always()
run: docker rm -f ndc-dev-api-ci || true

done:
name: CI 完了
# ブランチ保護の必須チェックにはこのジョブだけを指定する。
# ジョブを増減しても保護の設定を変えずに済む。
needs: [check, docker]
if: ${{ always() }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions: {}
steps:
- name: 各ジョブの結果を確認
env:
RESULTS: ${{ join(needs.*.result, ' ') }}
run: |
echo "各ジョブの結果: $RESULTS"
for r in $RESULTS; do
if [ "$r" != "success" ]; then
echo "::error::成功しなかったジョブがあります"
exit 1
fi
done
32 changes: 32 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Actionsのセキュリティチェック(zizmor)の設定
#
# unpinned-uses: uses: の書き方をどこまで厳しくするか
#
# GitHub 公式(actions/*)と自社(ndc-dev/* と CALIL/*)は、タグやブランチでの
# 指定を許容します。これらの参照先を差し替えられるのは GitHub 自身か自社だけで、
# 第三者が公開するアクションとはリスクの質が違うためです。
#
# CALIL/* を含めているのは、この設定を CALIL org のリポジトリと共通の形に
# 保っておくためです(ワークフローを org 間でコピーしても判定が変わらない)。
#
# それ以外はすべてコミットSHAでの固定を必須にします。第三者のアクションは
# タグを後から別のコミットに付け替えられるため、タグ指定だと
# 「レビューしたコードとは違うものが動く」ことが起こりえます。
#
# 第三者のアクションを追加するときの書き方:
# - uses: foo/bar@0123456789abcdef0123456789abcdef01234567 # v1.2.3
# SHA はタグのページか `gh api repos/foo/bar/commits/v1.2.3 --jq .sha` で取れます。
# Dependabot はこの形式を認識し、更新時に SHA とコメントの両方を書き換えます。
#
# 個別に許容したい指摘は、ワークフロー側の該当行に次のコメントを付けて除外します:
# # zizmor: ignore[ルール名]
#
# 設定の詳細: https://docs.zizmor.sh/configuration/
rules:
unpinned-uses:
config:
policies:
"actions/*": ref-pin
"ndc-dev/*": ref-pin
"CALIL/*": ref-pin
"*": hash-pin
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Python依存関係のインストール
# uv.lock をそのまま使うので requirements.txt は要らない。
# --frozen: uv.lock を書き換えず、ロックどおりに入れる(ずれていれば失敗する)
# --no-dev: autopep8 など開発用の依存は入れない
# --no-dev: ruff など開発用の依存は入れない
# --no-install-project: このプロジェクト自体はパッケージとして入れない
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project
Expand All @@ -33,4 +33,4 @@
# ワーカーを増やすとその分メモリに複製される。512Miの小規模インスタンスなので1ワーカーに絞り、
# 同時実行数はCloud Run側のインスタンス数(自動スケール)に任せる。
# --threads は sync/gthread worker専用のオプションで UvicornWorker(asyncio)には効かないため付けない。
CMD exec gunicorn --bind :$PORT --workers 1 -k uvicorn_worker.UvicornWorker main:app

Check warning on line 36 in Dockerfile

View workflow job for this annotation

GitHub Actions / Dockerイメージ

JSON arguments recommended for ENTRYPOINT/CMD to prevent unintended behavior related to OS signals

JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior related to OS signals More info: https://docs.docker.com/go/dockerfile/rule/json-args-recommended/
Loading