Skip to content

fix(backend): Python 3.13 固定で libsql segfault を回避+起動スモークテスト/再発防止#400

Merged
yusuke0610 merged 4 commits into
mainfrom
fix/pin-python-3.13
Jun 22, 2026
Merged

fix(backend): Python 3.13 固定で libsql segfault を回避+起動スモークテスト/再発防止#400
yusuke0610 merged 4 commits into
mainfrom
fix/pin-python-3.13

Conversation

@yusuke0610

@yusuke0610 yusuke0610 commented Jun 22, 2026

Copy link
Copy Markdown
Owner

概要

devforge-apiSegmentation fault(exit 139 / SIGSEGV)で起動ループする不具合の修正と、その再発防止一式です。

根本原因

Renovate の chore(deps): update python docker tag to v3.14 で backend のベースイメージが python:3.13-slimpython:3.14-slim に上がり、sqlalchemy-libsql が引く libsql-experimental(ネイティブ拡張)が Python 3.14 未対応で、起動時の alembic マイグレーション(app/db/bootstrap.py)で native crash していた。faulthandler の C スタックが libsql_experimental.so を指すことを確認済み。

upstream / arch 検証

  • libsql-experimental0.0.55 が最新で 3.14 対応版は未リリース(wheel は cp312 まで)。
  • 3.14 対応は upstream で未解決の open issue: tursodatabase/libsql-experimental-python#106
  • arm64(ローカル)/ amd64(Cloud Run と同一 arch)の両方で segfault を実機再現。非互換は arch 非依存で本番でも 3.14 は不可。→ 3.13 据え置きが正しい。

変更内容

1. 修正(hotfix)

ファイル 変更
backend/Dockerfile builder / runtime の base を python:3.13-slim(元の SHA pin)へ戻す
.github/renovate.json5 dockerfilepythonallowedVersions: "<3.14" に制限(3.13.x patch・digest は維持し 3.14 bump のみ抑止)

2. 再発防止(CI スモークテスト)

ファイル 変更
.github/workflows/ci.yml smoke-backend ジョブ追加。本番イメージ build → 実 libSQL 起動 → /health(DB 接続検証)が 200 を返すことを確認。pytest が通らない「ビルドは成功するが起動時に native が segfault する」種の不具合を検知する

3. 本番 arch 再現用ツール

ファイル 変更
docker-compose.amd64.yml / make dev-amd64(-build) ローカルで本番と同じ amd64 を重ねて起動できるオーバーレイ(native 不具合の再現用 / Mac では低速)

4. ドキュメント

ファイル 変更
CLAUDE.md / rules/backend/{test,database}.md 「ネイティブ・コンテナ起動は smoke-backend で検証する」方針を明文化(旧「make test-backend では検証されない」記述を更新)

なぜ CI が green のまま本番が落ちたか

test-backenduv python install 3.13 + 標準 SQLite(create_all)で動き、3.14 も libsql ネイティブ経路も一度も実行していなかった。本 PR の smoke-backend はこの穴を塞ぐ(本 PR の CI でも自己検証される)。

フォローアップ

upstream #106 が解決し libsql-experimental が 3.14 対応版を出したら、renovate.json5<3.14 制限を外して Python を上げ直す。

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Enhanced backend startup validation through automated health checks in CI
    • Updated Python runtime to version 3.13 for improved stability
    • Added development tools for testing on amd64 architecture
    • Improved CI/CD infrastructure for better deployment reliability

Renovate が base image を python:3.14 に上げた結果、libsql-experimental
(sqlalchemy-libsql 経由)が 3.14 未対応でマイグレーション時に segfault
(exit 139)し api が起動ループしていた。

- backend/Dockerfile: builder/runtime を python:3.13-slim に戻す
- .github/renovate.json5: dockerfile の python を <3.14 に制限し再発防止
  (upstream 対応待ち: tursodatabase/libsql-python#106)

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

coderabbitai Bot commented Jun 22, 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 53 minutes and 16 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 refill rate.

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, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

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: 0ccea1d8-2784-40ce-8813-393f62143c1e

📥 Commits

Reviewing files that changed from the base of the PR and between 32f27ae and 2d78d53.

📒 Files selected for processing (2)
  • .claude/rules/backend/test.md
  • .github/workflows/ci.yml
📝 Walkthrough

Walkthrough

The PR downgrades the backend Docker base image from Python 3.14 to 3.13 (with updated SHA256 digests), pins Renovate to block 3.14+ upgrades, adds a smoke-backend CI job that builds the production image and polls /health, introduces a docker-compose.amd64.yml override and two new Makefile targets for local amd64 reproduction, and updates Claude AI rules/docs to document the smoke test coverage boundary.

Changes

Python 3.13 downgrade, smoke-backend CI, and amd64 local dev tooling

Layer / File(s) Summary
Python 3.13 downgrade and Renovate version pin
backend/Dockerfile, .github/renovate.json5
Both builder and final Dockerfile stages switch from python:3.14-slim to python:3.13-slim with updated SHA256 digests. A new Renovate packageRules entry restricts dockerfile python updates to versions <3.14.
AMD64 local dev compose override and Makefile targets
docker-compose.amd64.yml, Makefile
docker-compose.amd64.yml is introduced to pin the api service to linux/amd64. Makefile gains dev-amd64 and dev-amd64-build targets (added to .PHONY, help text, and implementation) that apply the override on top of docker-compose.yml.
smoke-backend CI job
.github/workflows/ci.yml
A new smoke-backend job generates ephemeral .env secrets (including a JWT RSA keypair), runs docker compose up --build for the api service, polls http://localhost:8000/health with retries, prints container state and logs on failure, and always tears down with docker compose down -v.
Claude rules and docs for smoke coverage boundary
.claude/CLAUDE.md, .claude/rules/backend/database.md, .claude/rules/backend/test.md
CLAUDE.md adds a lesson-learned bullet for smoke-backend. database.md updates libSQL native path verification to reference smoke-backend CI and adds make dev-amd64-build to local steps. test.md adds a section describing execution paths pytest does not cover that smoke-backend fills.

Sequence Diagram(s)

sequenceDiagram
  participant GHA as GitHub Actions
  participant DC as docker compose
  participant API as api container
  participant Health as /health

  GHA->>GHA: Generate .env (RSA keypair, DB URL, secrets)
  GHA->>DC: docker compose up -d --build api
  DC->>API: Build python:3.13-slim → run alembic migrate → start uvicorn
  loop Poll /health (up to N attempts)
    GHA->>Health: GET http://localhost:8000/health
    Health-->>GHA: 200 OK or connection refused
  end
  alt Health check failed
    GHA->>DC: docker compose ps
    GHA->>DC: docker compose logs api
    DC-->>GHA: container state + stderr
    GHA->>GHA: exit 1
  end
  GHA->>DC: docker compose down -v
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hopping past Python's newest gate,
We pinned to 3.13 — 3.14 must wait!
A smoke test now sniffs every container start,
AMD64 tricks no longer fool the art.
Green /health replies make this bunny cheer,
No broken prod surprises lurking here! 🥕

🚥 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 changes: fixing a Python 3.13 pinning issue to avoid libsql segfault and adding smoke tests for startup validation.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pin-python-3.13

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 and usage tips.

yusuke0610 and others added 2 commits June 22, 2026 21:56
test-backend(pytest) は標準 SQLite で動き本番イメージの起動経路
(libsql ネイティブ / alembic / uvicorn 起動)を検証しないため、Python 3.14
bump 時の起動 segfault を CI ですり抜けていた。実イメージ build → 実 libSQL
起動 → /health で起動成功を検証する smoke-backend ジョブを追加する。

- .github/workflows/ci.yml: smoke-backend ジョブ追加(amd64 ランナー)
- CLAUDE.md / rules/backend/{test,database}.md: ネイティブ・コンテナ起動は
  smoke-backend で検証する方針を明文化(旧「検証されない」記述を更新)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@yusuke0610 yusuke0610 changed the title fix(backend): Python を 3.13 に固定し libsql segfault を回避 fix(backend): Python 3.13 固定で libsql segfault を回避+起動スモークテスト/再発防止 Jun 22, 2026

@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 @.claude/rules/backend/test.md:
- Around line 30-33: There is conflicting guidance in this test documentation
file. The new section about pytest coverage clarifies that make test-backend
does not exercise Alembic migrations, libsql native driver, or container startup
paths (those are validated by the smoke-backend CI job instead). However, the
trigger list earlier in the document still instructs contributors to verify
migrations using make test-backend. Reconcile these sections by either removing
the make test-backend instruction from the migration verification checks in the
trigger list, or clarifying which specific checks use make test-backend versus
smoke-backend, so contributors follow consistent and non-contradictory guidance.

In @.github/workflows/ci.yml:
- Around line 302-303: The Checkout step in the GitHub Actions workflow is
persisting GitHub token credentials by default, which creates unnecessary
security risk since this job does not need to push back to the repository. Add
the persist-credentials option set to false in the actions/checkout step to
disable credential persistence and reduce the attack surface in accordance with
security guidelines.
🪄 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: c5299bee-63e0-443b-901c-bd43252971b6

📥 Commits

Reviewing files that changed from the base of the PR and between ef2dfe5 and 32f27ae.

📒 Files selected for processing (8)
  • .claude/CLAUDE.md
  • .claude/rules/backend/database.md
  • .claude/rules/backend/test.md
  • .github/renovate.json5
  • .github/workflows/ci.yml
  • Makefile
  • backend/Dockerfile
  • docker-compose.amd64.yml

Comment thread .claude/rules/backend/test.md
Comment thread .github/workflows/ci.yml
- ci.yml: smoke-backend の checkout に persist-credentials: false を付与
  (push しないジョブのため認証情報を保持しない / codegen-drift と同方針)
- rules/backend/test.md: マイグレーション追加トリガーの「make test-backend で確認」を
  smoke-backend / database.md 手順に整合(pytest は migration を通らない旨と矛盾しないよう修正)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@yusuke0610
yusuke0610 merged commit 9fc6f10 into main Jun 22, 2026
19 checks passed
@yusuke0610
yusuke0610 deleted the fix/pin-python-3.13 branch July 20, 2026 12:26
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