Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit acaba56

Browse files
feat: Use uv package manager
1 parent 4a2bb9b commit acaba56

File tree

8 files changed

+2558
-596
lines changed

8 files changed

+2558
-596
lines changed

Makefile

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ branch = $(shell git branch | grep \* | cut -f2 -d' ')
77
epoch := $(shell date +"%s")
88
AR_REPO ?= codecov/api
99
DOCKERHUB_REPO ?= codecov/self-hosted-api
10-
REQUIREMENTS_TAG := requirements-v1-$(shell sha1sum requirements.txt | cut -d ' ' -f 1)-$(shell sha1sum docker/Dockerfile.requirements | cut -d ' ' -f 1)
10+
REQUIREMENTS_TAG := requirements-v1-$(shell sha1sum uv.lock | cut -d ' ' -f 1)-$(shell sha1sum docker/Dockerfile.requirements | cut -d ' ' -f 1)
1111
VERSION := release-${sha}
1212
CODECOV_UPLOAD_TOKEN ?= "notset"
1313
CODECOV_STATIC_TOKEN ?= "notset"
@@ -21,7 +21,7 @@ API_DOMAIN ?= api
2121
PROXY_NETWORK ?= api_default
2222

2323
# Codecov CLI version to use
24-
CODECOV_CLI_VERSION := 0.5.1
24+
CODECOV_CLI_VERSION := 9.0.4
2525

2626
build:
2727
make build.requirements
@@ -31,13 +31,13 @@ check-for-migration-conflicts:
3131
python manage.py check_for_migration_conflicts
3232

3333
test:
34-
COVERAGE_CORE=sysmon python -m pytest --cov=./ --junitxml=junit.xml -o junit_family=legacy
34+
COVERAGE_CORE=sysmon pytest --cov=./ --junitxml=junit.xml -o junit_family=legacy
3535

3636
test.unit:
37-
COVERAGE_CORE=sysmon python -m pytest --cov=./ -m "not integration" --cov-report=xml:unit.coverage.xml --junitxml=unit.junit.xml -o junit_family=legacy
37+
COVERAGE_CORE=sysmon pytest --cov=./ -m "not integration" --cov-report=xml:unit.coverage.xml --junitxml=unit.junit.xml -o junit_family=legacy
3838

3939
test.integration:
40-
COVERAGE_CORE=sysmon python -m pytest --cov=./ -m "integration" --cov-report=xml:integration.coverage.xml --junitxml=integration.junit.xml -o junit_family=legacy
40+
COVERAGE_CORE=sysmon pytest --cov=./ -m "integration" --cov-report=xml:integration.coverage.xml --junitxml=integration.junit.xml -o junit_family=legacy
4141

4242
lint:
4343
make lint.install
@@ -179,17 +179,17 @@ push.self-hosted-rolling:
179179
docker push ${DOCKERHUB_REPO}:rolling
180180

181181
shell:
182-
docker-compose exec api bash
182+
docker compose exec api bash
183183

184184
test_env.up:
185185
env | grep GITHUB > .testenv; true
186-
TIMESERIES_ENABLED=${TIMESERIES_ENABLED} docker-compose up -d
186+
TIMESERIES_ENABLED=${TIMESERIES_ENABLED} docker compose up -d
187187

188188
test_env.prepare:
189-
docker-compose exec api make test_env.container_prepare
189+
docker compose exec api make test_env.container_prepare
190190

191191
test_env.check_db:
192-
docker-compose exec api make test_env.container_check_db
192+
docker compose exec api make test_env.container_check_db
193193
make test_env.check-for-migration-conflicts
194194

195195
test_env.install_cli:
@@ -205,18 +205,18 @@ test_env.container_check_db:
205205
while ! nc -vz timescale 5432; do sleep 1; echo "waiting for timescale"; done
206206

207207
test_env.run_unit:
208-
docker-compose exec api make test.unit
208+
docker compose exec api make test.unit
209209

210210
test_env.run_integration:
211-
#docker-compose exec api make test.integration
211+
#docker compose exec api make test.integration
212212
echo "Skipping. No Tests"
213213

214214
test_env.check-for-migration-conflicts:
215-
docker-compose exec api python manage.py check_for_migration_conflicts
215+
docker compose exec api python manage.py check_for_migration_conflicts
216216

217217
test_env.upload:
218-
docker-compose exec api make test_env.container_upload CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
219-
docker-compose exec api make test_env.container_upload_test_results CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
218+
docker compose exec api make test_env.container_upload CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
219+
docker compose exec api make test_env.container_upload_test_results CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
220220

221221
test_env.container_upload:
222222
codecovcli -u ${CODECOV_URL} upload-process --flag unit-latest-uploader --flag unit \
@@ -229,13 +229,13 @@ test_env.container_upload_test_results:
229229
--files-search-exclude-folder=api/internal/tests/unit/views/cassetes/** || true
230230

231231
test_env.static_analysis:
232-
docker-compose exec api make test_env.container_static_analysis CODECOV_STATIC_TOKEN=${CODECOV_STATIC_TOKEN}
232+
docker compose exec api make test_env.container_static_analysis CODECOV_STATIC_TOKEN=${CODECOV_STATIC_TOKEN}
233233

234234
test_env.label_analysis:
235-
docker-compose exec api make test_env.container_label_analysis CODECOV_STATIC_TOKEN=${CODECOV_STATIC_TOKEN}
235+
docker compose exec api make test_env.container_label_analysis CODECOV_STATIC_TOKEN=${CODECOV_STATIC_TOKEN}
236236

237237
test_env.ats:
238-
docker-compose exec api make test_env.container_ats CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN}
238+
docker compose exec api make test_env.container_ats CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN}
239239

240240
test_env.container_static_analysis:
241241
codecovcli -u ${CODECOV_URL} static-analysis --token=${CODECOV_STATIC_TOKEN}

docker-compose.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
version: "3"
2-
31
services:
42
api:
53
image: ${API_DOCKER_REPO}:${API_DOCKER_VERSION}
@@ -17,11 +15,11 @@ services:
1715
- SETUP__TIMESERIES__ENABLED=${TIMESERIES_ENABLED-true}
1816
# Improves pytest-cov performance in python 3.12
1917
# https://github.com/nedbat/coveragepy/issues/1665#issuecomment-1937075835
20-
- COVERAGE_CORE=sysmon
18+
- COVERAGE_CORE=sysmon
2119
env_file:
2220
- .testenv
2321
postgres:
24-
image: postgres:14.7-alpine
22+
image: postgres:14-alpine
2523
environment:
2624
- POSTGRES_USER=postgres
2725
- POSTGRES_HOST_AUTH_METHOD=trust
@@ -32,7 +30,7 @@ services:
3230
tmpfs:
3331
size: 2048M
3432
timescale:
35-
image: timescale/timescaledb-ha:pg14-latest
33+
image: timescale/timescaledb:latest-pg14
3634
environment:
3735
- POSTGRES_USER=postgres
3836
- POSTGRES_HOST_AUTH_METHOD=trust
@@ -44,4 +42,3 @@ services:
4442
size: 2048M
4543
redis:
4644
image: redis:6-alpine
47-

docker/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ ARG BERGLAS_VERSION=2.0.6
66
FROM us-docker.pkg.dev/berglas/berglas/berglas:$BERGLAS_VERSION as berglas
77

88
FROM $REQUIREMENTS_IMAGE as app
9-
COPY . /app
109
WORKDIR /app
11-
RUN pip install setuptools==71.1.0
10+
ADD . /app
1211
RUN python manage.py collectstatic --no-input
1312

1413
FROM app as local
@@ -57,6 +56,7 @@ FROM self-hosted as self-hosted-runtime
5756
USER root
5857
ARG EXTERNAL_DEPS_FOLDER=./external_deps
5958
RUN mkdir $EXTERNAL_DEPS_FOLDER
59+
# TODO - replace the pip install here?
6060
RUN pip install --target $EXTERNAL_DEPS_FOLDER psycopg2-binary tlslite-ng
6161
RUN chown codecov:application $EXTERNAL_DEPS_FOLDER
6262
USER codecov

docker/Dockerfile.requirements

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,62 @@
11
# syntax=docker/dockerfile:1.4
2-
ARG PYTHON_IMAGE=python:3.12-slim-bookworm
2+
ARG PYTHON_IMAGE=ghcr.io/astral-sh/uv:python3.12-bookworm-slim
33

44
# BUILD STAGE - Download dependencies from GitHub that require SSH access
55
FROM $PYTHON_IMAGE as build
66

77
RUN apt-get update
88
RUN apt-get install -y \
99
build-essential \
10+
git \
1011
libffi-dev \
1112
libpq-dev \
1213
curl
1314

14-
COPY requirements.txt /
15-
WORKDIR /pip-packages/
16-
RUN pip wheel -r /requirements.txt
17-
RUN rm -rf /pip-packages/src
15+
ENV UV_LINK_MODE=copy \
16+
UV_COMPILE_BYTECODE=1 \
17+
UV_PYTHON_DOWNLOADS=never \
18+
UV_PYTHON=python \
19+
UV_PROJECT_ENVIRONMENT=/worker
20+
21+
# Then, add the rest of the project source code and install it
22+
# Installing separately from its dependencies allows optimal layer caching
23+
RUN --mount=type=cache,target=/root/.cache/uv \
24+
--mount=type=bind,source=uv.lock,target=uv.lock \
25+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
26+
uv sync --frozen
27+
28+
RUN --mount=type=cache,target=/root/.cache/uv \
29+
--mount=type=bind,source=uv.lock,target=uv.lock \
30+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
31+
uv export --no-hashes --frozen --format requirements-txt > requirements.txt
32+
33+
RUN grep -v '^-e ' requirements.txt > requirements.remote.txt
34+
35+
# build all remote wheels
36+
RUN pip wheel -w wheels --find-links wheels -r requirements.remote.txt
37+
38+
# build all local packages to wheels
39+
RUN --mount=type=cache,target=/root/.cache/uv \
40+
--mount=type=bind,source=uv.lock,target=uv.lock \
41+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
42+
uv build --all-packages --wheel -o wheels
1843

1944
# RUNTIME STAGE - Copy packages from build stage and install runtime dependencies
2045
FROM $PYTHON_IMAGE
2146

2247
# Our postgres driver psycopg2 requires libpq-dev as a runtime dependency
2348
RUN apt-get update
2449
RUN apt-get install -y \
50+
git \
2551
libpq-dev \
2652
make \
2753
curl \
2854
libexpat1 \
2955
&& pip install --upgrade pip
3056

31-
WORKDIR /pip-packages/
32-
COPY --from=build /pip-packages/ /pip-packages/
57+
COPY --from=build /wheels/ /wheels/
3358

34-
RUN pip install --no-deps --no-index --find-links=/pip-packages/ /pip-packages/*
59+
RUN --mount=type=cache,target=/root/.cache/uv \
60+
--mount=type=bind,source=uv.lock,target=uv.lock \
61+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
62+
uv pip install --no-deps --no-index --find-links=wheels wheels/* --system

pyproject.toml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
[project]
2+
name = "api"
3+
version = "0.1.0"
4+
description = "Codecov's API layer"
5+
readme = "README.md"
6+
requires-python = ">=3.12"
7+
dependencies = [
8+
"aiodataloader",
9+
"ariadne==0.23",
10+
"ariadne_django==0.3.0",
11+
"celery>=5.3.6",
12+
"cerberus",
13+
"ddtrace",
14+
"Django>=4.2.16",
15+
"django-cors-headers",
16+
"django-csp",
17+
"django-dynamic-fixture",
18+
"django-filter",
19+
"django-model-utils",
20+
"django-postgres-extra>=2.0.8",
21+
"django-prometheus",
22+
"djangorestframework==3.15.2",
23+
"drf-spectacular",
24+
"drf-spectacular-sidecar",
25+
"elastic-apm",
26+
"factory-boy",
27+
"fakeredis",
28+
"freezegun",
29+
"google-cloud-pubsub",
30+
"gunicorn>=22.0.0",
31+
"idna>=3.7",
32+
"minio",
33+
"opentelemetry-instrumentation-django>=0.45b0",
34+
"opentelemetry-sdk>=1.24.0",
35+
"opentracing",
36+
"polars==1.12.0",
37+
"pre-commit",
38+
"psycopg2",
39+
"PyJWT",
40+
"pydantic",
41+
"pytest>=7.2.0",
42+
"pytest-cov",
43+
"pytest-django",
44+
"pytest-mock",
45+
"pytest-asyncio",
46+
"python-dateutil",
47+
"python-json-logger",
48+
"python-redis-lock",
49+
"pytz",
50+
"redis",
51+
"regex",
52+
"requests",
53+
"sentry-sdk>=2.13.0",
54+
"sentry-sdk[celery]",
55+
"setproctitle",
56+
"simplejson",
57+
"starlette==0.40.0",
58+
"stripe>=9.6.0",
59+
"urllib3>=1.26.19",
60+
"vcrpy",
61+
"whitenoise",
62+
"django-autocomplete-light",
63+
"django-better-admin-arrayfield",
64+
"certifi>=2024.07.04",
65+
]
66+
67+
[build-system]
68+
requires = ["setuptools"]
69+
build-backend = "setuptools.build_meta"
70+
71+
[tool.setuptools]
72+
py-modules = []
73+
74+
[tool.uv]
75+
dev-dependencies = [
76+
"factory-boy>=3.3.1",
77+
"freezegun>=1.5.1",
78+
"mock>=5.1.0",
79+
"pre-commit>=4.0.1",
80+
"pytest>=8.3.3",
81+
"pytest-asyncio>=0.24.0",
82+
"pytest-celery>=1.1.3",
83+
"pytest-cov>=6.0.0",
84+
"pytest-django>=4.9.0",
85+
"pytest-freezegun>=0.4.2",
86+
"pytest-mock>=3.14.0",
87+
"pytest-sqlalchemy>=0.2.1",
88+
"respx>=0.21.1",
89+
"sqlalchemy-utils>=0.41.2",
90+
"time-machine>=2.16.0",
91+
"vcrpy>=6.0.2",
92+
]
93+
94+
95+
[tool.uv.sources]
96+
timestring = { git = "https://github.com/codecov/timestring", rev = "d37ceacc5954dff3b5bd2f887936a98a668dda42" }
97+
test-results-parser = { git = "https://github.com/codecov/test-results-parser", rev = "94ff26cb083a02ff726dd2497c2129e4aaf5f7cd" }
98+
shared = { git = "https://github.com/codecov/shared", rev = "511b553fd19113f1716326b0363b9d9a4afca1d7" }

requirements.in

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)