Skip to content

Commit 98e28c1

Browse files
committed
Manage project environment with uv
1 parent 7c7e19a commit 98e28c1

25 files changed

+1469
-5303
lines changed

.dockerignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
**
22

3-
!/requirements*
3+
# We need .git to not be excluded from the context (hatch-vcs).
4+
!/.git/**
5+
46
!/a3m/**
57
!/.python-version
8+
!/uv.lock
69
!/pyproject.toml
710
!/README.rst
811
!/LICENSE

.github/workflows/tests.yml

Lines changed: 18 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -6,93 +6,30 @@ on:
66
- main
77
jobs:
88
tests:
9-
name: "Test on ${{ matrix.os }}"
10-
runs-on: "${{ matrix.os }}-latest"
11-
strategy:
12-
fail-fast: false
13-
matrix:
14-
os:
15-
- ubuntu
9+
name: "Test"
10+
runs-on: "ubuntu-22.04"
1611
steps:
1712
- name: "Check out source code"
1813
uses: "actions/checkout@v4"
19-
- name: "Install Python"
20-
uses: "actions/setup-python@v4"
14+
- name: Install the latest version of uv
15+
uses: astral-sh/setup-uv@v2
2116
with:
22-
python-version: |
23-
3.11
24-
3.12
25-
- name: "Restore cache"
26-
id: "restore-cache"
27-
uses: "actions/cache@v3"
17+
enable-cache: true
18+
version: latest
19+
- name: Run tests
20+
run: ./test.sh
21+
- name: "Upload coverage report"
22+
if: github.repository == 'artefactual-labs/a3m'
23+
uses: "codecov/codecov-action@v4"
2824
with:
29-
path: |
30-
.tox/
31-
.venv/
32-
key: "cache-python-${{ steps.setup-python.outputs.python-version }}-os-${{ runner.os }}-hash-${{ hashFiles('pyproject.toml', 'requirements.txt', 'requirements-dev.txt') }}"
33-
- name: "Install tox"
34-
if: "steps.restore-cache.outputs.cache-hit == false"
35-
run: |
36-
python -m venv .venv
37-
.venv/bin/python -m pip install -U setuptools
38-
.venv/bin/python -m pip install tox
39-
- name: "Run tox"
40-
run: |
41-
.venv/bin/python -m tox -e py
42-
- name: "Upload coverage data"
43-
uses: actions/upload-artifact@v3
25+
files: ./coverage.xml
26+
token: ${{ secrets.CODECOV_TOKEN }}
27+
- name: Upload test results to Codecov
28+
if: ${{ !cancelled() }}
29+
uses: codecov/test-results-action@v1
4430
with:
45-
name: covdata
46-
path: .coverage.*
47-
coverage:
48-
name: Coverage
49-
needs: tests
50-
runs-on: ubuntu-latest
51-
steps:
52-
- name: "Check out the repo"
53-
uses: "actions/checkout@v4"
54-
- name: "Set up Python"
55-
uses: "actions/setup-python@v4"
56-
with:
57-
python-version-file: ".python-version"
58-
cache: pip
59-
cache-dependency-path: "requirements-dev.txt"
60-
- name: "Install tox"
61-
run: |
62-
python -m pip install -U setuptools
63-
python -m pip install tox
64-
- name: "Download coverage data"
65-
uses: actions/download-artifact@v3
66-
with:
67-
name: covdata
68-
- name: "Combine and report"
69-
run: |
70-
python -m tox -e coverage
71-
export TOTAL=$(python -c "import json;print(json.load(open('coverage.json'))['totals']['percent_covered_display'])")
72-
echo "total=$TOTAL" >> $GITHUB_ENV
73-
echo "### Total coverage: ${TOTAL}%" >> $GITHUB_STEP_SUMMARY
74-
- name: "Codecov"
75-
uses: codecov/codecov-action@v3
76-
with:
77-
files: coverage.xml
78-
pre-commit:
79-
name: "Run pre-commit"
80-
runs-on: "ubuntu-latest"
81-
steps:
82-
- name: "Check out the repo"
83-
uses: "actions/checkout@v4"
84-
- name: "Set up Python"
85-
uses: "actions/setup-python@v4"
86-
with:
87-
python-version-file: ".python-version"
88-
cache: pip
89-
cache-dependency-path: "requirements-dev.txt"
90-
- name: "Install requirements"
91-
run: |
92-
python -m pip install -U setuptools
93-
python -m pip install -r requirements-dev.txt
94-
- name: "Run pre-commit"
95-
run: tox -e pre-commit
31+
files: ./junit.xml
32+
token: ${{ secrets.CODECOV_TOKEN }}
9633
e2e:
9734
name: "Run E2E tests"
9835
runs-on: ubuntu-latest
@@ -121,5 +58,3 @@ jobs:
12158
-m a3m.cli.client \
12259
--name=MARBLES \
12360
https://github.com/artefactual/archivematica-sampledata/raw/master/SampleTransfers/Images/pictures/MARBLES.TGA
124-
# TODO: main branch? push image to a3m:main
125-
# TODO: and tagged? push image to a3m:${tag} and a3m:latest

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ coverage.*
2929
# pytest's working directory
3030
.cache
3131
.pytest_cache
32-
33-
# tox working directory
34-
.tox/
32+
junit.xml
3533

3634
# mypy cache
3735
.mypy_cache/

.pre-commit-config.yaml

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
repos:
2-
32
- repo: https://github.com/pre-commit/pre-commit-hooks
43
rev: v4.6.0
54
hooks:
@@ -12,61 +11,26 @@ repos:
1211
a3m/assets/.*\.json|
1312
tests/server/fixtures/workflow-integration-test.json
1413
)
15-
1614
- repo: https://github.com/PyCQA/doc8
1715
rev: v1.1.2
1816
hooks:
1917
- id: doc8
2018
files: ^docs/.*\.rst$
21-
2219
- repo: https://github.com/astral-sh/ruff-pre-commit
23-
rev: v0.6.3
20+
rev: v0.6.7
2421
hooks:
2522
- id: ruff
2623
args:
2724
- "--fix"
2825
- "--exit-non-zero-on-fix"
2926
- id: ruff-format
30-
3127
- repo: https://github.com/adamchainz/django-upgrade
3228
rev: "1.21.0"
3329
hooks:
3430
- id: django-upgrade
3531
args:
3632
- "--target-version=4.2"
37-
38-
- repo: local
39-
hooks:
40-
- id: mypy
41-
name: mypy
42-
entry: mypy
43-
language: system
44-
types: [python]
45-
pass_filenames: false
46-
args:
47-
- "a3m"
48-
4933
- repo: https://github.com/astral-sh/uv-pre-commit
50-
rev: 0.4.5
34+
rev: 0.4.16
5135
hooks:
52-
- id: pip-compile
53-
args:
54-
- "--python-version=3.12"
55-
- "--output-file=requirements.txt"
56-
- "pyproject.toml"
57-
files: |
58-
(?x)^(
59-
pyproject.toml|
60-
requirements.txt
61-
)$
62-
- id: pip-compile
63-
args:
64-
- "--python-version=3.12"
65-
- "--output-file=requirements-dev.txt"
66-
- "pyproject.toml"
67-
- "--extra=dev"
68-
files: |
69-
(?x)^(
70-
pyproject.toml|
71-
requirements-dev.txt
72-
)$
36+
- id: uv-lock

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.12.5
1+
3.12.6

.readthedocs.yaml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ version: 2
22
build:
33
os: "ubuntu-22.04"
44
tools:
5-
python: "3.11"
6-
jobs:
7-
post_checkout:
8-
- "git fetch --unshallow"
5+
python: "3.12"
6+
commands:
7+
- asdf plugin add uv
8+
- asdf install uv latest
9+
- asdf global uv latest
10+
- uv sync --frozen
11+
- git fetch --unshallow
12+
- .venv/bin/python -m sphinx -T -b html -d docs/_build/doctrees -D language=en docs $READTHEDOCS_OUTPUT/html
913
sphinx:
1014
configuration: "docs/conf.py"
11-
python:
12-
install:
13-
- requirements: "requirements-dev.txt"

CHANGELOG.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ See the fragment files in the `changelog.d directory`_.
1919

2020
.. scriv-insert-here
2121
22+
.. _changelog-0.8.0:
23+
24+
0.8.0 - 2024-09-25
25+
==================
26+
27+
Changed
28+
-------
29+
30+
- Use Python 3.12.6.
31+
- Use ``uv`` to manage the project environment.
32+
2233
.. _changelog-0.7.14:
2334

2435
0.7.14 - 2024-09-24

Dockerfile

Lines changed: 44 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
# syntax=docker/dockerfile:1.10.0-labs
2+
13
ARG SYSTEM_IMAGE=ubuntu:22.04
4+
ARG UV_VERSION=0.4.16
5+
ARG USER_ID=1000
6+
ARG GROUP_ID=1000
27

38
#
49
# Base
510
#
611

712
FROM ${SYSTEM_IMAGE} AS base
813

9-
ARG USER_ID=1000
10-
ARG GROUP_ID=1000
11-
1214
ENV DEBIAN_FRONTEND=noninteractive
1315
ENV PYTHONUNBUFFERED=1
1416

@@ -67,64 +69,53 @@ RUN set -ex \
6769
uuid \
6870
&& rm -rf /var/lib/apt/lists/*
6971

70-
# Python build.
71-
RUN set -ex \
72-
&& apt-get update \
73-
&& apt-get install -y --no-install-recommends \
74-
build-essential \
75-
libbz2-dev \
76-
libffi-dev \
77-
liblzma-dev \
78-
libncursesw5-dev \
79-
libreadline-dev \
80-
libsqlite3-dev \
81-
libssl-dev \
82-
libxml2-dev \
83-
libxmlsec1-dev \
84-
tk-dev \
85-
xz-utils \
86-
zlib1g-dev
87-
88-
# Create a3m user
89-
RUN set -ex \
90-
&& groupadd --gid ${GROUP_ID} --system a3m \
91-
&& useradd --uid ${USER_ID} --gid ${GROUP_ID} --create-home --home-dir /home/a3m --system a3m \
92-
&& mkdir -p /home/a3m/.local/share/a3m/share \
93-
&& chown -R a3m:a3m /home/a3m/.local
72+
# -----------------------------------------------------------------------------
9473

74+
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv
9575

96-
#
97-
# a3m
98-
#
76+
# -----------------------------------------------------------------------------
9977

10078
FROM base AS a3m
10179

102-
ARG DJANGO_SETTINGS_MODULE=a3m.settings.common
103-
ENV DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE}
104-
ENV PYENV_ROOT="/home/a3m/.pyenv"
105-
ENV PATH=$PYENV_ROOT/shims:$PYENV_ROOT/bin:$PATH
106-
ARG PYTHON_VERSION=""
107-
ARG REQUIREMENTS=/a3m/requirements.txt
80+
ARG USER_ID
81+
ARG GROUP_ID
10882

109-
COPY ./.python-version /a3m/.python-version
110-
RUN set -ex \
111-
&& curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash \
112-
&& if [ -z "${PYTHON_VERSION}" ]; then PYTHON_VERSION=$(cat /a3m/.python-version); fi \
113-
&& pyenv install ${PYTHON_VERSION} \
114-
&& pyenv global ${PYTHON_VERSION}
115-
116-
COPY ./requirements.txt /a3m/requirements.txt
117-
COPY ./requirements-dev.txt /a3m/requirements-dev.txt
118-
COPY ./pyproject.toml /a3m/pyproject.toml
83+
# Create a3m user.
11984
RUN set -ex \
120-
&& pyenv exec python3 -m pip install --upgrade pip setuptools \
121-
&& pyenv exec python3 -m pip install --requirement ${REQUIREMENTS} \
122-
&& pyenv rehash
85+
&& groupadd --gid ${GROUP_ID} --system a3m \
86+
&& useradd --uid ${USER_ID} --gid ${GROUP_ID} --home-dir /home/a3m --system a3m \
87+
&& mkdir -p /home/a3m/.local/share/a3m/share \
88+
&& chown -R a3m:a3m /home/a3m
89+
90+
# Install uv.
91+
COPY --from=uv /uv /bin/uv
12392

124-
COPY . /a3m
125-
WORKDIR /a3m
126-
RUN pip install . --no-deps
93+
# Enable bytecode compilation.
94+
ENV UV_COMPILE_BYTECODE=1
12795

96+
# Copy from the cache instead of linking since it's a mounted volume.
97+
ENV UV_LINK_MODE=copy
98+
99+
# Change the current user.
128100
USER a3m
129101

130-
ENTRYPOINT ["python", "-m", "a3m.cli.server"]
102+
# Install the project into `/app`.
103+
WORKDIR /app
104+
105+
# Install the project's dependencies using the lockfile and settings.
106+
RUN --mount=type=cache,target=/home/a3m/.cache/uv,uid=${USER_ID},gid=${GROUP_ID} \
107+
--mount=type=bind,source=uv.lock,target=uv.lock \
108+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
109+
uv sync --frozen --no-install-project --no-dev
110+
111+
# Add the rest of the project source code and install it.
112+
# Installing separately from its dependencies allows optimal layer caching.
113+
COPY --exclude=.git . /app
114+
RUN --mount=type=cache,target=/home/a3m/.cache/uv,uid=${USER_ID},gid=${GROUP_ID} \
115+
--mount=type=bind,source=.git,target=.git \
116+
uv sync --frozen --no-dev
117+
118+
# Place executables in the environment at the front of the path.
119+
ENV PATH="/app/.venv/bin:$PATH"
120+
121+
CMD ["a3md"]

0 commit comments

Comments
 (0)