Skip to content

Commit 5335350

Browse files
authored
refactor(translator): move into src layout and use uv properly (#213)
Now translator is actually a proper python package. We could publish it in pypy if we were so inclined, but for now, at least it's using uv workspaces and actually is setup to not be so intermingled with scram-django. I also updated scheduler to now use the root lockfile so that we can use one lockfile to rule them all. We also have a pre-commit step to check for an out of date lockfile to make sure we don't change pyproject but forget to update the lock. Having the lock file committed allows us to have our builds actually be reproducible, which is nice. Also updates django-simple-history as `pkg_resources` seems to have been broken and 3.4+ removes that dependency (and is still compatible with django 4.2)
1 parent b4d6126 commit 5335350

25 files changed

Lines changed: 1467 additions & 719 deletions

File tree

.github/workflows/behave.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ jobs:
7373
with:
7474
parallel: true
7575
flag-name: behave
76+
fail-on-error: false
7677

7778
- name: Upload Coverage to GitHub
7879
if: matrix.python-version == '3.12'

.github/workflows/coverage-finish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ jobs:
1818
uses: coverallsapp/github-action@v2
1919
with:
2020
parallel-finished: true
21+
fail-on-error: false

.github/workflows/pytest.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ jobs:
9898
file: ./scheduler/coverage.xml
9999
parallel: true
100100
flag-name: scheduler
101+
fail-on-error: false
101102

102103
- name: Display Scheduler Coverage Metrics for scheduler tests
103104
if: matrix.python-version == '3.12'

.pre-commit-config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,9 @@ repos:
1515
- id: ruff-format
1616
- id: ruff-check
1717
args: [--fix, --exit-non-zero-on-fix]
18+
19+
- repo: https://github.com/astral-sh/uv-pre-commit
20+
rev: 0.10.7
21+
hooks:
22+
- id: uv-lock
23+
args: [--check]

.vscode/launch.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
},
4545
"pathMappings": [
4646
{
47-
"localRoot": "${workspaceFolder}/translator",
47+
"localRoot": "${workspaceFolder}/translator/src/translator",
4848
"remoteRoot": "/app"
4949
}
5050
]
@@ -59,7 +59,7 @@
5959
},
6060
"pathMappings": [
6161
{
62-
"localRoot": "${workspaceFolder}/translator",
62+
"localRoot": "${workspaceFolder}/translator/src/translator",
6363
"remoteRoot": "/app"
6464
}
6565
]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ integration-tests: run
4141
## behave-translator
4242
.Phony: behave-translator
4343
behave-translator: compose.override.yml
44-
@docker compose exec -T translator /usr/local/bin/behave /app/tests/acceptance/features
44+
@docker compose exec -T translator behave /app/tests/acceptance/features
4545

4646
## build: rebuilds all your containers or a single one if CONTAINER is specified
4747
.Phony: build

compose.override.local.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ services:
105105
replicas: 1
106106

107107
translator:
108+
build:
109+
context: .
110+
dockerfile: ./compose/local/translator/Dockerfile
108111
volumes:
109112
- ./translator/tests/:/app/tests/
110113
env_file:
@@ -117,6 +120,9 @@ services:
117120
- DEBUG=${DEBUG:-}
118121

119122
translator-secondary:
123+
build:
124+
context: .
125+
dockerfile: ./compose/local/translator/Dockerfile
120126
volumes:
121127
- ./translator/tests/:/app/tests/
122128
env_file:

compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ services:
101101
translator:
102102
build:
103103
context: .
104-
dockerfile: ./compose/local/translator/Dockerfile
104+
dockerfile: ./compose/production/translator/Dockerfile
105105
depends_on:
106106
redis:
107107
condition: service_healthy
@@ -119,7 +119,7 @@ services:
119119
translator-secondary:
120120
build:
121121
context: .
122-
dockerfile: ./compose/local/translator/Dockerfile
122+
dockerfile: ./compose/production/translator/Dockerfile
123123
depends_on:
124124
redis:
125125
condition: service_healthy
Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
FROM python:3.13-slim-bookworm
1+
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim
22

3-
ENV PYTHONUNBUFFERED 1
4-
ENV PYTHONDONTWRITEBYTECODE 1
3+
ENV PYTHONUNBUFFERED=1
4+
ENV UV_COMPILE_BYTECODE=1
5+
ENV UV_LINK_MODE=copy
56

67
RUN apt-get update \
78
# dependencies for building Python packages
@@ -10,24 +11,39 @@ RUN apt-get update \
1011
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
1112
&& rm -rf /var/lib/apt/lists/*
1213

13-
# Requirements are installed here to ensure they will be cached.
14-
COPY ./translator/requirements /requirements
15-
RUN pip install uv
16-
RUN uv pip install --system -r /requirements/base.txt
14+
WORKDIR /app
1715

18-
RUN mkdir /app \
19-
&& cd /app \
20-
&& git clone -b v3.33.0 https://github.com/osrg/gobgp.git \
21-
&& cd gobgp/api \
22-
&& python3 -m grpc_tools.protoc -I./ --python_out=/app/ --pyi_out=/app/ --grpc_python_out=/app/ *.proto
16+
# At first we install the deps only (as protobuf stuff doesn't exist yet but we need deps to setup protobufs). We also
17+
# mount instead of copying to have a small build cache gain. Not that useful but is modern practice so why not.
18+
RUN --mount=type=cache,target=/root/.cache/uv \
19+
--mount=type=bind,source=uv.lock,target=uv.lock \
20+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
21+
--mount=type=bind,source=translator/pyproject.toml,target=translator/pyproject.toml \
22+
uv sync --frozen --no-install-project --package translator
2323

24-
COPY ./translator/translator.py /app
25-
COPY ./translator/gobgp.py /app
26-
COPY ./translator/exceptions.py /app
27-
COPY ./translator/shared.py /app
24+
# put the venv into PATH
25+
ENV PATH="/app/.venv/bin:$PATH"
2826

29-
RUN chmod +x /app/translator.py
27+
COPY ./translator/src ./translator/src/
3028

31-
WORKDIR /app
32-
33-
ENTRYPOINT ["/app/translator.py"]
29+
# Generate protobuf files
30+
# TODO: Make this less jank and don't do the git clone crap?
31+
# Protos don't work well in packages so we generate them in /app/ outside the package so that bare
32+
# `import gobgp_pb2` style imports work.
33+
RUN git clone -b v3.33.0 https://github.com/osrg/gobgp.git gobgp \
34+
&& cd gobgp/api \
35+
&& python3 -m grpc_tools.protoc -I./ \
36+
--python_out=/app/ \
37+
--pyi_out=/app/ \
38+
--grpc_python_out=/app/ \
39+
*.proto \
40+
&& cd /app && rm -rf gobgp
41+
42+
# Install the project itself (including the protobuff stuff) again mounting in the project files.
43+
RUN --mount=type=cache,target=/root/.cache/uv \
44+
--mount=type=bind,source=uv.lock,target=uv.lock \
45+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
46+
--mount=type=bind,source=translator/pyproject.toml,target=translator/pyproject.toml \
47+
uv sync --frozen --package translator
48+
49+
ENTRYPOINT ["python", "-m", "translator.translator"]

compose/production/celery/Dockerfile

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,23 @@ ENV UV_NO_DEV=1
2121
ENV UV_TOOL_BIN_DIR=/usr/local/bin
2222

2323
COPY ./scheduler/pyproject.toml ./scheduler/uv.lock* ./
24-
25-
# Install the project's dependencies using the lockfile and settings
24+
# Install the project's dependencies only
2625
RUN --mount=type=cache,target=/root/.cache/uv \
27-
--mount=type=bind,source=scheduler/uv.lock,target=uv.lock \
28-
--mount=type=bind,source=scheduler/pyproject.toml,target=pyproject.toml \
29-
uv sync --locked --no-install-project
26+
--mount=type=bind,source=uv.lock,target=uv.lock \
27+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
28+
--mount=type=bind,source=scheduler/pyproject.toml,target=scheduler/pyproject.toml \
29+
uv sync --frozen --no-install-project --package scheduler
3030

3131
# Then, add the rest of the project source code and install it
32-
# Installing separately from its dependencies allows optimal layer caching
33-
COPY ./scheduler/src /app/
32+
# Installing separately from its dependencies allows optimal layer caching. We use --frozen since we
33+
# have differing python versions across the stack.
34+
COPY ./scheduler/src ./scheduler/src/
3435

3536
RUN --mount=type=cache,target=/root/.cache/uv \
36-
uv sync --locked
37+
--mount=type=bind,source=uv.lock,target=uv.lock \
38+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
39+
--mount=type=bind,source=scheduler/pyproject.toml,target=scheduler/pyproject.toml \
40+
uv sync --frozen --package scheduler
3741

3842
# Place executables in the environment at the front of the path
3943
ENV PATH="/app/.venv/bin:$PATH"

0 commit comments

Comments
 (0)