Skip to content

Rebuild full application#485

Merged
chrisaddy merged 9 commits intomasterfrom
rebuild
May 12, 2025
Merged

Rebuild full application#485
chrisaddy merged 9 commits intomasterfrom
rebuild

Conversation

@forstmeier
Copy link
Copy Markdown
Collaborator

@forstmeier forstmeier commented May 8, 2025

Changes

  • purge all resources
  • add back initial/minimal resources

Comments

Starting from scratch in Python for the rebuild sprint.

Summary by CodeRabbit

  • New Features
    • Introduced a new data management service with FastAPI, providing endpoints for health checks and querying equity bar data by date range.
    • Added support for querying data from either local in-memory tables or Google Cloud Storage CSV files, based on environment configuration.
  • Chores
    • Added project configuration and Docker support for the new data management service.
    • Introduced standardized GitHub issue templates for bugs and feature requests.
    • Added Python code quality check workflow using Mise.
  • Refactor
    • Simplified and updated project configuration files, removing unused language- and environment-specific settings.
    • Updated CI workflows for testing and coverage reporting.
  • Style
    • Reformatted configuration files for improved readability.
  • Documentation
    • Updated and simplified the README content.
  • Removed
    • Deleted legacy infrastructure, Haskell platform, and related build/test files.
    • Removed obsolete GitHub workflows and infrastructure configuration files.
    • Removed static landing page and Pulumi infrastructure code.

@forstmeier forstmeier requested a review from chrisaddy May 8, 2025 19:43
@forstmeier forstmeier self-assigned this May 8, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 8, 2025

## Walkthrough

This update removes the Haskell-based platform service, its infrastructure-as-code (Pulumi) deployment, and related CI/CD workflows. It introduces a new Python-based "datamanager" FastAPI service with Docker support, updates project configuration to focus on Python, and streamlines ignore and task files. New GitHub issue templates are added for bug and feature reporting.

## Changes

| File(s) / Path(s)                                   | Change Summary |
|-----------------------------------------------------|---------------|
| `.flox/.gitignore`, `.flox/env.json`, `.flox/env/manifest.toml` | Deleted or reformatted `.flox` files; removed ignored directories and cleaned up manifest. |
| `.github/PULL_REQUEST_TEMPLATE.md`                  | Removed a comment line from PR template. |
| `.github/workflows/lint.yaml`, `.github/workflows/stale.yaml`, `.github/workflows/test.yaml` | Deleted lint workflow; updated stale workflow permissions and naming; renamed and modified test workflow for push trigger and coverage upload. |
| `.github/workflows/quality.yaml`                     | Added new GitHub Actions workflow for Python code quality checks. |
| `.gitignore`                                        | Simplified: removed language/editor-specific ignores, now ignores only `.flox`, `.env`, and `.DS_Store`. |
| `.mise.toml`                                        | Removed Haskell and platform-specific tasks; added generic Python install and parameterized Docker build/run tasks for services. |
| `README.md`                                         | Simplified repository description; removed detailed component listing and section header; clarified setup instructions with new install task. |
| `index.html`                                        | Deleted static HTML landing page. |
| `infrastructure/*`                                  | Deleted all infrastructure code and configs: Pulumi YAML, Python modules, dependencies, and project metadata. |
| `platform/*`                                        | Deleted all Haskell platform service code, build files, Dockerfile, and test suite. |
| `pyproject.toml`                                    | Updated: capitalized description, Python 3.13+, changed workspace members, added build configuration sections. |
| `.github/ISSUE_TEMPLATE/BUG.md`, `.github/ISSUE_TEMPLATE/FEATURE.md` | Added new issue templates for bugs and features. |
| `application/datamanager/.dockerignore`             | Added Docker ignore file for Python build artifacts and VCS data. |
| `application/datamanager/Dockerfile`                | Added Dockerfile for FastAPI service with Uvicorn and DuckDB/Polars. |
| `application/datamanager/pyproject.toml`            | Added Python project config for datamanager with dependencies and build settings. |
| `application/datamanager/src/datamanager/main.py`   | Added new FastAPI service for querying equity bar data from DuckDB or GCS, with health and data endpoints. |
| `.pre-commit-config.yaml`                            | Added pre-commit configuration for Python quality and test hooks. |
| `application/datamanager/tests/test_main.py`        | Added test for health endpoint of the datamanager FastAPI service. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant User
    participant FastAPI (application)
    participant Database
    participant DuckDB
    participant GCS

    User->>FastAPI (application): GET /equity-bars?start_date&end_date
    FastAPI (application)->>Database: query(start_date, end_date)
    alt GCS credentials provided
        Database->>DuckDB: Install & load httpfs extension
        Database->>GCS: Generate daily CSV file paths
        Database->>DuckDB: Query read_csv(GCS paths)
    else No GCS credentials
        Database->>DuckDB: Query local in-memory table
    end
    DuckDB-->>Database: Return Polars DataFrame
    Database-->>FastAPI (application): DataFrame
    FastAPI (application)-->>User: JSON response with data and metadata

Poem

🍊
Out with the Haskell, in with the new,
Python and FastAPI now carry us through!
Datamanager's ready, with DuckDB in tow,
Query your bars, watch the data flow.
The platform is lighter, the cloud now at rest—
This bunny hops forward, and wishes you the best!
🐇


<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> - CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> 
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=pocketsizefund/pocketsizefund&utm_content=485):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Copy Markdown
Contributor

@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 (4)
README.md (2)

9-9: Clarify the repository description.
The line reads "This repository holds the resources for the fund platform," which is quite generic. Consider specifying which resources are included (e.g., initial Python modules, configuration scripts, data pipelines) or rephrasing for greater clarity. For example:

“This repository contains the foundational Python modules and configuration scripts for the Pocket Size Fund platform.”


25-35: Reintroduce a header for the principles list.
The list of principles currently appears without its own section heading. Adding a header (e.g., ## Principles) before the block will improve the document’s structure and help readers understand the context of these items.

.flox/env.json (1)

2-3: Approve JSON reformatting. The updated indentation improves readability without altering any configuration values.

Consider ensuring a trailing newline at the end of this file to maintain POSIX compatibility.

.flox/env/manifest.toml (1)

24-24: Add POSIX-compliant trailing newline. Reintroducing a final newline improves compatibility with Unix tools and editors.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1e813f and f15499d.

⛔ Files ignored due to path filters (3)
  • .flox/env/manifest.lock is excluded by !**/*.lock
  • platform/stack.yaml.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (32)
  • .flox/.gitignore (0 hunks)
  • .flox/env.json (1 hunks)
  • .flox/env/manifest.toml (1 hunks)
  • .github/CODE_OF_CONDUCT.md (0 hunks)
  • .github/CONTRIBUTING.md (0 hunks)
  • .github/PULL_REQUEST_TEMPLATE.md (0 hunks)
  • .github/SECURITY.md (0 hunks)
  • .github/workflows/lint.yaml (0 hunks)
  • .github/workflows/stale.yaml (0 hunks)
  • .github/workflows/test.yaml (0 hunks)
  • .gitignore (1 hunks)
  • .mise.toml (0 hunks)
  • README.md (1 hunks)
  • index.html (0 hunks)
  • infrastructure/Pulumi.prod.yaml (0 hunks)
  • infrastructure/Pulumi.yaml (0 hunks)
  • infrastructure/__main__.py (0 hunks)
  • infrastructure/cloud_run.py (0 hunks)
  • infrastructure/project.py (0 hunks)
  • infrastructure/pyproject.toml (0 hunks)
  • infrastructure/topics.py (0 hunks)
  • platform/Dockerfile (0 hunks)
  • platform/Setup.hs (0 hunks)
  • platform/app/Main.hs (0 hunks)
  • platform/compose.yaml (0 hunks)
  • platform/package.yaml (0 hunks)
  • platform/platform.cabal (0 hunks)
  • platform/src/Account.hs (0 hunks)
  • platform/src/Lib.hs (0 hunks)
  • platform/stack.yaml (0 hunks)
  • platform/test/Spec.hs (0 hunks)
  • pyproject.toml (0 hunks)
💤 Files with no reviewable changes (28)
  • .github/CONTRIBUTING.md
  • platform/compose.yaml
  • .github/CODE_OF_CONDUCT.md
  • infrastructure/topics.py
  • infrastructure/main.py
  • platform/app/Main.hs
  • .github/PULL_REQUEST_TEMPLATE.md
  • infrastructure/Pulumi.yaml
  • infrastructure/project.py
  • platform/stack.yaml
  • .github/workflows/stale.yaml
  • infrastructure/Pulumi.prod.yaml
  • platform/Setup.hs
  • infrastructure/pyproject.toml
  • .flox/.gitignore
  • platform/src/Lib.hs
  • .mise.toml
  • pyproject.toml
  • index.html
  • .github/workflows/test.yaml
  • platform/test/Spec.hs
  • platform/Dockerfile
  • .github/workflows/lint.yaml
  • .github/SECURITY.md
  • platform/package.yaml
  • platform/platform.cabal
  • platform/src/Account.hs
  • infrastructure/cloud_run.py
🔇 Additional comments (2)
.gitignore (1)

2-4: Approve simplified ignore patterns. Retaining only .DS_Store and the relevant .flox subdirectories aligns perfectly with the new minimal project structure.

.flox/env/manifest.toml (1)

1-23: Approve manifest cleanup. The removal of Haskell and Pulumi package paths aligns with the PR’s objective to strip out unused dependencies and tooling.

Copy link
Copy Markdown
Contributor

@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: 5

🧹 Nitpick comments (4)
application/datamanager/Dockerfile (1)

19-19: Consider adding health check to Dockerfile.

Adding a HEALTHCHECK instruction would improve container orchestration by allowing Docker to monitor the application's health.

+HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 CMD curl -f http://localhost:8080/health || exit 1
 ENTRYPOINT ["uv", "run", "uvicorn", "application.datamanager.src.datamanager.main:application", "--host", "0.0.0.0", "--port", "8080"]
.mise.toml (1)

16-23: Docker run task could use additional container options.

The run task is good but could benefit from some improvements for development use cases.

 [tasks."application:service:run"]
 description = "Run the application service"
 run = """
 docker run \
 --env-file .env \
 --publish 8080:8080 \
+--rm \
+--name {{arg(name="service_name")}} \
 pocketsizefund/{{arg(name="service_name")}}:latest \
 """

Adding --rm would automatically remove the container when it stops, and --name would make it easier to reference the running container in other commands.

application/datamanager/src/datamanager/main.py (2)

91-101: Consider using environment configuration pattern.

Environment variables are loaded directly at module level. Consider using a configuration pattern with validation.

+from pydantic import BaseSettings, Field
+
+class Settings(BaseSettings):
+    gcp_key_id: str = Field("", env="GCP_KEY_ID")
+    gcp_secret: str = Field("", env="GCP_SECRET")
+    gcp_gcs_bucket: str = Field("", env="GCP_GCS_BUCKET")
+    
+    class Config:
+        env_file = ".env"
+
 application = FastAPI()
 
-gcp_key_id = os.getenv("GCP_KEY_ID")
-gcp_secret = os.getenv("GCP_SECRET")
-gcp_gcs_bucket = os.getenv("GCP_GCS_BUCKET")
+settings = Settings()
 
 database = Database(
-    gcp_key_id=gcp_key_id,
-    gcp_secret=gcp_secret,
-    gcp_gcs_bucket=gcp_gcs_bucket,
+    gcp_key_id=settings.gcp_key_id,
+    gcp_secret=settings.gcp_secret,
+    gcp_gcs_bucket=settings.gcp_gcs_bucket,
 )

1-6: Add missing typing imports.

The code uses types in function signatures but doesn't import the typing module.

 from fastapi import FastAPI
 import duckdb
 import polars as pl
 from datetime import datetime, timedelta
 import os
+from typing import List, Dict, Any
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f15499d and 9a58dd6.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/ISSUE_TEMPLATE/BUG.md (1 hunks)
  • .github/ISSUE_TEMPLATE/FEATURE.md (1 hunks)
  • .github/PULL_REQUEST_TEMPLATE.md (0 hunks)
  • .gitignore (1 hunks)
  • .mise.toml (1 hunks)
  • application/datamanager/.dockerignore (1 hunks)
  • application/datamanager/Dockerfile (1 hunks)
  • application/datamanager/pyproject.toml (1 hunks)
  • application/datamanager/src/datamanager/main.py (1 hunks)
  • pyproject.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • .github/PULL_REQUEST_TEMPLATE.md
✅ Files skipped from review due to trivial changes (4)
  • application/datamanager/.dockerignore
  • .github/ISSUE_TEMPLATE/FEATURE.md
  • .github/ISSUE_TEMPLATE/BUG.md
  • application/datamanager/pyproject.toml
🚧 Files skipped from review as they are similar to previous changes (1)
  • pyproject.toml
🔇 Additional comments (7)
.gitignore (1)

1-5: LGTM! Clean and focused .gitignore file.

The simplified .gitignore file is now focused only on the essential patterns needed for the Python-based rebuild, matching the PR objective of starting from scratch with minimal resources.

application/datamanager/Dockerfile (4)

1-1: Good choice of base image.

Using Python 3.13-slim as the base image is a good choice for minimizing container size while using the latest Python version.


3-3: Great choice using uv!

Copying the uv binary from a separate image is an excellent approach. The uv tool is significantly faster than pip and provides better dependency resolution.


5-7: Best practice for apt operations.

Following best practices by combining apt commands and cleaning up cache in a single layer, which reduces image size.


11-15: Good dependency caching strategy.

Copying just the pyproject.toml before the application code allows Docker to cache the dependency installation layer, which speeds up builds when only application code changes.

.mise.toml (2)

1-4: Good dependency management approach.

Using uv sync for Python dependency management is an excellent choice for speed and reliability.


5-14: Well-structured service build task.

The parameterized build task provides a clean way to handle multiple services with a single task definition. Good use of timestamped tags along with the latest tag.

Comment thread application/datamanager/Dockerfile
Comment thread application/datamanager/src/datamanager/main.py
Comment thread application/datamanager/src/datamanager/main.py
Comment thread application/datamanager/src/datamanager/main.py
Comment thread application/datamanager/src/datamanager/main.py
Copy link
Copy Markdown
Contributor

@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 (5)
.mise.toml (5)

6-6: Consistent property spacing
Use description = "Format Python code" instead of description="Format Python code" to match the spacing style used in other tasks.


11-11: Consistent property spacing
Use description = "Check for dead Python code" instead of description="Check for dead Python code" for uniformity.


21-21: Consistent property spacing
Use description = "Run Python code quality checks" instead of description="Run Python code quality checks".


28-36: Restrict Docker build context & pull latest base image
Building from . will send the entire repo (including any unwanted files) to the daemon, potentially slowing builds. Also, add --pull to ensure you’re using the latest base image. For example:

 run = """
 TIMESTAMP=$(date +%Y%m%d)
-docker build \
-  --file application/{{arg(name="service_name")}}/Dockerfile \
-  --tag pocketsizefund/{{arg(name="service_name")}}:latest \
-  --tag pocketsizefund/{{arg(name="service_name")}}:${TIMESTAMP} \
-  .
+docker build --pull \
+  --file application/{{arg(name="service_name")}}/Dockerfile \
+  --tag pocketsizefund/{{arg(name="service_name")}}:latest \
+  --tag pocketsizefund/{{arg(name="service_name")}}:${TIMESTAMP} \
+  application/{{arg(name="service_name")}}
 """

This change narrows your build context to the service folder and keeps the base image up-to-date.


39-45: Parameterize port mapping & streamline container run
Exposing a hard-coded 8080:8080 can lead to conflicts when multiple services run concurrently. Consider making the host port an argument and adding cleanup/detached flags:

 run = """
-docker run \
-  --env-file .env \
-  --publish 8080:8080 \
-  pocketsizefund/{{arg(name="service_name")}}:latest \
-"""
+docker run --rm -d \
+  --env-file .env \
+  --publish {{arg(name="host_port")}}:8080 \
+  pocketsizefund/{{arg(name="service_name")}}:latest \
+"""

You might also reintroduce a generic docker-compose task for orchestrating multi-service setups.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a58dd6 and 4c90dfc.

📒 Files selected for processing (1)
  • .mise.toml (2 hunks)
🔇 Additional comments (1)
.mise.toml (1)

1-3: Check for CLI tool availability
Ensure the uv command is installed and available in all environments (CI, local dev). If this is a custom alias or part of a specific toolkit, document it or add a fallback (e.g., pip install -r requirements.txt or switch to a more common installer like pip-sync).

Copy link
Copy Markdown
Contributor

@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: 3

🧹 Nitpick comments (2)
.github/workflows/stale.yaml (1)

24-24: Add newline at end of file.

YAML files should end with a single newline to satisfy POSIX standards and avoid lint errors.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 24-24: no new line character at the end of file

(new-line-at-end-of-file)

.mise.toml (1)

45-54: Consider adding --pull to docker build.

To ensure you always use the latest base images, you could add --pull. Example diff:

 docker build \
-  --file application/{{arg(name="service_name")}}/Dockerfile \
+  --pull \
+  --file application/{{arg(name="service_name")}}/Dockerfile \
   --tag pocketsizefund/{{arg(name="service_name")}}:latest \
   --tag pocketsizefund/{{arg(name="service_name")}}:${TIMESTAMP} \
   .
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87fc3fb and ce9faa9.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • .github/workflows/quality.yaml (1 hunks)
  • .github/workflows/stale.yaml (2 hunks)
  • .github/workflows/test.yaml (1 hunks)
  • .gitignore (1 hunks)
  • .mise.toml (2 hunks)
  • .pre-commit-config.yaml (1 hunks)
  • README.md (1 hunks)
  • pyproject.toml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .gitignore
  • README.md
  • pyproject.toml
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/test.yaml

12-12: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

.github/workflows/quality.yaml

12-12: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🪛 YAMLlint (1.35.1)
.github/workflows/stale.yaml

[error] 24-24: no new line character at the end of file

(new-line-at-end-of-file)

🔇 Additional comments (11)
.github/workflows/stale.yaml (1)

5-7: Approve permissions configuration.

Defining issues: write and pull-requests: write at the workflow root correctly scopes permissions for the stale action.

.github/workflows/quality.yaml (2)

12-13: Skip actionlint false positive for setup-python.

actions/setup-python@v4 is the current recommended major version and is fully supported. You can safely ignore this actionlint warning.

🧰 Tools
🪛 actionlint (1.7.4)

12-12: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


1-25: Workflow setup is correct.

All steps correctly set up Python 3.13, install and configure uv and mise, and run the lint task as intended.

🧰 Tools
🪛 actionlint (1.7.4)

12-12: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

.mise.toml (6)

1-4: Approve python:install task.

The python:install task correctly installs dependencies using uv sync --all-packages.


5-8: Approve python:format task.

The python:format task is properly configured to format code with ruff format.


9-17: Approve python:dead-code task.

The dead-code check with vulture is set up correctly with appropriate exclusion patterns.


19-27: Approve python:lint task.

ruff check is correctly configured to run code quality checks with GitHub output formatting.


28-44: Approve python:test task.

The coverage steps (run, report, xml) are well-defined for parallel coverage collection and reporting.


56-63: Approve application:service:run task.

The docker run configuration correctly uses environment variables and port mapping.

.github/workflows/test.yaml (2)

12-13: Skip actionlint false positive for setup-python.

actions/setup-python@v4 is fully supported and correct. Ignore this warning.

🧰 Tools
🪛 actionlint (1.7.4)

12-12: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


1-32: Workflow changes are appropriate.

The test and coverage workflow correctly sets up Python 3.13, installs uv and mise, runs tests, and uploads coverage to Coveralls.

🧰 Tools
🪛 actionlint (1.7.4)

12-12: the runner of "actions/setup-python@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

Comment thread .pre-commit-config.yaml
Comment thread .github/workflows/quality.yaml
Comment thread .github/workflows/test.yaml
Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (2)
.mise.toml (2)

1-3: Introducing python:install task
The new task correctly bootstraps Python dependencies using uv sync --all-packages. Consider adding a cache mechanism (e.g., leveraging pip’s cache or preserving a virtual environment directory) to speed up CI and local iterations.


59-66: Declare service_name argument for run task (and consider detach)
Similarly, define the service_name argument here for consistency. Optionally, you may add -d to detach the container by default.

 [tasks."application:service:run"]
+args = ["service_name"]
 description = "Run the application service"
 run = """
   docker run \
     --env-file .env \
     --publish 8080:8080 \
     pocketsizefund/{{arg(name="service_name")}}:latest
 """
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce9faa9 and 76309b4.

📒 Files selected for processing (1)
  • .mise.toml (2 hunks)
🔇 Additional comments (3)
.mise.toml (3)

6-6: Formatting task configuration is solid
The python:format task using ruff format is clear and effective for automatic code styling.


11-11: Dead-code detection is well-configured
python:dead-code leverages Vulture with a high confidence threshold and excludes common folders—good balance between noise and accuracy.


21-21: Lint task dependency and description look good
Chaining python:lint after python:dead-code ensures cleanup before static analysis.

Comment thread .mise.toml
Comment thread .mise.toml
Copy link
Copy Markdown
Contributor

@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: 3

🧹 Nitpick comments (2)
application/datamanager/tests/test_main.py (2)

2-2: Consider simplifying the import path.

The import path from application.datamanager.src.datamanager.main import application is unusually deep and repeats "datamanager" twice. This might indicate a suboptimal package structure.

Consider restructuring the project to simplify imports, perhaps to something like:

-from application.datamanager.src.datamanager.main import application
+from datamanager.main import application

This would require adjusting your package structure and ensuring proper Python path configuration.


6-6: Remove unnecessary blank line.

There are two consecutive blank lines before the test function definition. One is sufficient according to PEP 8 style guidelines.

-

def test_health_check():
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 76309b4 and c8efb15.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • .gitignore (1 hunks)
  • application/datamanager/tests/test_main.py (1 hunks)
  • pyproject.toml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .gitignore
🧰 Additional context used
🪛 GitHub Actions: Test and coverage check
application/datamanager/tests/test_main.py

[error] 1-1: ModuleNotFoundError: No module named 'fastapi'. The test module failed to import due to missing dependency 'fastapi'.

🔇 Additional comments (4)
application/datamanager/tests/test_main.py (1)

7-10: LGTM: Health check test is well-structured.

This test function correctly validates both the status code and response body of the health endpoint.

pyproject.toml (3)

15-16:

Details

✅ Verification successful

Verify workspace source configuration.

The new [tool.uv.sources] section with datamanager = { workspace = true } suggests using uv for dependency management. Ensure this configuration is correct and that the team is familiar with uv usage.


🏁 Script executed:

#!/bin/bash
# Check if uv is mentioned in any documentation or configuration files
find . -type f -name "*.md" -o -name "*.yaml" -o -name "*.toml" | xargs grep -l "uv" | grep -v "pyproject.toml"

Length of output: 211


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "🔍 Searching for ‘tool.uv’ references across the repo"
rg -n "tool\.uv" || echo "No matches for tool.uv found"

echo
echo "📄 Showing top 200 lines of .mise.toml to inspect uv usage"
sed -n '1,200p' .mise.toml || echo ".mise.toml not found"

echo
echo "📄 Showing top 200 lines of .github/workflows/quality.yaml to inspect uv steps"
sed -n '1,200p' .github/workflows/quality.yaml || echo "quality.yaml not found"

echo
echo "📄 Showing top 200 lines of .github/workflows/test.yaml to inspect uv steps"
sed -n '1,200p' .github/workflows/test.yaml || echo "test.yaml not found"

echo
echo "📄 Showing top 200 lines of .flox/env/manifest.toml to inspect uv config"
sed -n '1,200p' .flox/env/manifest.toml || echo "manifest.toml not found"

Length of output: 4283


Workspace Source Configuration Verified

  • Confirmed extensive uv usage in the repo:
    .mise.toml tasks invoke uv sync and uv run …
    • CI workflows install uv via astral-sh/setup-uv@v3 and run tasks with mise
    .flox/env/manifest.toml defines uv.pkg-path = "uv"
  • The new [tool.uv.sources] datamanager = { workspace = true } correctly overrides the datamanager package to use the local workspace.
  • No further changes required.

12-13:

Details

✅ Verification successful

Infrastructure replacement verification.

The workspace members have changed from ["infrastructure"] to ["application/datamanager"], indicating a significant architectural shift. Make sure that all functionality previously in the infrastructure module has been either migrated or intentionally removed.


🏁 Script executed:

#!/bin/bash
# Check if there are any references to the old infrastructure module
git ls-files | xargs grep -l "infrastructure" | grep -v "pyproject.toml"

Length of output: 70


I’ll double-check whether the old infrastructure directory or files still exist in the repo.


🏁 Script executed:

#!/usr/bin/env bash
# Verify if any files or directories under "infrastructure/" remain tracked
git ls-files | grep '^infrastructure/'

Length of output: 64


Infrastructure module removal verified.

A search confirms that the only remaining file under infrastructure/ is .gitkeep and there are no references to “infrastructure” elsewhere in the repo. The old module’s code has been fully migrated or removed. You may delete the empty infrastructure/ directory (and its .gitkeep) if it’s no longer needed.


5-5:

Details

❓ Verification inconclusive

Verify Python 3.13 requirement.

Python 3.13 is a very recent version requirement which might limit adoption and compatibility. Ensure this is intentional and necessary for your project.


🏁 Script executed:

#!/bin/bash
# Check current Python versions in GitHub Actions
cat .github/workflows/test.yaml | grep -i python

# Check if any specific Python 3.13 features are being used
find application -name "*.py" | xargs grep -l "match" | head -5

Length of output: 381


🌐 Web query:

When was Python 3.13 released and what is its adoption rate?

💡 Result:

Python 3.13 Release Date

Python 3.13 was officially released on October 7, 2024[2][3][5][10]. This version was initially scheduled for October 1, 2024, but the release was delayed by a week to address last-minute issues discovered during testing[3][5].

Adoption Rate of Python 3.13

As of May 2025, Python 3.13 adoption is progressing but is not yet universal among developers and organizations. Here are key points about its adoption:

  • Staged Adoption Typical: Historically, new Python versions see gradual adoption as libraries and tools update support. The initial recommendation for most production environments was to wait until all critical dependencies officially supported Python 3.13[8].
  • Ecosystem Support Improving: By the time of the first maintenance releases (3.13.1 in December 2024 and 3.13.2 in February 2025), most widely used packages had started supporting 3.13, making it feasible for many projects to upgrade[8][6].
  • Industry Adoption: There are no precise, up-to-date statistics on adoption rates specifically for Python 3.13 as of May 2025 in the public search results. However, expert commentary suggests that adoption is accelerating now that major libraries and tools have been updated, and more projects are beginning to use 3.13, especially to leverage new features like improved interpreter performance and experimental free-threaded mode[8][6].

"Now that 3.13.1 has come out, you can both get the bug fixes and most packages will be updated, so it’s worth trying to upgrade. If the dependencies you require are still missing 3.13 support, keep trying again every month or two."[8]

Summary Table

Python Version Official Release Date Typical Adoption Status (as of May 2025)
3.13 October 7, 2024 Increasing, but not universal; major projects updating[8][6]

Conclusion

Python 3.13 was released on October 7, 2024. Its adoption rate is steadily increasing, especially following bug-fix releases and wider support across major Python libraries, but it is not yet the default choice in all environments as of mid-2025. Deliberate upgrade pacing is common in the Python ecosystem to ensure compatibility and stability[8][6].

Citations:


Confirm Python ≥3.13 Requirement

Please verify that locking the minimum Python version to 3.13 is intentional:

  • pyproject.toml (requires-python = ">=3.13")
  • .github/workflows/test.yaml is already using python-version: "3.13".
  • No Python 3.13-only syntax (e.g. new pattern-matching constructs) was found in the application code.
  • Python 3.13 was released on October 7, 2024; adoption is growing but not yet universal.

If you rely on new features or performance improvements in 3.13, this requirement is reasonable. Otherwise, consider lowering the bound (for example to 3.11+) to maximize compatibility.

Comment thread application/datamanager/tests/test_main.py
Comment thread pyproject.toml
Comment thread pyproject.toml
@chrisaddy chrisaddy merged commit 5e0c318 into master May 12, 2025
1 of 3 checks passed
@chrisaddy chrisaddy deleted the rebuild branch May 12, 2025 20:18
This was referenced May 13, 2025
This was referenced May 31, 2025
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.

2 participants