Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
195 commits
Select commit Hold shift + click to select a range
94d7227
Initial ruff formatting and uv project init
bfoley12 May 28, 2026
3c79379
Added .venv and .env to gitignore
bfoley12 May 28, 2026
4d5c64f
Moved dev optional-dependencies to a dependency group
bfoley12 May 28, 2026
8ebb3f6
Synced lock file
bfoley12 May 28, 2026
98d867f
Example env vars
bfoley12 May 28, 2026
6558bc7
Moved to a src/proj style repo. Began creating fastapi server
bfoley12 May 28, 2026
04da662
Removed project-level uv ennvironment
bfoley12 May 28, 2026
b84f81f
Updated python version to 3.14
bfoley12 Jun 1, 2026
a3624de
Added projects router and reintroduced prefix
bfoley12 Jun 1, 2026
f31519b
Added Beanie init
bfoley12 Jun 1, 2026
4de7efd
Broke redis and kong settings into their own classes for modularity
bfoley12 Jun 1, 2026
48f19a6
Added shared types
bfoley12 Jun 1, 2026
4e44d03
Removed unnecessary files
bfoley12 Jun 1, 2026
c44dc0e
Added packages to uv
bfoley12 Jun 1, 2026
da8d2e5
Built out project domain for getting data
bfoley12 Jun 1, 2026
b130b33
Added shared dependencies for injection
bfoley12 Jun 1, 2026
c3004a0
Added AuthenticationError and GatewayError for more control over thro…
bfoley12 Jun 1, 2026
a5b5849
Ruff formatting and checking
bfoley12 Jun 1, 2026
74ac09f
PrefixedEmail now throws ValidationError instead of ValueError
bfoley12 Jun 1, 2026
6baffad
Changed ProjectResource for ProjectOut for consistency with ProjectIn…
bfoley12 Jun 1, 2026
d761d3a
Changed create_project to insert_project
bfoley12 Jun 1, 2026
bd2dbbb
Added Project patch for partial udpates
bfoley12 Jun 2, 2026
9271c5b
Added Project delete
bfoley12 Jun 2, 2026
0ac8204
Added Projet Upsert (put)
bfoley12 Jun 2, 2026
b8bbb4d
Added docstrings and removed dead code
bfoley12 Jun 2, 2026
617afad
Removed outdated runtime_checkable and awaited async function to get …
bfoley12 Jun 2, 2026
22ad07d
Created a parent class to abstract the handling of fields requested f…
bfoley12 Jun 2, 2026
a4d2330
modified docstrings to match function definition
bfoley12 Jun 2, 2026
5808483
Fixed issue where find_one syntax was used with get
bfoley12 Jun 2, 2026
2998c02
Removed dead ProjectSummary usages
bfoley12 Jun 2, 2026
41dd24b
Automatic projection processing now hanldes dot-paths and validates e…
bfoley12 Jun 2, 2026
95d3398
Initial Contributions route setup
bfoley12 Jun 2, 2026
8053215
Added stub methods
bfoley12 Jun 2, 2026
1d30533
Added base contributions class and ContributionPatch. Contribution no…
bfoley12 Jun 2, 2026
97f01bd
Added settings to Project to name proper collection and prevent nulls…
bfoley12 Jun 2, 2026
a2d31fb
Added contributions router
bfoley12 Jun 2, 2026
191c4c0
Sketched out endpoints and repo methods
bfoley12 Jun 2, 2026
96832e8
Mostly formatting and type checking changes. Added stub files for com…
bfoley12 Jun 3, 2026
25bdc30
Abstracted repository and models
bfoley12 Jun 3, 2026
6392fb2
Implemented classes and methods with new abstractions
bfoley12 Jun 3, 2026
960ab66
Implemented delete_contributions
bfoley12 Jun 3, 2026
de54f47
Added linked-document filtering for contributions
bfoley12 Jun 3, 2026
78f32b2
Anyonymous users can no longer be admin. Fixed imports
bfoley12 Jun 3, 2026
ee75871
Added unit tests
bfoley12 Jun 3, 2026
dbd664d
added check fix for normal fixes
bfoley12 Jun 3, 2026
71aaf9d
Various small fixes in function signatures and usages
bfoley12 Jun 3, 2026
573aeb5
Added integration tests
bfoley12 Jun 3, 2026
0f84dd4
Added test commands to justfile
bfoley12 Jun 3, 2026
8c0060b
Added tests to live dev db
bfoley12 Jun 3, 2026
d7b5b8b
Fixed importing from src
bfoley12 Jun 3, 2026
d3496ab
OpenAPI UI improvement. Added app info and tags to routers
bfoley12 Jun 3, 2026
4333511
Moved more openapi info dicts to _openapi
bfoley12 Jun 4, 2026
2a2d03e
Changed imports so they resolve
bfoley12 Jun 4, 2026
7a8181c
Removed old repo
bfoley12 Jun 4, 2026
0c45e9d
Fixed basedpyright not knowing proper import path. Removed old ignore…
bfoley12 Jun 4, 2026
38b2b14
Removed dependencies. Some temporarily
bfoley12 Jun 4, 2026
f21e781
Reordered deps
bfoley12 Jun 4, 2026
eb2ddf9
fields argument in routers now expects a list instead of comma delimi…
bfoley12 Jun 4, 2026
fb176b4
Fleshed out contribution repo methods
bfoley12 Jun 4, 2026
9d83970
Pulled repeated repo logic into parent class
bfoley12 Jun 4, 2026
792f83a
Changed logging middleware to allow contextvars being passed upwards
bfoley12 Jun 4, 2026
870456a
basedpyright ignores tests
bfoley12 Jun 4, 2026
ba08993
Infra changes for rewrite
bfoley12 Jun 4, 2026
c7d7bcf
Added healthcheck endpoint
bfoley12 Jun 4, 2026
5991392
Forward username and is_admin values for logging
bfoley12 Jun 5, 2026
eac368f
Convert ids coming into Contributions to PydanticObjectIds
bfoley12 Jun 5, 2026
d77cf4b
Fleshed out Contribution component models
bfoley12 Jun 5, 2026
7a5dbf8
Init component models
bfoley12 Jun 5, 2026
9a96716
Bulk upload of contributions with components now bulk inserts compone…
bfoley12 Jun 5, 2026
4d860f9
Made component repositories to pull insert logic out of contributions…
bfoley12 Jun 5, 2026
7435e7d
Moved cross-repo insert logic into service layer
bfoley12 Jun 5, 2026
ca962a4
Documents now handle decoding cursor to accomodate differing id types…
bfoley12 Jun 6, 2026
4bb92e2
Added docstrings
bfoley12 Jun 6, 2026
8276016
Inserting many contributions now uses multi-document transactions rat…
bfoley12 Jun 8, 2026
3725643
upsert_contributions uses semaphore
bfoley12 Jun 8, 2026
610ca6d
Added project_identifier index on ContributionsBase
bfoley12 Jun 8, 2026
9ab2a6a
clamp max_concurrent_transactions
bfoley12 Jun 8, 2026
d63edcb
Atomically upsert a contribution by identifiers rather than _id
bfoley12 Jun 8, 2026
2bce5ed
Contributions delete children on bulk delete
bfoley12 Jun 9, 2026
d3c8bf0
Deleting contribution by id deletes all children
bfoley12 Jun 9, 2026
6d6b4ed
Further parameterized the AsyncMongoClient
bfoley12 Jun 9, 2026
24fa834
Fixed spacing issues
bfoley12 Jun 9, 2026
8f965d0
Added table routes
bfoley12 Jun 9, 2026
c979f3d
Moved types to shared domains
bfoley12 Jun 9, 2026
ddb8b7f
Removed unused import
bfoley12 Jun 9, 2026
fa456ad
Added session to delete_by_id and made a DeleteResponse model
bfoley12 Jun 10, 2026
93d60e0
Fleshed out basic CRUD operations for Tables
bfoley12 Jun 10, 2026
b6278e0
Added missing update to patch endpoint
bfoley12 Jun 10, 2026
be8b7fd
Added missing colon in patch function def
bfoley12 Jun 10, 2026
b1977f8
Fleshed out streaming download to user with compression
bfoley12 Jun 10, 2026
f199f9f
Removed unused response paramter from download_table
bfoley12 Jun 10, 2026
dc8e53b
Added shared repository for components
bfoley12 Jun 10, 2026
2572d1d
Added Structures endpoint and refatored to use shared components repo
bfoley12 Jun 10, 2026
7277a99
Added Attachments endpoint
bfoley12 Jun 10, 2026
dd91fbc
Removed get and patch capabilities from attachment endpoint
bfoley12 Jun 10, 2026
b6c9753
Removed logic for inserting attachments during contribution insert
bfoley12 Jun 10, 2026
8cb3422
Moved _children to a property
bfoley12 Jun 10, 2026
3fb7e01
Added attachments, structures, and tables routers to main router
bfoley12 Jun 11, 2026
c844e0a
Made PolarsFrame type to handle coercion and serialization
bfoley12 Jun 11, 2026
4f7b57d
Removed 'components' tag from components routers
bfoley12 Jun 11, 2026
b776d2d
Added additional logging context to each request
bfoley12 Jun 11, 2026
73e5acf
Removed unused gateway secret check
bfoley12 Jun 11, 2026
724698a
Moved router tagging to the api router
bfoley12 Jun 11, 2026
c126522
Updated tests to account for new code
bfoley12 Jun 11, 2026
75d4bdb
Changed exception handling and modified variable names to be descript…
bfoley12 Jun 11, 2026
a934bdd
Removed old settings reference and scoped contribution access to proj…
bfoley12 Jun 11, 2026
79ef63f
DeleteResponse now consumes a DeleteResult to allow for easier expans…
bfoley12 Jun 11, 2026
93e6bf4
Removed vestigial GatewayError references
bfoley12 Jun 11, 2026
946e2e7
Contribution.data validation for depth <= 7
bfoley12 Jun 11, 2026
210b0e1
Disallow lists in Contribution.data
bfoley12 Jun 11, 2026
cb9b506
Added more validation to Contribution.data dict
bfoley12 Jun 11, 2026
39c032f
Removed useless thin wrapper method
bfoley12 Jun 12, 2026
3e21a4d
Inserting many components now validates by md5 hash and returns docum…
bfoley12 Jun 12, 2026
f415323
Component.insert_component delegates to insert_components
bfoley12 Jun 12, 2026
e92977f
Attachments document model now verifies extension of file. Modified i…
bfoley12 Jun 12, 2026
7e359ea
Greatly expanded unit testing
bfoley12 Jun 12, 2026
0413425
Fixed domain routers not prefixing '/'
bfoley12 Jun 12, 2026
d89e40c
Added more thorough integration test coverage
bfoley12 Jun 12, 2026
86ba711
Moved download logic to base shared repository
bfoley12 Jun 15, 2026
8e83e65
Added csv serialization for downloads
bfoley12 Jun 15, 2026
26d0398
Added tests to cover downloads
bfoley12 Jun 15, 2026
12340a6
Fixed gzip missing final packet; improved CSV serialization; improved…
bfoley12 Jun 15, 2026
381353a
Moved DataFormat decision to a match statement
bfoley12 Jun 15, 2026
ddcd41f
Removed module-level docstrings
bfoley12 Jun 15, 2026
b41a420
Setup app to use aioboto3 and load defaults from env
bfoley12 Jun 15, 2026
0264d35
Added dependencies for boto and S3
bfoley12 Jun 16, 2026
a69e64d
Changed filename to authz to clarify that it is authorization
bfoley12 Jun 16, 2026
bfb32c9
Added S3Dep and s3 reliance to download methods; modified auth import…
bfoley12 Jun 16, 2026
d4129b4
Updated auth import to authz
bfoley12 Jun 16, 2026
937be7d
Uncommented kong in settings
bfoley12 Jun 16, 2026
453845c
Modified S3Dep to return the client rather than a generator; moved ke…
bfoley12 Jun 16, 2026
2249c68
Removed kong settings, since they are unused
bfoley12 Jun 17, 2026
6906556
Made a shared ComponentService to ensure deletion only occurs when no…
bfoley12 Jun 17, 2026
6604e55
Added .claude/ to gitignore
bfoley12 Jun 17, 2026
79fd99c
Moved component repo and service logic into a shared service. Compone…
bfoley12 Jun 17, 2026
d2ca35c
Added download tests, removed config test raising on creating Setting…
bfoley12 Jun 17, 2026
5f75cf3
Reverted non-API changes to master versions
bfoley12 Jun 17, 2026
d79ac6f
upgrade dependencies for deployment
invalid-email-address Jun 2, 2026
fa4886c
Infra changes for rewrite
bfoley12 Jun 4, 2026
a5d543b
Stop tracking .claude/ directory
bfoley12 Jun 17, 2026
24d7b5d
Revert changes to deployment of other submodules
bfoley12 Jun 17, 2026
e9e1074
Switched to standard docker image. Allows decoupling python versions …
bfoley12 Jun 18, 2026
0ebd99c
Improved OTel instrumentation. Removed ddtrace references
bfoley12 Jun 18, 2026
53ed677
Fixed uv build wheel building from old directory style
bfoley12 Jun 18, 2026
f7fbff0
Added dependencies to routes that require users to be logged in
bfoley12 Jun 18, 2026
e48eb19
Requests to contributions or their components are now scoped by the u…
bfoley12 Jun 18, 2026
2077a49
Enforce contribution-scoped components at service level
bfoley12 Jun 18, 2026
fa292e1
Convert id str to objectid
bfoley12 Jun 18, 2026
7d617ef
Readded start_rq so supervisord doesnt fail
bfoley12 Jun 18, 2026
8c162ed
Moved kwargs to new spec
bfoley12 Jun 18, 2026
8cc2c23
Changed example kwargs to new specs
bfoley12 Jun 18, 2026
3acff74
Added back n start_rq.sh so build succeeds
bfoley12 Jun 18, 2026
48dce53
Added lines to ignore build artifacts
bfoley12 Jun 18, 2026
0280950
Modernized claude.md
bfoley12 Jun 18, 2026
23494a1
Pointed setuptools at the right repo - src
bfoley12 Jun 18, 2026
0862484
Added and fixed tests
bfoley12 Jun 18, 2026
0521e7c
Formatting
bfoley12 Jun 18, 2026
507c11e
Removing accidental commit of build artifacts
bfoley12 Jun 18, 2026
afbbee1
Unified deletion behavior by moving BaseDocumentWithInput to inherit …
bfoley12 Jun 18, 2026
19df929
Upsert now functions like bulk insert, allowing upserts to fail and r…
bfoley12 Jun 18, 2026
09c6a25
Improved sensitivity of dict key validation
bfoley12 Jun 18, 2026
4a48ef7
Simplified md5 check and improved patch_component_by_id
bfoley12 Jun 18, 2026
cb90bc7
Added a constant for how to handle encoding of polars.DataFrames to h…
bfoley12 Jun 18, 2026
1c7a420
Improved dataframe handling to read and write dataframes
bfoley12 Jun 18, 2026
57d906a
Made ComponentIn to clarify and unify input schema from storage schema
bfoley12 Jun 18, 2026
7992612
Modified tests to account for new handling
bfoley12 Jun 18, 2026
408b6a6
Added ty for typechecking
bfoley12 Jun 22, 2026
90eaca5
Removed ty - not mature enough
bfoley12 Jun 22, 2026
0d122bc
Changed docstring, imports, and added polars dep
bfoley12 Jun 22, 2026
10ce393
Commented out unused dependencies
bfoley12 Jun 23, 2026
dbb8c28
Added custom Access logging in line with previous format.
bfoley12 Jun 24, 2026
17e67f7
pass exc_info through to logger on upsert error
bfoley12 Jun 24, 2026
dd257b3
Added log_level to errors
bfoley12 Jun 24, 2026
0cf8e8f
Moved healthcheck router to healthcheck instead of health
bfoley12 Jun 24, 2026
e1096e5
Added 'version' to healthcheck for backwards compat
bfoley12 Jun 24, 2026
cb5d299
Added user to contribution service and threaded user into repo to che…
bfoley12 Jun 25, 2026
ad1eb94
Added tests for user-contribution validation and modified healthcheck…
bfoley12 Jun 25, 2026
a072a8a
Brought user group checking logic onto user
bfoley12 Jun 25, 2026
d87458b
Added redirects for old endpoints to their corresponding new ones, an…
bfoley12 Jun 25, 2026
87d018b
Added libsnappy back for snappy compression
bfoley12 Jun 25, 2026
7df8e04
Added supervisor and python-snappy to deps
bfoley12 Jun 25, 2026
5f400e4
Made the uv sync no-editable so .pth doesn't cause an error referenci…
bfoley12 Jun 25, 2026
7d91699
Added --workers parameterization
bfoley12 Jun 25, 2026
a6774b8
Brought supervisor up to current use practices
bfoley12 Jun 25, 2026
de403ee
Moved log headers into access log specification to avoid duplication …
bfoley12 Jun 25, 2026
4359ee8
Added jinja2 back to dependencies and sorted deps
bfoley12 Jun 26, 2026
016546b
Build uv venv outside of app so dependencies load properly
bfoley12 Jun 26, 2026
05811ea
Fixed env var names to match new format
bfoley12 Jun 26, 2026
7aee18e
Added shared BaseFilter to convert from Beanie's aliased 'id' to real…
bfoley12 Jun 29, 2026
8257384
Pagination cursor pads b64 encoded cursor to safely decode
bfoley12 Jun 29, 2026
b899b94
Removed response_model from router 'get_*' methods since that would o…
bfoley12 Jun 29, 2026
2c5cedb
Contributions are now versioned. The server derives integer versions …
bfoley12 Jun 30, 2026
8d29dab
Added model and router to expose limits that well-behaved clients sho…
bfoley12 Jul 1, 2026
ddac7eb
Added custom exceptions and middleware to immediately detect oversize…
bfoley12 Jul 1, 2026
88c6f54
Implementing limits endpoint, new exceptions & middleware, and added …
bfoley12 Jul 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ coverage.xml
mpcontribs-api/supervisord.conf
mpcontribs-portal/supervisord.conf
**/.DS_Store
.venv/
.env
.claude/
11 changes: 11 additions & 0 deletions mpcontribs-api/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
MPCONTRIBS_ENVIRONMENT=dev

MPCONTRIBS_MONGO__URI=mongodb+srv://<db_username>:<db_password>@host.hash.mongodb.net/?appName=database-name
MPCONTRIBS_MONGO__DB_NAME=database-name

MPCONTRIBS_REDIS__ADDRESS=redis-address # placeholder; not used yet
MPCONTRIBS_REDIS__URL=redis-url

MPCONTRIBS_MAIL_DEFAULT_SENDER=mail-default-sender # placeholder; not used yet

MPCONTRIBS_VERSION=version
2 changes: 2 additions & 0 deletions mpcontribs-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build/
dist/
88 changes: 88 additions & 0 deletions mpcontribs-api/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

This is a complete rewrite of the MPContribs API server.
The core of the package is FastAPI, Pydantic, and Beanie.
Developer experience and process efficiency are top priorities.

## Commands

```bash
# Format, fix, and lint (preferred)
just fmt

# Run tests
uv run pytest

# Run tests by marker
uv run pytest -m base
uv run pytest -m extra

# Run tests in parallel
uv run pytest -n auto

# Type check
uv run basedpyright
```

## Environment

Copy `.env.example` to `.env`. Key variables (all prefixed `MPCONTRIBS_`):

- `MONGO__URI` — MongoDB Atlas URI
- `MONGO__DB_NAME` — database name
- `ENVIRONMENT` — `dev` or `prod` (controls log format and debug mode)

## Architecture

### Domain structure

Each resource lives in `src/mpcontribs_api/domains/<resource>/` with four files:

- `models.py` — Beanie `Document` subclass (DB model) + Pydantic output/input/patch/filter models
- `repository.py` — `MongoDb<Resource>Repository` encapsulating all database access
- `router.py` — `APIRouter` with CRUD endpoint handlers
- `dependencies.py` — `<Resource>Dep` type alias (`Annotated[MongoDb<Resource>Repository, Depends(...)]`)

Routers are registered in `src/mpcontribs_api/api/v1/router.py`.

### Authentication and authorization

Kong injects user identity via headers; `dependencies.get_user` parses them into a frozen `User` model (`authz.py`). The dependency chain is:

- `UserDep` — any caller (anonymous or authenticated)
- `AuthedDep` / `require_user` — requires an authenticated user (raises 401 otherwise)
- `require_role(role)` — factory returning a dependency that requires a specific group membership

All mutating endpoints (POST/PUT/PATCH/DELETE) depend on `require_user`, so anonymous callers get 401; read endpoints (GET) stay open and rely on scope to filter results.

All database access goes through a repository instantiated with the current `User`. The repository's `_scope` dict is injected into every MongoDB query automatically:

- **Admins** (members of `mongo.admin_group`): no filter applied
- **Authenticated users**: see public+approved data, own resources (`owner == username`), and group resources
- **Anonymous**: public + approved only

Components (structures/tables/attachments) have no access field of their own; their reads and deletes are gated by whether an in-scope contribution references them (see `ContributionService`/`ComponentService`).

**Trust boundary:** the service is only reachable through Kong, which terminates auth and sets the identity headers. There is no in-app gateway-secret check today — the deployment network is the boundary, so the identity headers are trusted. If the service is ever exposed off the Kong path, add a gateway-secret (or mTLS) check before trusting those headers.

### Repository pattern

Repositories take a `User` at construction time and expose typed async methods (`get_*`, `insert_*`, `patch_*`, `upsert_*`, `delete_*`). They never leak the scope logic to routers — routers only call repository methods.

### Sparse field selection

The `_fields` query parameter (handled in `projection.py`) lets callers request specific fields (comma-separated, dotted for nesting). `SparseFieldsModel` dynamically creates a trimmed Pydantic model via `create_model()` and converts field paths to MongoDB projection syntax. Results are cached with `@lru_cache`.

### Cursor-based pagination

`Page[T]` in `pagination.py` contains `items` and a `next_cursor` (base64-encoded last item ID). Pagination is forward-only and stateless. Default page size is 20; max is 100.

### Exception hierarchy

`exceptions.py` defines `AppError` subclasses (`NotFoundError`, `ConflictError`, `ValidationError`, `AuthenticationError`, `PermissionError`). All carry `status_code`, `error_code`, `message`, and a `context` dict. Handlers in `app.py` convert them to a uniform JSON shape; internal context is logged but not sent to clients.

### Observability

`logging.py` configures structlog with per-request context vars (request_id, method, path, consumer_id) bound by the middleware in `middleware.py`. OpenTelemetry traces are exported via OTLP/gRPC and trace/span IDs are injected into every log line.
55 changes: 20 additions & 35 deletions mpcontribs-api/Dockerfile

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Switch from pip building to uv.
!! Needs further verification

Original file line number Diff line number Diff line change
@@ -1,58 +1,43 @@
FROM materialsproject/devops:python-3.1113.4 AS base
RUN apt-get update && apt-get install -y --no-install-recommends supervisor libopenblas-dev libpq-dev vim && apt-get clean
# FROM materialsproject/devops:python-3.1113.4 AS base
FROM python:3.14-slim AS base

@bfoley12 bfoley12 Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I moved off of the shared base image here. There are definitely both pros and cons (below), and I have to test a full build still.
Pros:

  1. UV uses a lockfile and doesn't need to rely on manually finding and building binaries - this seems to be the main benefit of the shared image (scipy, matplotlib, etc.)
  2. Allows each portion of the stack to upgrade python independently (we don't have to hold back one piece until we build a shared image and force every upgrade at once)

Cons:

  1. If we have truly shared logic, we will have duplication, or revert to a shared image
  2. If the underlying default image changes, we would silently change as well

RUN apt-get update && apt-get install -y --no-install-recommends supervisor libopenblas-dev vim && apt-get clean
WORKDIR /app

FROM base AS builder
RUN apt-get update && apt-get install -y --no-install-recommends gcc git g++ libsnappy-dev wget liblapack-dev && apt-get clean
ENV PIP_FLAGS "--no-cache-dir --compile"
COPY requirements/deployment.txt ./requirements.txt
RUN pip install $PIP_FLAGS -r requirements.txt
COPY pyproject.toml .
COPY mpcontribs mpcontribs
RUN apt-get update && apt-get install -y --no-install-recommends gcc git g++ wget liblapack-dev libsnappy-dev && apt-get clean
RUN pip install uv
# Build the venv OUTSIDE /app: docker-compose bind-mounts the host source over
# /app for live reload, which would mask a /app/.venv and leave `python` falling
# back to the system interpreter (missing deps)
ENV UV_PROJECT_ENVIRONMENT=/opt/venv
COPY pyproject.toml uv.lock ./
COPY src src
ARG CONTRIBS_VERSION
RUN SETUPTOOLS_SCM_PRETEND_VERSION=${CONTRIBS_VERSION} pip install $PIP_FLAGS --no-deps .
#ENV SETUPTOOLS_SCM_PRETEND_VERSION 0.0.0
#COPY marshmallow-mongoengine marshmallow-mongoengine
#RUN cd marshmallow-mongoengine && pip install $PIP_FLAGS --no-deps -e .
#COPY mimerender mimerender
#RUN cd mimerender && pip install $PIP_FLAGS --no-deps -e .
#COPY flask-mongorest flask-mongorest
#RUN cd flask-mongorest && pip install $PIP_FLAGS --no-deps -e .
#COPY AtlasQ AtlasQ
#RUN cd AtlasQ && pip install $PIP_FLAGS --no-deps -e .
RUN SETUPTOOLS_SCM_PRETEND_VERSION=${CONTRIBS_VERSION} uv sync --frozen --no-dev --no-editable
RUN wget -q https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh && \
chmod +x wait-for-it.sh && mv wait-for-it.sh /usr/local/bin/ && \
wget -q https://github.com/materialsproject/MPContribs/blob/master/mpcontribs-api/mpcontribs/api/contributions/formulae.json.gz?raw=true \
-O mpcontribs/api/contributions/formulae.json.gz
Comment on lines -25 to -26

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

reason for removing the formulae file?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

The file seemed to just function as an id-to-formula translation. I made formulas required when POSTing.

If we want that moved back to optional and filled in automatically, I think I'd prefer actively fetching the formula over keeping it in a data file that we track in git. That would mean an extra query to mongo, and reaching into the nextgen database, but I feel that it is more reactive and resilient that way.

chmod +x wait-for-it.sh && mv wait-for-it.sh /usr/local/bin/

FROM base
ARG BUILDARCH
ENV BUILDARCH=x86_64
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /usr/lib/$BUILDARCH-linux-gnu/libsnappy* /usr/lib/$BUILDARCH-linux-gnu/
ARG BUILDARCH=aarch64
COPY --from=builder /opt/venv /opt/venv
COPY --from=builder /usr/local/bin/wait-for-it.sh /usr/local/bin/

COPY --from=builder /app/mpcontribs/api /app/mpcontribs/api
WORKDIR /app
RUN mkdir -p /var/log/supervisor

COPY supervisord supervisord
COPY scripts scripts
COPY main.py .
COPY maintenance.py .
COPY docker-entrypoint.sh .
COPY gunicorn.conf.py .
RUN chmod +x main.py scripts/start.sh scripts/start_rq.sh docker-entrypoint.sh

ARG VERSION
ENV DD_SERVICE=contribs-apis \
DD_ENV=prod \
DD_VERSION=$VERSION \
DD_TRACE_HOST=localhost:8126 \
DD_TRACE_OTEL_ENABLED=false \
DD_MAIN_PACKAGE=mpcontribs-api
# Telemetry (traces/metrics/logs) is emitted via OTLP to the Datadog Agent's OTLP receiver; the
# endpoint and other OTEL settings are configured per-environment in supervisord.conf.jinja
# (MPCONTRIBS_OTEL__*). No Datadog-specific app config lives here.
ENV PATH="/opt/venv/bin:$PATH"

LABEL com.datadoghq.ad.logs='[{"source": "gunicorn", "service": "contribs-apis"}]'
EXPOSE 10000 10002 10003 10005 20000
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["/usr/bin/supervisord", "-c", "supervisord.conf"]
16 changes: 0 additions & 16 deletions mpcontribs-api/gunicorn.conf.py

This file was deleted.

20 changes: 20 additions & 0 deletions mpcontribs-api/justfile

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Convenient command runner

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Run the dev server (auto-reloads on file changes)
dev:
uv run fastapi dev src/mpcontribs_api/app.py

# Format, fix, and lint all source code
fmt:
uv run ruff format
-uv run ruff check --fix
-uv run ruff check --fix --unsafe-fixes
-uv run pydocstringformatter --write

test suite="all":
#!/usr/bin/env bash
case "{{suite}}" in
all|a) uv run pytest tests/ ;;
integration|i) uv run pytest tests/integration/ -m "not db" ;;
unit|u) uv run pytest tests/unit/ ;;
db|d) uv run pytest tests/integration/db/ -m db ;;
*) echo "unknown suite '{{suite}}' — use: all/a, integration/i, unit/u, db/d" && exit 1 ;;
esac
8 changes: 4 additions & 4 deletions mpcontribs-api/main.py

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Ruff formatting

Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#!/usr/bin/env python
import os
import requests
import boto3
import logging
import os

import boto3
import requests
from supervisor.options import ClientOptions
from supervisor.supervisorctl import Controller

logger = logging.getLogger(__name__)
client = boto3.client('ecs')
client = boto3.client("ecs")


def start(program):
Expand Down
41 changes: 0 additions & 41 deletions mpcontribs-api/maintenance.py

This file was deleted.

Loading