Skip to content

Conversation

@nanotaboada
Copy link
Owner

@nanotaboada nanotaboada commented Nov 28, 2025

Replace legacy runtime.txt with .python-version for better tooling support and developer experience.

Changes:

  • Add .python-version file with Python 3.13.3
  • Update .gitignore to track .python-version
  • Modify GitHub Actions to use python-version-file parameter
  • Remove hardcoded PYTHON_VERSION env variable from CI
  • Add Python Version Management section to README
  • Add Dockerfile comments referencing .python-version
  • Delete runtime.txt

Benefits:

  • Automatic version switching with pyenv/asdf/mise
  • Single source of truth for Python version
  • Simplified CI/CD configuration
  • Better alignment with modern Python ecosystem

Closes #433


This change is Reviewable

Summary by CodeRabbit

  • Chores
    • Centralized Python version management via a dedicated version file; CI and build tooling now consume that file instead of inline version settings. Updated ignore rules and runtime metadata to align with this approach.
  • Documentation
    • Added a Python version management section to the README describing the version file, tool compatibility, and expected workflow behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

Replace legacy runtime.txt with .python-version for better
tooling support and developer experience.

Changes:
- Add .python-version file with Python 3.13.3
- Update .gitignore to track .python-version
- Modify GitHub Actions to use python-version-file parameter
- Remove hardcoded PYTHON_VERSION env variable from CI
- Add Python Version Management section to README
- Add Dockerfile comments referencing .python-version
- Delete runtime.txt

Benefits:
- Automatic version switching with pyenv/asdf/mise
- Single source of truth for Python version
- Simplified CI/CD configuration
- Better alignment with modern Python ecosystem

Closes #433
@coderabbitai
Copy link

coderabbitai bot commented Nov 28, 2025

Walkthrough

Created and tracked a .python-version file (3.13.3), removed runtime.txt, updated GitHub Actions to read Python version from .python-version instead of an env var, updated .gitignore comments and Dockerfile annotations, and added a README section documenting .python-version usage.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
/.github/workflows/python-app.yml
Removed the PYTHON_VERSION env var and replaced inline python-version usage with python-version-file: '.python-version' in lint and test jobs; updated setup-python action versions where applicable.
Version file migration
/.python-version, /runtime.txt
Added .python-version containing 3.13.3; removed legacy runtime.txt.
Ignore & comments
/.gitignore
Replaced # .python-version comment with # Track .python-version for consistent Python version across environments in two locations (un-ignores intent).
Dockerfile annotations
/Dockerfile
Added comments in builder and runtime stages indicating Python version should match .python-version (no runtime behavior changes).
Documentation
/README.md
Added "Python Version Management" section describing .python-version usage and tool compatibility (pyenv/asdf/mise).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Focus review on:
    • .github/workflows/python-app.yml — ensure both jobs correctly reference python-version-file and action versions are compatible.
    • .python-version — confirm version value is intended (3.13.3).
    • Removal of runtime.txt — verify no deployment systems depend on it.
    • Dockerfile comments — ensure developers know to keep the Dockerfile Python tag in sync (no code change).

Pre-merge checks and finishing touches

✅ 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 and concisely summarizes the main change: migrating from runtime.txt to .python-version.
Linked Issues check ✅ Passed All requirements from issue #433 are met: .python-version created, .gitignore updated, GitHub Actions workflow modified, README documented, runtime.txt removed, and Dockerfile commented.
Out of Scope Changes check ✅ Passed All changes are directly related to the .python-version migration; no out-of-scope modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/python-version

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
Dockerfile (1)

5-5: Dockerfile comments reference specific patch version — consider making them version-agnostic.

The added comments helpfully cross-reference .python-version to guide synchronization. However, including the specific version "(currently 3.13.3)" in the comments creates a maintenance burden. If .python-version is updated (e.g., from 3.13.3 → 3.13 for security reasons), these comments become stale and misleading.

Consider revising the comments to reference the file without the hardcoded version:

-# Python version should match .python-version file (currently 3.13.3)
+# Python version should match .python-version file

This keeps the intent clear while avoiding version duplication and staleness issues.

Additionally, if the .python-version version is updated to use major.minor format (per the prior issue), the base image tags on lines 6 and 24 will need corresponding updates.

Also applies to: 23-23

README.md (1)

22-26: README version specification may need updating if .python-version version changes.

The new Python Version Management section is well-written and helpful. Line 26 hardcodes "Python 3.13.3," which risks becoming outdated if .python-version is updated. The parenthetical "(or the version specified in .python-version)" provides a good safety net, but consider simplifying to avoid dual-version statements:

-Alternatively, ensure you have Python 3.13.3 (or the version specified in `.python-version`) installed.
+Alternatively, ensure you have the Python version specified in `.python-version` installed.

This keeps the README version-agnostic and eliminates duplication.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f7a528 and 69fa9ab.

📒 Files selected for processing (6)
  • .github/workflows/python-app.yml (2 hunks)
  • .gitignore (2 hunks)
  • .python-version (1 hunks)
  • Dockerfile (2 hunks)
  • README.md (1 hunks)
  • runtime.txt (0 hunks)
💤 Files with no reviewable changes (1)
  • runtime.txt
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments using .python-version files, Heroku strongly recommends specifying only the major Python version (e.g., "3.13") rather than exact patch versions. This allows apps to automatically receive Python security updates each time they build. The .python-version file supports both major version syntax (3.13) and exact patch version syntax (3.13.3), but the major version approach is the recommended best practice.
📚 Learning: 2025-09-26T08:23:15.158Z
Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments using .python-version files, Heroku strongly recommends specifying only the major Python version (e.g., "3.13") rather than exact patch versions. This allows apps to automatically receive Python security updates each time they build. The .python-version file supports both major version syntax (3.13) and exact patch version syntax (3.13.3), but the major version approach is the recommended best practice.

Applied to files:

  • Dockerfile
  • .python-version
  • .gitignore
  • README.md
📚 Learning: 2025-09-26T08:23:15.158Z
Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments, .python-version files should specify only major.minor versions (e.g., "3.13") rather than exact patch versions (e.g., "3.13.3"). Heroku's documentation explicitly recommends against specifying patch versions, allowing the platform to automatically use the latest patch version for security updates.

Applied to files:

  • .python-version
  • .gitignore
  • README.md
📚 Learning: 2025-04-17T19:22:41.270Z
Learnt from: nanotaboada
Repo: nanotaboada/python-samples-fastapi-restful PR: 331
File: .github/workflows/python-app.yml:22-24
Timestamp: 2025-04-17T19:22:41.270Z
Learning: The wagoid/commitlint-github-action GitHub Action uses commitlint/config-conventional settings as a default fallback if no commitlint configuration file exists in the repository. This enforces Conventional Commits format with specific allowed types (build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test) and formatting rules.

Applied to files:

  • .github/workflows/python-app.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (3)
.gitignore (1)

89-89: Documentation improvement to .gitignore comment.

The updated comment clearly explains why .python-version should be tracked, improving developer understanding of the configuration decision.

.github/workflows/python-app.yml (1)

25-29: Workflow correctly delegates Python version to .python-version file.

Both the lint (lines 25-29) and test (lines 51-55) jobs properly use python-version-file: '.python-version' to read the version from the new .python-version file. The setup-python action will automatically parse the file and configure the correct Python version for each job. Caching via cache: 'pip' is preserved correctly.

Please verify that any hardcoded PYTHON_VERSION environment variable references have been fully removed from the codebase and are not used in other workflows or scripts.

Also applies to: 51-55

.python-version (1)

1-1: Original review comment's Heroku assumption does not apply to this project.

This repository is not Heroku-deployed. The project uses Docker Compose for containerized deployment and .python-version for local development tools (pyenv/asdf/mise), as documented in README.md. The migration from runtime.txt to .python-version reflects the change in development workflow tooling, not a Heroku deployment configuration.

For Docker-based projects, exact patch version pinning (3.13.3) is a valid and appropriate practice—it ensures reproducible builds and consistent behavior across environments. Security updates for Python are managed via base image updates in the Dockerfile, not through .python-version changes. The current cross-file consistency (.python-version, Dockerfile lines 5–6 and 23–24, README.md line 26) is correct and intentional.

The original review comment's recommendation was based on Heroku best practices that do not apply here.

@sonarqubecloud
Copy link

@codacy-production
Copy link

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.00%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (9f7a528) 131 119 90.84%
Head commit (1dd02d9) 131 (+0) 119 (+0) 90.84% (+0.00%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#434) 0 0 ∅ (not applicable)

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

@codecov
Copy link

codecov bot commented Nov 28, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.65%. Comparing base (9f7a528) to head (1dd02d9).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master     #434   +/-   ##
=======================================
  Coverage   89.65%   89.65%           
=======================================
  Files           3        3           
  Lines         116      116           
=======================================
  Hits          104      104           
  Misses         12       12           
Components Coverage Δ
Services 79.31% <ø> (ø)
Routes 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/python-app.yml (1)

25-29: Approved: Successfully migrated to python-version-file parameter.

Both the lint and test jobs now properly use the .python-version file via the python-version-file parameter, removing the hardcoded PYTHON_VERSION environment variable. This establishes a single source of truth for Python version across local development and CI/CD.

Minor note: Inconsistent setup-python versions across jobs.

The lint job uses actions/setup-python@v6.0.0 while the test job uses actions/setup-python@v6.1.0. For consistency and simpler maintenance, consider standardizing on a single version (e.g., both on v6.1.0). Both versions support python-version-file, so this is a style preference rather than a functional issue.

Also applies to: 51-55

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69fa9ab and 1dd02d9.

📒 Files selected for processing (1)
  • .github/workflows/python-app.yml (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments, .python-version files should specify only major.minor versions (e.g., "3.13") rather than exact patch versions (e.g., "3.13.3"). Heroku's documentation explicitly recommends against specifying patch versions, allowing the platform to automatically use the latest patch version for security updates.
Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments using .python-version files, Heroku strongly recommends specifying only the major Python version (e.g., "3.13") rather than exact patch versions. This allows apps to automatically receive Python security updates each time they build. The .python-version file supports both major version syntax (3.13) and exact patch version syntax (3.13.3), but the major version approach is the recommended best practice.
📚 Learning: 2025-04-17T19:22:41.270Z
Learnt from: nanotaboada
Repo: nanotaboada/python-samples-fastapi-restful PR: 331
File: .github/workflows/python-app.yml:22-24
Timestamp: 2025-04-17T19:22:41.270Z
Learning: The wagoid/commitlint-github-action GitHub Action uses commitlint/config-conventional settings as a default fallback if no commitlint configuration file exists in the repository. This enforces Conventional Commits format with specific allowed types (build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test) and formatting rules.

Applied to files:

  • .github/workflows/python-app.yml
📚 Learning: 2025-04-17T19:22:41.270Z
Learnt from: nanotaboada
Repo: nanotaboada/python-samples-fastapi-restful PR: 331
File: .github/workflows/python-app.yml:22-24
Timestamp: 2025-04-17T19:22:41.270Z
Learning: The wagoid/commitlint-github-action GitHub Action will use commitlint/config-conventional settings as a default fallback if no commitlint configuration file exists in the repository.

Applied to files:

  • .github/workflows/python-app.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (1)
.github/workflows/python-app.yml (1)

28-28: Verify .python-version file is properly created and tracked.

The workflow now expects the .python-version file to exist at the project root. Confirm that:

  • The file has been created with the correct Python version (3.13.3 per PR objectives)
  • It is tracked in git (.gitignore updated to allow it)
  • No runtime.txt remains as a conflicting source of truth

Also applies to: 54-54

@nanotaboada
Copy link
Owner Author

Actionable comments posted: 0

🧹 Nitpick comments (2)

Dockerfile (1)> 5-5: Dockerfile comments reference specific patch version — consider making them version-agnostic.

The added comments helpfully cross-reference .python-version to guide synchronization. However, including the specific version "(currently 3.13.3)" in the comments creates a maintenance burden. If .python-version is updated (e.g., from 3.13.3 → 3.13 for security reasons), these comments become stale and misleading.
Consider revising the comments to reference the file without the hardcoded version:

-# Python version should match .python-version file (currently 3.13.3)
+# Python version should match .python-version file

This keeps the intent clear while avoiding version duplication and staleness issues.
Additionally, if the .python-version version is updated to use major.minor format (per the prior issue), the base image tags on lines 6 and 24 will need corresponding updates.
Also applies to: 23-23

README.md (1)> 22-26: README version specification may need updating if .python-version version changes.

The new Python Version Management section is well-written and helpful. Line 26 hardcodes "Python 3.13.3," which risks becoming outdated if .python-version is updated. The parenthetical "(or the version specified in .python-version)" provides a good safety net, but consider simplifying to avoid dual-version statements:

-Alternatively, ensure you have Python 3.13.3 (or the version specified in `.python-version`) installed.
+Alternatively, ensure you have the Python version specified in `.python-version` installed.

This keeps the README version-agnostic and eliminates duplication.

📜 Review details
Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits
Reviewing files that changed from the base of the PR and between 9f7a528 and 69fa9ab.

📒 Files selected for processing (6)

  • .github/workflows/python-app.yml (2 hunks)
  • .gitignore (2 hunks)
  • .python-version (1 hunks)
  • Dockerfile (2 hunks)
  • README.md (1 hunks)
  • runtime.txt (0 hunks)

💤 Files with no reviewable changes (1)

  • runtime.txt

🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings

Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments using .python-version files, Heroku strongly recommends specifying only the major Python version (e.g., "3.13") rather than exact patch versions. This allows apps to automatically receive Python security updates each time they build. The .python-version file supports both major version syntax (3.13) and exact patch version syntax (3.13.3), but the major version approach is the recommended best practice.

📚 Learning: 2025-09-26T08:23:15.158Z

Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments using .python-version files, Heroku strongly recommends specifying only the major Python version (e.g., "3.13") rather than exact patch versions. This allows apps to automatically receive Python security updates each time they build. The .python-version file supports both major version syntax (3.13) and exact patch version syntax (3.13.3), but the major version approach is the recommended best practice.

Applied to files:

  • Dockerfile
  • .python-version
  • .gitignore
  • README.md

📚 Learning: 2025-09-26T08:23:15.158Z

Learnt from: edmorley
Repo: nanotaboada/python-samples-fastapi-restful PR: 419
File: .python-version:1-1
Timestamp: 2025-09-26T08:23:15.158Z
Learning: For Heroku deployments, .python-version files should specify only major.minor versions (e.g., "3.13") rather than exact patch versions (e.g., "3.13.3"). Heroku's documentation explicitly recommends against specifying patch versions, allowing the platform to automatically use the latest patch version for security updates.

Applied to files:

  • .python-version
  • .gitignore
  • README.md

📚 Learning: 2025-04-17T19:22:41.270Z

Learnt from: nanotaboada
Repo: nanotaboada/python-samples-fastapi-restful PR: 331
File: .github/workflows/python-app.yml:22-24
Timestamp: 2025-04-17T19:22:41.270Z
Learning: The wagoid/commitlint-github-action GitHub Action uses commitlint/config-conventional settings as a default fallback if no commitlint configuration file exists in the repository. This enforces Conventional Commits format with specific allowed types (build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test) and formatting rules.

Applied to files:

  • .github/workflows/python-app.yml

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)

  • GitHub Check: Codacy Static Code Analysis

🔇 Additional comments (3)

.gitignore (1)> 89-89: Documentation improvement to .gitignore comment.

The updated comment clearly explains why .python-version should be tracked, improving developer understanding of the configuration decision.

.github/workflows/python-app.yml (1)> 25-29: Workflow correctly delegates Python version to .python-version file.

Both the lint (lines 25-29) and test (lines 51-55) jobs properly use python-version-file: '.python-version' to read the version from the new .python-version file. The setup-python action will automatically parse the file and configure the correct Python version for each job. Caching via cache: 'pip' is preserved correctly.
Please verify that any hardcoded PYTHON_VERSION environment variable references have been fully removed from the codebase and are not used in other workflows or scripts.
Also applies to: 51-55

.python-version (1)> 1-1: Original review comment's Heroku assumption does not apply to this project.

This repository is not Heroku-deployed. The project uses Docker Compose for containerized deployment and .python-version for local development tools (pyenv/asdf/mise), as documented in README.md. The migration from runtime.txt to .python-version reflects the change in development workflow tooling, not a Heroku deployment configuration.
For Docker-based projects, exact patch version pinning (3.13.3) is a valid and appropriate practice—it ensures reproducible builds and consistent behavior across environments. Security updates for Python are managed via base image updates in the Dockerfile, not through .python-version changes. The current cross-file consistency (.python-version, Dockerfile lines 5–6 and 23–24, README.md line 26) is correct and intentional.
The original review comment's recommendation was based on Heroku best practices that do not apply here.

I've considered this approach, but I prefer to keep the full version 3.13.3 pinned for the following reasons:

Reproducibility & Determinism:

  • Explicit patch versions ensure identical builds across all environments (local, CI, production)
  • Critical for debugging - knowing the exact Python version eliminates a variable when investigating issues
  • Docker builds are deterministic and cacheable with specific versions

Security & Control:

  • Patch updates can introduce subtle behavioral changes or regressions
  • We maintain awareness of Python releases and can test/verify before upgrading
  • CVE fixes in patch releases are important, but we want to validate them first rather than auto-pulling

CI/CD Consistency:

  • Our GitHub Actions cache and Docker layer cache benefit from version stability
  • Unexpected patch bumps could cause cache invalidation and slower builds

Low Maintenance Burden:

  • Bumping every ~2 months is manageable and keeps us engaged with Python releases
  • It's an opportunity to review changelogs and test new patches deliberately
  • Already have Dependabot watching for updates

While 3.13 would work fine for many projects, for this application the benefits of explicit versioning outweigh the convenience of automatic patch updates. We value predictability over convenience here.

@nanotaboada nanotaboada merged commit c9b9737 into master Nov 28, 2025
19 checks passed
@nanotaboada nanotaboada deleted the feature/python-version branch November 28, 2025 23:18
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.

Migrate from runtime.txt to .python-version

2 participants