Skip to content

Fix configuration regressions and modernize container runtime defaults - #16

Merged
ThomasBury merged 1 commit into
mainfrom
codex/conduct-in-depth-code-review-for-best-practices-ppxx6x
Mar 3, 2026
Merged

Fix configuration regressions and modernize container runtime defaults#16
ThomasBury merged 1 commit into
mainfrom
codex/conduct-in-depth-code-review-for-best-practices-ppxx6x

Conversation

@ThomasBury

@ThomasBury ThomasBury commented Mar 3, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Address startup failures caused by missing or mismatched settings and make configuration usage explicit and typed.
  • Provide sane defaults for environment, logging and rate-limiting to allow bootstrapping in minimal environments and safer logging of secrets.
  • Replace deprecated FastAPI startup usage with a lifespan handler and improve container build/runtime best practices.

Description

  • Add typed AppSettings fields for environment, logging, and rate-limits with defaults and a redacted() helper for safe structured logging in src/acebet/app/config.py.
  • Wire the typed settings object into the application entrypoint and switch to settings.acebet_* attributes for rate limits and logging in src/acebet/app/main.py.
  • Replace @app.on_event("startup") with a FastAPI lifespan handler that runs configuration validation before serving requests.
  • Tidy authentication helpers for readability (organized imports and wrapped long jwt.encode/jwt.decode calls) in src/acebet/app/dependencies/auth.py.
  • Improve Dockerfile layering and runtime defaults by copying dependency manifests first, pre-installing deps with uv sync --no-install-project, copying source afterwards, and running the container as a non-root user, plus Python runtime env flags.

Testing

  • Ran uv run pytest -q and all tests passed (4 passed).
  • Ran uv run ruff check src/acebet/app/config.py src/acebet/app/main.py src/acebet/app/dependencies/auth.py and linting checks passed for the changed files.
  • Attempted docker build -t acebet:test . but the docker CLI is not available in the execution environment so the image build could not be validated here.

Codex Task

Summary by CodeRabbit

Release Notes

  • Chores

    • Optimized Docker container builds for faster caching and improved security with non-root user execution.
    • Improved application startup process with enhanced lifecycle management.
  • New Features

    • Added environment variable configuration for logging level and log file output.
    • Added configurable rate limiting settings for API endpoints and login attempts.

@coderabbitai

coderabbitai Bot commented Mar 3, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Optimizes Docker image build caching by separating dependency and source layers, adds new configuration fields for logging and rate limiting with environment variable support, introduces a non-root runtime user, and refactors app startup validation from event handler to async lifespan context manager.

Changes

Cohort / File(s) Summary
Docker Build Optimization
Dockerfile
Restructures build steps to copy dependency manifests first, install dependencies, then copy application source separately. Adds Python optimization environment variables and introduces non-root app user for runtime security.
Configuration Management
src/acebet/app/config.py
Adds new configurable fields: acebet_log_level, acebet_log_file, acebet_default_rate_limit, acebet_login_rate_limit with environment variable aliases. Sets default value for acebet_env to "development" and introduces redacted() method for safe logging output.
Application Lifecycle & Configuration Wiring
src/acebet/app/main.py
Refactors app startup validation from @app.on_event("startup") to async lifespan context manager. Wires new settings fields throughout: acebet_log_level, acebet_log_file for logging and acebet_default_rate_limit, acebet_login_rate_limit for rate limiting.
Code Cleanup
src/acebet/app/dependencies/auth.py
Reorders imports and reformats multi-line function calls without behavioral changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #14: Introduces settings object with redacted() method for safe log representation across configuration surface.
  • PR #9: Modifies AppSettings class and its integration into main.py startup validation and authentication dependencies.

Suggested labels

enhancement

Poem

🐰 Configuration hops and Docker layers spring,
Non-root users guarding secrets they bring,
Lifespan contexts at startup's first bound,
Rate limits and logging, all wired around,
A swifter build with each caching sound!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main changes: fixing configuration regressions while modernizing container runtime practices, which aligns with all four modified files (config.py, main.py, auth.py, and Dockerfile).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/conduct-in-depth-code-review-for-best-practices-ppxx6x

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.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the application's robustness and maintainability by addressing configuration regressions and modernizing container runtime practices. It ensures explicit and typed configuration usage, provides sensible defaults for various settings, and improves the overall security and efficiency of the Docker build process. The changes aim to prevent startup failures, facilitate easier bootstrapping in minimal environments, and promote safer handling of sensitive information.

Highlights

  • Configuration Modernization: Modernized application configuration by introducing typed settings with explicit defaults for environment, logging, and rate-limiting, and added a redacted() helper for safe structured logging.
  • FastAPI Lifespan Handler: Replaced the deprecated FastAPI @app.on_event("startup") decorator with an asynccontextmanager based lifespan handler to ensure configuration validation occurs before the application serves requests.
  • Dockerfile Improvements: Improved Dockerfile efficiency and security by optimizing layer caching, introducing Python runtime environment variables, and running the container as an unprivileged user.
  • Authentication Helper Readability: Enhanced readability of authentication helpers by organizing imports and reformatting long jwt.encode and jwt.decode calls.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • Dockerfile
    • Added PYTHONDONTWRITEBYTECODE and PYTHONUNBUFFERED environment variables.
    • Reordered COPY and RUN commands to leverage Docker layer caching more effectively.
    • Introduced an unprivileged app user for running the container.
  • src/acebet/app/config.py
    • Imported Any for type hinting.
    • Added acebet_env with a default value.
    • Introduced new fields for logging (acebet_log_level, acebet_log_file) and rate-limiting (acebet_default_rate_limit, acebet_login_rate_limit) with default values.
    • Refactored ValueError message for ACEBET_ACCESS_TOKEN_EXPIRE_MINUTES for better readability.
    • Implemented a redacted() method to provide a safe, redacted representation of settings for logging.
  • src/acebet/app/dependencies/auth.py
    • Reordered imports for consistency.
    • Refactored jwt.encode and jwt.decode calls to improve line wrapping and readability.
  • src/acebet/app/main.py
    • Imported asynccontextmanager for the new lifespan handler.
    • Imported the settings object directly from config.py.
    • Replaced the @app.on_event("startup") decorator with an asynccontextmanager based lifespan handler for FastAPI.
    • Updated limiter and logging.basicConfig to use the new settings.acebet_* attributes for configuration.
Activity
  • The author ran uv run pytest -q, and all 4 tests passed.
  • Linting checks passed for the changed files (src/acebet/app/config.py, src/acebet/app/main.py, src/acebet/app/dependencies/auth.py) using uv run ruff check.
  • An attempt was made to build the Docker image (docker build -t acebet:test .), but validation could not be completed due to the docker CLI not being available in the execution environment.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@ThomasBury
ThomasBury merged commit 17b0989 into main Mar 3, 2026
1 check was pending
@ThomasBury
ThomasBury deleted the codex/conduct-in-depth-code-review-for-best-practices-ppxx6x branch March 3, 2026 13:10

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several significant improvements, including modernizing the Dockerfile for better caching and security, fixing configuration-related startup issues by introducing a typed AppSettings model, and replacing a deprecated FastAPI startup event with a lifespan handler. The changes are well-executed and enhance the project's robustness and maintainability. I have a couple of suggestions to further improve container image size and configuration consistency.

Comment thread Dockerfile
# Run the application.
CMD ["/app/.venv/bin/fastapi", "run", "src/acebet/app/main.py", "--port", "80", "--host", "0.0.0.0"]
# Copy dependency manifests first for better layer caching.
COPY pyproject.toml uv.lock README.md ./

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The README.md file is being copied into the container image but doesn't appear to be required for building dependencies or at runtime. To keep the container image as lean as possible, which is a containerization best practice, consider removing it from this COPY instruction.

COPY pyproject.toml uv.lock ./

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex check if it the readme is still being copied and needs to be fixed

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result

I checked the Dockerfile at the referenced location, and README.md is not being copied anymore. The COPY instruction at line 12 currently includes only pyproject.toml and uv.lock, so there is nothing to fix for that specific review comment. DockerfileL11-L13

Commands I used

  • sed -n '1,220p' Dockerfile
  • nl -ba Dockerfile | sed -n '1,80p'
  • curl -s https://docs.docker.com/build/cache/optimize/ | head -n 5 (web check per instruction)

Repo update status

No code changes were required for this check, so I did not create a commit and did not open a PR.

View task →

Comment thread src/acebet/app/main.py
from starlette.types import Message

from acebet.app.config import validate_config
from acebet.app.config import settings, validate_config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Great work introducing the typed settings object. For consistency and to fully embrace the typed configuration pattern you've introduced, I suggest refactoring the application to exclusively use the settings object for all configuration values. Currently, some parts of the code still use module-level constants from config.py (e.g., ACCESS_TOKEN_EXPIRE_MINUTES). Using settings.acebet_access_token_expire_minutes directly would make the configuration management more unified and maintainable.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex check if we need to fix the imports and make consistent importing settings and accessing the env var via the config object

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85efb3c635

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Dockerfile
Comment on lines +25 to +28
USER app

# Run the application.
CMD ["/app/.venv/bin/fastapi", "run", "src/acebet/app/main.py", "--port", "80", "--host", "0.0.0.0"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use unprivileged default port for non-root runtime

This change switches the container to USER app but keeps FastAPI bound to port 80, which causes startup failure on standard Linux container defaults where non-root users cannot bind ports below 1024. In those environments the process exits with a permission error before serving traffic, so the default image command is not runnable without extra runtime sysctl/capability tweaks.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex check if the issue remains and fix it if necessary

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Checked the referenced review concern and confirmed it still applied: the container ran as non-root (USER app) while binding FastAPI to privileged port 80; updated the Docker CMD to use port 8000 so default runtime works without extra capabilities. DockerfileL25-L28
  • Committed the fix on the current branch (5f7c5d6) and created a follow-up PR via the make_pr tool.

Testing

  • curl -s https://man7.org/linux/man-pages/man7/ip.7.html | rg -n "privileged ports|below 1024" -m 2
  • nl -ba Dockerfile | sed -n '1,120p'
  • nl -ba Dockerfile | sed -n '22,32p'
  • git status --short

View task →

Comment thread Dockerfile
RUN uv sync --frozen --no-cache --no-install-project

# Copy application source.
COPY src ./src

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Include production data directory in image build

The Docker build now copies only src/, but the /predict/ handler defaults to testing=False and reads the production dataset from /app/data/atp_data_production.feather (the top-level data/ tree). Because that directory is no longer copied into the image, regular prediction requests in the container hit a file-not-found error at runtime.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex make sure the copy cotains also the data, the prediction requests must work in docker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Addressed the PR thread request by updating the Docker build to include runtime data needed by prediction requests: Dockerfile now copies data/ into /app/data (COPY data ./data) alongside src/. This preserves the current layering approach while fixing the missing dataset issue in container runs. DockerfileL17-L19
  • Confirmed the app’s production prediction path expects the dataset under /app/data/atp_data_production.feather, which is why this copy is required for Docker runtime correctness. src/acebet/app/main.pyL215-L219
  • Committed the change on the current branch (b34434a) and created a follow-up PR via the make_pr tool.

Testing

  • curl -s https://docs.docker.com/build/cache/optimize/ | head -n 5
  • nl -ba Dockerfile | sed -n '1,120p'
  • nl -ba src/acebet/app/main.py | sed -n '206,230p'
  • git add Dockerfile && git commit -m "Include data assets in Docker image for prediction endpoint"
  • git status --short

View task →

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17b09896a1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/acebet/app/config.py
model_config = SettingsConfigDict(extra="ignore")

acebet_env: str = Field(alias="ACEBET_ENV")
acebet_env: str = Field(default="development", alias="ACEBET_ENV")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require ACEBET_ENV instead of defaulting to development

Defaulting acebet_env to "development" makes a missing ACEBET_ENV look like an intentional dev deployment, so validate_secret_key_in_non_dev is bypassed and the code falls back to the hardcoded JWT secret (ACEBET_SECRET_KEY = ... "acebet-dev-insecure-secret-key"). Before this change, missing ACEBET_ENV failed fast; after it, a misconfigured production container can silently start with a predictable signing key.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex revert to the clean fail fast solution

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Reverted ACEBET_ENV to a required setting by removing the "development" default from AppSettings, restoring fail-fast behavior when the env var is missing. src/acebet/app/config.pyL14-L17
  • Updated test bootstrap setup to explicitly define ACEBET_ENV=test before app import, so tests remain stable with the stricter config requirement. tests/test_acebet.pyL6-L10
  • Committed the changes on the current branch (bfb1c47) and created a follow-up PR via the make_pr tool.

Testing

  • curl -s https://docs.pydantic.dev/latest/concepts/pydantic_settings/ | head -n 20
  • uv run pytest -q
  • uv run ruff check src/acebet/app/config.py tests/test_acebet.py

View task →

Comment thread Dockerfile
RUN uv sync --frozen --no-cache --no-install-project

# Copy application source.
COPY src ./src

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Copy production data assets into the Docker image

This Dockerfile now only copies src into /app, but the default inference path (testing=false) loads /app/data/atp_data_production.feather from src/acebet/app/main.py. As a result, containerized /predict requests in default mode will fail with FileNotFoundError unless operators manually mount data/, which is a regression from the previous COPY . /app behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex make sure the data are also copied so that the predict works fine in docker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Updated the Docker build to include runtime data assets by adding COPY data ./data alongside src, so prediction requests in Docker can access /app/data/* as expected. DockerfileL17-L19
  • Kept the existing layer-caching structure intact (manifests first, dependency install, then app assets), only expanding the runtime copy step to include data/ as requested in the review thread. DockerfileL11-L22
  • Committed the change on the current branch (9dabf11) and created a follow-up PR via the make_pr tool.

Testing

  • curl -s https://docs.docker.com/reference/dockerfile/ | head -n 20
  • nl -ba Dockerfile | sed -n '1,80p'
  • git status --short && git rev-parse HEAD

View task →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant