Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try using uv for worker #896

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
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
22 changes: 2 additions & 20 deletions .envrc
Original file line number Diff line number Diff line change
@@ -1,20 +1,2 @@
#!/bin/bash
# shellcheck disable=SC1091

if [ ! -d .venv ]; then
echo "warning: creating virtualenv for the first time"
if which pyenv > /dev/null; then
eval "$(pyenv init -)"
pyenv install -s
else
echo "warning: pyenv not installed, using python3 and hoping for the best"
fi

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install ruff
else
source .venv/bin/activate
unset PS1
fi
uv sync
source .venv/bin/activate
26 changes: 13 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ epoch := $(shell date +"%s")

AR_REPO ?= codecov/worker
DOCKERHUB_REPO ?= codecov/self-hosted-worker
REQUIREMENTS_TAG := requirements-v1-$(shell sha1sum requirements.txt | cut -d ' ' -f 1)-$(shell sha1sum docker/Dockerfile.requirements | cut -d ' ' -f 1)
REQUIREMENTS_TAG := requirements-v1-$(shell sha1sum uv.lock | cut -d ' ' -f 1)-$(shell sha1sum docker/Dockerfile.requirements | cut -d ' ' -f 1)
VERSION := release-${sha}
CODECOV_UPLOAD_TOKEN ?= "notset"
CODECOV_STATIC_TOKEN ?= "notset"
@@ -22,7 +22,7 @@ export WORKER_DOCKER_VERSION=${VERSION}
export CODECOV_TOKEN=${CODECOV_UPLOAD_TOKEN}

# Codecov CLI version to use
CODECOV_CLI_VERSION := 0.5.1
CODECOV_CLI_VERSION := 9.0.4

build:
$(MAKE) build.requirements
@@ -48,13 +48,13 @@ lint:
make lint.run

test:
COVERAGE_CORE=sysmon python -m pytest --cov=./ --junitxml=junit.xml
COVERAGE_CORE=sysmon pytest --cov=./ --junitxml=junit.xml

test.unit:
COVERAGE_CORE=sysmon python -m pytest --cov=./ -m "not integration" --cov-report=xml:unit.coverage.xml --junitxml=unit.junit.xml
COVERAGE_CORE=sysmon pytest --cov=./ -m "not integration" --cov-report=xml:unit.coverage.xml --junitxml=unit.junit.xml

test.integration:
COVERAGE_CORE=sysmon python -m pytest --cov=./ -m "integration" --cov-report=xml:integration.coverage.xml --junitxml=integration.junit.xml
COVERAGE_CORE=sysmon pytest --cov=./ -m "integration" --cov-report=xml:integration.coverage.xml --junitxml=integration.junit.xml


update-requirements:
@@ -200,17 +200,17 @@ push.self-hosted-rolling:
docker push ${DOCKERHUB_REPO}:rolling

shell:
docker-compose exec worker bash
docker compose exec worker bash

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

test_env.prepare:
docker-compose exec worker make test_env.container_prepare
docker compose exec worker make test_env.container_prepare

test_env.check_db:
docker-compose exec worker make test_env.container_check_db
docker compose exec worker make test_env.container_check_db

test_env.install_cli:
pip install --no-cache-dir codecov-cli==$(CODECOV_CLI_VERSION)
@@ -226,14 +226,14 @@ test_env.container_check_db:
while ! nc -vz timescale 5432; do sleep 1; echo "waiting for timescale"; done

test_env.run_unit:
docker-compose exec worker make test.unit
docker compose exec worker make test.unit

test_env.run_integration:
docker-compose exec worker make test.integration
docker compose exec worker make test.integration

test_env.upload:
docker-compose exec worker make test_env.container_upload CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
docker-compose exec worker make test_env.container_upload_test_results CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
docker compose exec worker make test_env.container_upload CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}
docker compose exec worker make test_env.container_upload_test_results CODECOV_UPLOAD_TOKEN=${CODECOV_UPLOAD_TOKEN} CODECOV_URL=${CODECOV_URL}

test_env.container_upload:
codecovcli -u ${CODECOV_URL} do-upload --flag unit --file unit.coverage.xml --disable-search
2 changes: 1 addition & 1 deletion database/engine.py
Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@ def create_session(self):
timeseries_engine = self.timeseries_engine

class RoutingSession(Session):
def get_bind(self, mapper=None, clause=None):
def get_bind(self, mapper=None, clause=None, **kw):
if mapper is not None and issubclass(
mapper.class_, TimeseriesBaseModel
):
1 change: 1 addition & 0 deletions database/tests/unit/test_engine.py
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@ def test_session_get_bind_timeseries_enabled(self, sqlalchemy_connect_url, mocke
database_url=sqlalchemy_connect_url,
timeseries_database_url=sqlalchemy_connect_url,
)

session = session_factory.create_session()
assert session_factory.main_engine is not None
assert session_factory.timeseries_engine is not None
12 changes: 7 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
version: "3"

services:
worker:
image: ${WORKER_DOCKER_REPO}:${WORKER_DOCKER_VERSION}
depends_on:
- mailhog
- postgres
- redis
- timescale
@@ -20,8 +19,9 @@ services:
command:
- sleep
- infinity

postgres:
image: postgres:14.7-alpine
image: postgres:14-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_HOST_AUTH_METHOD=trust
@@ -31,8 +31,9 @@ services:
target: /var/lib/postgresql/data
tmpfs:
size: 2048M

timescale:
image: timescale/timescaledb-ha:pg14-latest
image: timescale/timescaledb:latest-pg14
environment:
- POSTGRES_USER=postgres
- POSTGRES_HOST_AUTH_METHOD=trust
@@ -42,8 +43,9 @@ services:
target: /var/lib/postgresql/data
tmpfs:
size: 2048M

redis:
image: redis:6-alpine

mailhog:
image: mailhog/mailhog:latest

10 changes: 6 additions & 4 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -5,22 +5,24 @@ ARG BERGLAS_VERSION=2.0.6

FROM us-docker.pkg.dev/berglas/berglas/berglas:$BERGLAS_VERSION as berglas


FROM $REQUIREMENTS_IMAGE as app
COPY . /worker
WORKDIR /worker
RUN pip install setuptools==72.1.0
ADD . /worker
RUN chmod +x worker.sh
ARG RELEASE_VERSION
ENV RELEASE_VERSION=$RELEASE_VERSION
ENTRYPOINT ["./worker.sh"]


FROM app as local


FROM app as cloud
COPY --chmod=755 --from=berglas /bin/berglas /usr/local/bin/berglas


FROM app as self-hosted
RUN pip uninstall -y typing
ENV RUN_ENV="ENTERPRISE"


@@ -33,4 +35,4 @@ RUN chown codecov:application $EXTERNAL_DEPS_FOLDER
USER codecov


FROM ${BUILD_ENV}
FROM ${BUILD_ENV}
52 changes: 38 additions & 14 deletions docker/Dockerfile.requirements
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# syntax=docker/dockerfile:1.4
ARG PYTHON_IMAGE=python:3.12-slim-bookworm
ARG PYTHON_IMAGE=ghcr.io/astral-sh/uv:python3.12-bookworm-slim
# BUILD STAGE
FROM $PYTHON_IMAGE as build

RUN apt-get update
RUN apt-get install -y \
build-essential \
libffi-dev \
libpq-dev \
curl \
git \
libxml2-dev \
libxslt-dev \
curl
libxslt-dev

# Install Rust
ARG RUST_VERSION=stable
@@ -20,27 +19,52 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| bash -s -- -y --profile minimal --default-toolchain $RUST_VERSION
ENV PATH="/root/.cargo/bin:$PATH"

COPY requirements.txt /
WORKDIR /pip-packages/
ENV PYCURL_SSL_LIBRARY=openssl
ENV UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1 \
UV_PYTHON_DOWNLOADS=never \
UV_PYTHON=python \
UV_PROJECT_ENVIRONMENT=/worker

# Then, add the rest of the project source code and install it
# Installing separately from its dependencies allows optimal layer caching
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --frozen

RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv export --no-hashes --frozen --format requirements-txt > requirements.txt

RUN grep -v '^-e ' requirements.txt > requirements.remote.txt

# build all remote wheels
RUN pip wheel -w wheels --find-links wheels -r requirements.remote.txt

# build all local packages to wheels
RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv build --all-packages --wheel -o wheels

RUN pip wheel --no-cache-dir -r /requirements.txt
RUN rm -rf /pip-packages/src

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

RUN apt-get update
RUN apt-get install -y \
libpq-dev \
git \
libxml2-dev \
libxslt-dev \
make

WORKDIR /pip-packages/
COPY --from=build /pip-packages/ /pip-packages/
COPY --from=build /wheels/ /wheels/

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

RUN addgroup --system application \
&& adduser --system codecov --ingroup application --home /home/codecov
4 changes: 2 additions & 2 deletions docker/test_codecov_config.yml
Original file line number Diff line number Diff line change
@@ -5,8 +5,8 @@ setup:
encryption_secret: "zp^P9*i8aR3"

services:
database_url: postgres://postgres:password@postgres:5432/postgres
timeseries_database_url: postgres://postgres:password@timescale:5432/postgres
database_url: postgresql://postgres:password@postgres:5432/postgres
timeseries_database_url: postgresql://postgres:password@timescale:5432/postgres
redis_url: redis://redis:6379
minio:
hash_key: testixik8qdauiab1yiffydimvi72ekq # never change this
69 changes: 69 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[project]
name = "worker"
version = "0.1.0"
description = "The codecov worker"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"asgiref>=3.8.1",
"celery>=5.4.0",
"click>=8.1.7",
"codecov-ribs>=0.1.18",
"django-postgres-extra>=2.0.8",
"django<5",
"google-cloud-pubsub>=2.27.1",
"httpx>=0.27.2",
"jinja2>=3.1.4",
"lxml>=5.3.0",
"openai>=1.54.4",
"orjson>=3.10.11",
"polars>=1.13.1",
"psycopg2-binary>=2.9.10",
"python-json-logger>=2.0.7",
"pyyaml>=6.0.2",
"redis>=5.2.0",
"regex>=2024.11.6",
"requests>=2.32.3",
"sentry-sdk>=2.18.0",
"shared",
"sqlalchemy<2",
"statsd>=4.0.1",
"stripe>=11.2.0",
"test-results-parser",
"timestring",
"zstandard>=0.23.0",
]

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[tool.setuptools]
py-modules = []

[tool.uv]
dev-dependencies = [
"factory-boy>=3.3.1",
"freezegun>=1.5.1",
"mock>=5.1.0",
"mypy>=1.13.0",
"pre-commit>=4.0.1",
"pytest-asyncio>=0.24.0",
"pytest-celery>=1.1.3",
"pytest-cov>=6.0.0",
"pytest-django>=4.9.0",
"pytest-freezegun>=0.4.2",
"pytest-mock>=3.14.0",
"pytest-sqlalchemy>=0.2.1",
"pytest>=8.3.3",
"respx>=0.21.1",
"ruff>=0.7.4",
"sqlalchemy-utils>=0.41.2",
"time-machine>=2.16.0",
"vcrpy>=6.0.2",
]

[tool.uv.sources]
timestring = { git = "https://github.com/codecov/timestring", rev = "d37ceacc5954dff3b5bd2f887936a98a668dda42" }
test-results-parser = { git = "https://github.com/codecov/test-results-parser", rev = "94ff26cb083a02ff726dd2497c2129e4aaf5f7cd" }
shared = { git = "https://github.com/codecov/shared", rev = "511b553fd19113f1716326b0363b9d9a4afca1d7" }
Loading
Oops, something went wrong.
Loading
Oops, something went wrong.