This commit is contained in:
Jelmer Draaijer 2024-10-05 21:20:29 +02:00
parent fb27881b33
commit 1cf227b3a8
11 changed files with 70 additions and 89 deletions

View File

@ -84,11 +84,11 @@ and then editing the results to include your name, email, and various configurat
First, get Cookiecutter. Trust me, it's awesome: First, get Cookiecutter. Trust me, it's awesome:
$ pip install "cookiecutter>=1.7.0" $ uv tool install "cookiecutter>=1.7.0"
Now run it against this repo: Now run it against this repo:
$ cookiecutter https://github.com/cookiecutter/cookiecutter-django $ uvx cookiecutter https://github.com/cookiecutter/cookiecutter-django
You'll be prompted for some values. Provide them, then a Django project will be created for you. You'll be prompted for some values. Provide them, then a Django project will be created for you.

View File

@ -154,10 +154,10 @@ This tells our computer that all future commands are specifically for the dev1 m
Add 3rd party python packages Add 3rd party python packages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To install a new 3rd party python package, you cannot use ``pip install <package_name>``, that would only add the package to the container. The container is ephemeral, so that new library won't be persisted if you run another container. Instead, you should modify the Docker image: To install a new 3rd party python package, you cannot use ``uv add <package_name>``, that would only add the package to the container. The container is ephemeral, so that new library won't be persisted if you run another container. Instead, you should modify the Docker image:
You have to modify the relevant requirement file: base, local or production by adding: :: You have to modify pyproject.toml and either add it to project.dependencies or to tool.uv.dev-dependencies by adding: ::
<package_name>==<package_version> "<package_name>==<package_version>"
To get this change picked up, you'll need to rebuild the image(s) and restart the running container: :: To get this change picked up, you'll need to rebuild the image(s) and restart the running container: ::

View File

@ -1,7 +1,7 @@
Getting Up and Running Locally Getting Up and Running Locally
============================== ==============================
.. index:: pip, virtualenv, PostgreSQL .. index:: PostgreSQL
Setting Up Development Environment Setting Up Development Environment
@ -9,7 +9,7 @@ Setting Up Development Environment
Make sure to have the following on your host: Make sure to have the following on your host:
* Python 3.12 * uv https://docs.astral.sh/uv/getting-started/installation/
* PostgreSQL_. * PostgreSQL_.
* Redis_, if using Celery * Redis_, if using Celery
* Cookiecutter_ * Cookiecutter_
@ -29,7 +29,7 @@ First things first.
#. Install development requirements: :: #. Install development requirements: ::
$ cd <what you have entered as the project_slug at setup stage> $ cd <what you have entered as the project_slug at setup stage>
$ pip install -r requirements/local.txt $ uv sync
$ git init # A git repo is required for pre-commit to install $ git init # A git repo is required for pre-commit to install
$ pre-commit install $ pre-commit install

View File

@ -18,13 +18,13 @@ cd my_awesome_project
sudo utility/install_os_dependencies.sh install sudo utility/install_os_dependencies.sh install
# Install Python deps # Install Python deps
pip install -r requirements/local.txt uv sync --frozen
# run the project's tests # run the project's tests
pytest uv run pytest
# Make sure the check doesn't raise any warnings # Make sure the check doesn't raise any warnings
python manage.py check --fail-level WARNING uv run python manage.py check --fail-level WARNING
# Run npm build script if package.json is present # Run npm build script if package.json is present
if [ -f "package.json" ] if [ -f "package.json" ]

View File

@ -13,7 +13,7 @@ environment:
steps: steps:
- name: lint - name: lint
pull: if-not-exists pull: if-not-exists
image: python:3.12 image: ghcr.io/astral-sh/uv:python3.12
environment: environment:
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
volumes: volumes:
@ -21,8 +21,8 @@ steps:
path: ${PRE_COMMIT_HOME} path: ${PRE_COMMIT_HOME}
commands: commands:
- export PRE_COMMIT_HOME=$CI_PROJECT_DIR/.cache/pre-commit - export PRE_COMMIT_HOME=$CI_PROJECT_DIR/.cache/pre-commit
- pip install -q pre-commit - uv pip install -q pre-commit pre-commit-uv
- pre-commit run --show-diff-on-failure --color=always --all-files - uv run pre-commit run --show-diff-on-failure --color=always --all-files
- name: test - name: test
pull: if-not-exists pull: if-not-exists
@ -37,10 +37,10 @@ steps:
- docker-compose -f docker-compose.local.yml up -d - docker-compose -f docker-compose.local.yml up -d
- docker-compose -f docker-compose.local.yml run django pytest - docker-compose -f docker-compose.local.yml run django pytest
{%- else %} {%- else %}
image: python:3.12 image: ghcr.io/astral-sh/uv:python3.12
commands: commands:
- pip install -r requirements/local.txt - uv sync --frozen
- pytest - uv run pytest
{%- endif%} {%- endif%}
volumes: volumes:

View File

@ -87,26 +87,20 @@ jobs:
run: docker compose -f docker-compose.local.yml down run: docker compose -f docker-compose.local.yml down
{%- else %} {%- else %}
- name: Set up Python - uses: actions/checkout@v4
uses: actions/setup-python@v4 - name: Install uv
uses: astral-sh/setup-uv@v2
with: with:
python-version: '3.12' enable-cache: "true"
cache: pip - name: Install dependencies
cache-dependency-path: | run: uv sync
requirements/base.txt
requirements/local.txt
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements/local.txt
- name: Check DB Migrations - name: Check DB Migrations
run: python manage.py makemigrations --check run: uv run python manage.py makemigrations --check
- name: Run DB Migrations - name: Run DB Migrations
run: python manage.py migrate run: uv run python manage.py migrate
- name: Test with pytest - name: Test with pytest
run: pytest run: uv run pytest
{%- endif %} {%- endif %}

View File

@ -13,16 +13,16 @@ variables:
precommit: precommit:
stage: lint stage: lint
image: python:3.12 image: ghcr.io/astral-sh/uv:python3.12
variables: variables:
PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
cache: cache:
paths: paths:
- ${PRE_COMMIT_HOME} - ${PRE_COMMIT_HOME}
before_script: before_script:
- pip install -q pre-commit - uv pip install -q pre-commit pre-commit-uv
script: script:
- pre-commit run --show-diff-on-failure --color=always --all-files - uv run pre-commit run --show-diff-on-failure --color=always --all-files
pytest: pytest:
stage: test stage: test
@ -39,13 +39,13 @@ pytest:
script: script:
- docker compose -f docker-compose.local.yml run django pytest - docker compose -f docker-compose.local.yml run django pytest
{%- else %} {%- else %}
image: python:3.12 image: ghcr.io/astral-sh/uv:python3.12
services: services:
- postgres:{{ cookiecutter.postgresql_version }} - postgres:{{ cookiecutter.postgresql_version }}
variables: variables:
DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB
before_script: before_script:
- pip install -r requirements/local.txt - uv sync --frozen
script: script:
- pytest - uv run pytest
{%- endif %} {%- endif %}

View File

@ -1,8 +1,6 @@
# define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.7-slim-bookworm AS python
# Python build stage # Python build stage
FROM python AS python-build-stage FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS python-build-stage
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
ARG BUILD_ENVIRONMENT=local ARG BUILD_ENVIRONMENT=local
@ -14,15 +12,17 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
libpq-dev libpq-dev
# Requirements are installed here to ensure they will be cached. # Requirements are installed here to ensure they will be cached.
COPY ./requirements . RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
# Create Python Dependency and Sub-Dependency Wheels. --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
RUN pip wheel --wheel-dir /usr/src/app/wheels \ uv sync --frozen --no-install-project --no-dev \
-r ${BUILD_ENVIRONMENT}.txt
ADD . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Python 'run' stage # Python 'run' stage
FROM python AS python-run-stage FROM docker.io/python:3.12.7-slim-bookworm AS python-run-stage
ARG BUILD_ENVIRONMENT=local ARG BUILD_ENVIRONMENT=local
ARG APP_HOME=/app ARG APP_HOME=/app
@ -58,11 +58,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
# All absolute dir copies ignore workdir instruction. All relative dir copies are wrt to the workdir instruction # All absolute dir copies ignore workdir instruction. All relative dir copies are wrt to the workdir instruction
# copy python dependency wheels from python-build-stage # copy python dependency wheels from python-build-stage
COPY --from=python-build-stage /usr/src/app/wheels /wheels/ COPY --from=builder --chown=app:app ${APP_HOME} ${APP_HOME}
# use wheels to install python dependencies
RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \
&& rm -rf /wheels/
COPY ./compose/production/django/entrypoint /entrypoint COPY ./compose/production/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint RUN sed -i 's/\r$//g' /entrypoint
@ -86,7 +82,6 @@ RUN sed -i 's/\r$//g' /start-flower
RUN chmod +x /start-flower RUN chmod +x /start-flower
{% endif %} {% endif %}
# copy application code to WORKDIR ENV PATH="/app/.venv/bin:$PATH"
COPY . ${APP_HOME}
ENTRYPOINT ["/entrypoint"] ENTRYPOINT ["/entrypoint"]

View File

@ -1,7 +1,3 @@
# define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.7-slim-bookworm AS python
# Python build stage # Python build stage
FROM python AS python-build-stage FROM python AS python-build-stage
@ -17,16 +13,17 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Requirements are installed here to ensure they will be cached. # Requirements are installed here to ensure they will be cached.
COPY ./requirements /requirements RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
# create python dependency wheels --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
RUN pip wheel --no-cache-dir --wheel-dir /usr/src/app/wheels \ uv sync --frozen --no-install-project --no-dev
-r /requirements/local.txt -r /requirements/production.txt \ ADD . /app
&& rm -rf /requirements RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Python 'run' stage # Python 'run' stage
FROM python AS python-run-stage FROM docker.io/python:3.12.7-slim-bookworm AS python-run-stage
ARG BUILD_ENVIRONMENT ARG BUILD_ENVIRONMENT
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
@ -49,14 +46,12 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# copy python dependency wheels from python-build-stage # copy python dependency wheels from python-build-stage
COPY --from=python-build-stage /usr/src/app/wheels /wheels COPY --from=builder --chown=app:app /app /app
# use wheels to install python dependencies
RUN pip install --no-cache /wheels/* \
&& rm -rf /wheels
COPY ./compose/local/docs/start /start-docs COPY ./compose/local/docs/start /start-docs
RUN sed -i 's/\r$//g' /start-docs RUN sed -i 's/\r$//g' /start-docs
RUN chmod +x /start-docs RUN chmod +x /start-docs
ENV PATH="/app/.venv/bin:$PATH"
WORKDIR /docs WORKDIR /docs

View File

@ -24,11 +24,9 @@ ENV DJANGO_AZURE_ACCOUNT_NAME=${DJANGO_AZURE_ACCOUNT_NAME}
RUN npm run build RUN npm run build
{%- endif %} {%- endif %}
# define an alias for the specific python version used in this file.
FROM docker.io/python:3.12.7-slim-bookworm AS python
# Python build stage FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim AS python-build-stage
FROM python AS python-build-stage ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
ARG BUILD_ENVIRONMENT=production ARG BUILD_ENVIRONMENT=production
@ -41,15 +39,17 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
# Requirements are installed here to ensure they will be cached. # Requirements are installed here to ensure they will be cached.
COPY ./requirements . RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \
# Create Python Dependency and Sub-Dependency Wheels. --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
RUN pip wheel --wheel-dir /usr/src/app/wheels \ uv sync --frozen --no-install-project --no-dev
-r ${BUILD_ENVIRONMENT}.txt ADD . /app
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev
# Python 'run' stage # Python 'run' stage
FROM python AS python-run-stage FROM docker.io/python:3.12.7-slim-bookworm AS python-run-stage
ARG BUILD_ENVIRONMENT=production ARG BUILD_ENVIRONMENT=production
ARG APP_HOME=/app ARG APP_HOME=/app
@ -76,14 +76,11 @@ RUN apt-get update && apt-get install --no-install-recommends -y \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# All absolute dir copies ignore workdir instruction. All relative dir copies are wrt to the workdir instruction # Copy the application from the builder
# copy python dependency wheels from python-build-stage COPY --from=builder --chown=app:app /app /app
COPY --from=python-build-stage /usr/src/app/wheels /wheels/
# use wheels to install python dependencies
RUN pip install --no-cache-dir --no-index --find-links=/wheels/ /wheels/* \
&& rm -rf /wheels/
# Place executables in the environment at the front of the path
ENV PATH="/app/.venv/bin:$PATH"
COPY --chown=django:django ./compose/production/django/entrypoint /entrypoint COPY --chown=django:django ./compose/production/django/entrypoint /entrypoint
RUN sed -i 's/\r$//g' /entrypoint RUN sed -i 's/\r$//g' /entrypoint

View File

@ -33,7 +33,7 @@ if [ -z "$VIRTUAL_ENV" ]; then
echo >&2 -e "\n" echo >&2 -e "\n"
exit 1; exit 1;
else else
pip install -r $PROJECT_DIR/requirements/local.txt uv sync --frozen
{%- if cookiecutter.use_heroku == "y" -%} {%- if cookiecutter.use_heroku == "y" -%}
pip install -r $PROJECT_DIR/requirements.txt pip install -r $PROJECT_DIR/requirements.txt
{%- endif %} {%- endif %}