Skip to content

Switch to uv for package management #1720

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

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
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
78 changes: 27 additions & 51 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,24 @@
"uses": "actions/checkout@v2"
},
{
"name": "Set up Python ${{ matrix.python-version }}",
"uses": "actions/setup-python@v5",
"with": {
"python-version": "${{ matrix.python-version }}"
}
"name": "Set up uv",
"uses": "astral-sh/setup-uv@v5"
},
{
"name": "Set up pip cache",
"uses": "actions/cache@v4",
"with": {
"path": "~/.cache/pip",
"key": "pip-${{ matrix.python-version }}"
}
"name": "Set up Python ${{ matrix.python-version }}",
"run": "uv python install ${{ matrix.python-version }}"
},
{
"name": "Set up packages",
"run": "set -e\n\npip install -U pip setuptools wheel\npip install -U \\\n pre-commit coveralls pyyaml pytest-django\npip install -U -r requirements.txt\n\necho \"PATH=$PATH\" >> $GITHUB_ENV\n"
"run": "uv sync --group ci --locked"
},
{
"name": "Copy secret.py",
"run": "cp intranet/settings/ci_secret.py intranet/settings/secret.py"
},
{
"name": "Run pre-commit",
"run": "pre-commit run --all-files"
"run": "uv run pre-commit run --all-files"
}
]
},
Expand All @@ -78,57 +71,47 @@
}
},
{
"name": "Set up Python ${{ matrix.python-version }}",
"uses": "actions/setup-python@v5",
"with": {
"python-version": "${{ matrix.python-version }}"
}
"name": "Set up uv",
"uses": "astral-sh/setup-uv@v5"
},
{
"name": "Set up pip cache",
"uses": "actions/cache@v4",
"with": {
"path": "~/.cache/pip",
"key": "pip-${{ matrix.python-version }}"
}
"name": "Set up Python ${{ matrix.python-version }}",
"run": "uv python install ${{ matrix.python-version }}"
},
{
"name": "Set up packages",
"run": "set -e\n\npip install -U pip setuptools wheel\npip install -U \\\n pre-commit coveralls pyyaml pytest-django\npip install -U -r requirements.txt\n\necho \"PATH=$PATH\" >> $GITHUB_ENV\n"
"run": "uv sync --group ci --locked"
},
{
"name": "Copy secret.py",
"run": "cp intranet/settings/ci_secret.py intranet/settings/secret.py"
},
{
"name": "Regenerate workflow YAML file and check for changes",
"run": "./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py"
"run": "uv run ./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py"
},
{
"name": "Check for changes to CI spec",
"run": "./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py"
"run": "uv run ./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py"
},
{
"name": "Validate PR commit messages",
"if": "github.event_name == 'pull_request'",
"run": "./scripts/validate-commit-messages.py ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
"run": "uv run ./scripts/validate-commit-messages.py ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
},
{
"name": "Validate push commit messages",
"if": "github.event_name == 'push' && (github.repository_owner != 'tjcsl' || github.ref != 'refs/heads/master' || github.ref != 'refs/heads/dev')",
"run": "git fetch origin ${{ github.event.before }} && ./scripts/validate-commit-messages.py ${{ github.event.before }}..${{ github.event.after }}"
},
{
"name": "Install docs dependencies",
"run": "# sphinxcontrib_django imports our django project, so we need the deps\npip install -U -r requirements.txt\ncd docs\npip install -U -r requirements.txt\n"
},
{
"name": "Check docs build up to date",
"run": "./scripts/build_ensure_no_changes.sh python3 scripts/build_docs.py"
},
{
"name": "Build docs",
"run": "cd docs\nmake html\n"
"workding_dir": "docs",
"run": "uv run make html"
},
{
"name": "Push docs",
Expand Down Expand Up @@ -187,23 +170,16 @@
"uses": "actions/checkout@v2"
},
{
"name": "Set up Python ${{ matrix.python-version }}",
"uses": "actions/setup-python@v5",
"with": {
"python-version": "${{ matrix.python-version }}"
}
"name": "Set up uv",
"uses": "astral-sh/setup-uv@v5"
},
{
"name": "Set up pip cache",
"uses": "actions/cache@v4",
"with": {
"path": "~/.cache/pip",
"key": "pip-${{ matrix.python-version }}"
}
"name": "Set up Python ${{ matrix.python-version }}",
"run": "uv python install ${{ matrix.python-version }}"
},
{
"name": "Set up packages",
"run": "set -e\n\npip install -U pip setuptools wheel\npip install -U \\\n pre-commit coveralls pyyaml pytest-django\npip install -U -r requirements.txt\n\necho \"PATH=$PATH\" >> $GITHUB_ENV\n"
"run": "uv sync --group ci --locked"
},
{
"name": "Copy secret.py",
Expand Down Expand Up @@ -235,24 +211,24 @@
{
"name": "Run tests (Fork)",
"if": "github.repository_owner != 'tjcsl'",
"run": "coverage run -a ./manage.py test --noinput --parallel 4"
"run": "uv run coverage run -a ./manage.py test --noinput --parallel 4"
},
{
"name": "Run tests (PR/Push)",
"if": "github.repository_owner == 'tjcsl'",
"run": "coverage run -a ./manage.py test --noinput"
"run": "uv run coverage run -a ./manage.py test --noinput"
},
{
"name": "Check for unmigrated changes",
"run": "coverage run -a ./manage.py makemigrations --noinput --check"
"run": "uv run coverage run -a ./manage.py makemigrations --noinput --check"
},
{
"name": "Migrate database",
"run": "coverage run -a ./manage.py migrate"
"run": "uv run coverage run -a ./manage.py migrate"
},
{
"name": "Collect static files",
"run": "coverage run -a ./manage.py collectstatic --noinput -v 0"
"run": "uv run coverage run -a ./manage.py collectstatic --noinput -v 0"
},
{
"name": "Report coverage to Coveralls",
Expand All @@ -264,7 +240,7 @@
{
"name": "Build coverage XML file",
"if": "github.repository_owner == 'tjcsl' && github.event_name != 'pull_request'",
"run": "coverage xml"
"run": "uv run coverage xml"
},
{
"name": "Report coverage to Codacy",
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.8
69 changes: 24 additions & 45 deletions ci/spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ env:
node_versions: &node_versions
- 14.x

python_setup: &python_setup
name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

repo_setup: &repo_setup
name: Set up repo
uses: actions/checkout@v2
Expand All @@ -43,24 +37,17 @@ env:
with:
fetch-depth: 0

setup_pip_cache: &setup_pip_cache
name: Set up pip cache
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: pip-${{ matrix.python-version }}
setup_uv_cache: &setup_uv_cache
name: Set up uv
uses: astral-sh/setup-uv@v6

python_setup: &python_setup
name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}

setup_packages: &setup_packages
name: Set up packages
run: |
set -e

pip install -U pip setuptools wheel
pip install -U \
pre-commit coveralls pyyaml pytest-django
pip install -U -r requirements.txt

echo "PATH=$PATH" >> $GITHUB_ENV
run: uv sync --group ci --locked

.copy_secret: &copy_secret
name: Copy secret.py
Expand All @@ -77,13 +64,13 @@ jobs:

steps:
- *repo_setup
- *setup_uv_cache
- *python_setup
- *setup_pip_cache
- *setup_packages
- *copy_secret

- name: Run pre-commit
run: 'pre-commit run --all-files'
run: 'uv run pre-commit run --all-files'

build:
runs-on: ubuntu-latest
Expand All @@ -96,43 +83,34 @@ jobs:
steps:
# We need the full history so we can validate commit messages.
- *repo_setup_fetch_all
- *setup_uv_cache
- *python_setup
- *setup_pip_cache
- *setup_packages
- *copy_secret

- name: Regenerate workflow YAML file and check for changes
run: ./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py
run: uv run ./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py

# Check for changes to CI spec
- name: Check for changes to CI spec
run: ./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py
run: uv run ./scripts/build_ensure_no_changes.sh ./ci/regen-workflow.py

# Validate commit messages
- name: Validate PR commit messages
# Validate commit messages for PRs
if: "github.event_name == 'pull_request'"
run: ./scripts/validate-commit-messages.py ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
run: uv run ./scripts/validate-commit-messages.py ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
- name: Validate push commit messages
# Validate commit messages for forks and branches that aren't dev or master
if: "github.event_name == 'push' && (github.repository_owner != 'tjcsl' || github.ref != 'refs/heads/master' || github.ref != 'refs/heads/dev')"
run: 'git fetch origin ${{ github.event.before }} && ./scripts/validate-commit-messages.py ${{ github.event.before }}..${{ github.event.after }}'

# Build/push docs
- name: Install docs dependencies
run: |
# sphinxcontrib_django imports our django project, so we need the deps
pip install -U -r requirements.txt
cd docs
pip install -U -r requirements.txt

- name: Check docs build up to date
run: ./scripts/build_ensure_no_changes.sh python3 scripts/build_docs.py

- name: Build docs
run: |
cd docs
make html
workding_dir: docs
run: uv run make html

- name: Push docs
# Only run for pushes to the main Ion repo
Expand Down Expand Up @@ -177,8 +155,8 @@ jobs:

steps:
- *repo_setup
- *setup_uv_cache
- *python_setup
- *setup_pip_cache
- *setup_packages
- *copy_secret

Expand Down Expand Up @@ -210,20 +188,21 @@ jobs:
sudo apt update
sudo apt install -y krb5-user


# Tests
- name: Run tests (Fork)
if: github.repository_owner != 'tjcsl'
run: coverage run -a ./manage.py test --noinput --parallel 4
run: uv run coverage run -a ./manage.py test --noinput --parallel 4
- name: Run tests (PR/Push)
if: github.repository_owner == 'tjcsl' # Run single-threaded for accurate coverage reporting on Ion GitHub
run: coverage run -a ./manage.py test --noinput
run: uv run coverage run -a ./manage.py test --noinput
# Check for unmigrated changes
- name: Check for unmigrated changes
run: coverage run -a ./manage.py makemigrations --noinput --check
run: uv run coverage run -a ./manage.py makemigrations --noinput --check
- name: Migrate database
run: coverage run -a ./manage.py migrate
run: uv run coverage run -a ./manage.py migrate
- name: Collect static files
run: coverage run -a ./manage.py collectstatic --noinput -v 0
run: uv run coverage run -a ./manage.py collectstatic --noinput -v 0

# Coveralls
- name: Report coverage to Coveralls
Expand All @@ -234,7 +213,7 @@ jobs:
# Codacy
- name: Build coverage XML file
if: github.repository_owner == 'tjcsl' && github.event_name != 'pull_request'
run: coverage xml
run: uv run coverage xml
- name: Report coverage to Codacy
uses: codacy/codacy-coverage-reporter-action@master
if: github.repository_owner == 'tjcsl' && github.event_name != 'pull_request'
Expand Down
18 changes: 11 additions & 7 deletions config/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
FROM python:3.8.19-alpine3.18

ENV TZ America/New_York
ENV C_FORCE_ROOT true
ENV TZ=America/New_York
ENV C_FORCE_ROOT=true
ENV UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1 \
UV_PYTHON_DOWNLOADS=never \
UV_PROJECT_ENVIRONMENT=/venv

COPY config/krb5.conf /etc/krb5.conf
COPY requirements.txt .
COPY requirements-dev.txt .
COPY pyproject.toml .
COPY uv.lock .

COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv

RUN apk update && \
apk add bash git curl build-base libpq-dev freetype-dev libffi-dev ruby-full libmagic krb5 kinit rsync nodejs npm tzdata libxml2-dev libxslt-dev && \
npm install -g sass && \
ln -s /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
pip3 install -Ir requirements.txt && \
pip3 install -Ir requirements-dev.txt && \
rm requirements.txt requirements-dev.txt
uv sync

WORKDIR /ion
6 changes: 2 additions & 4 deletions config/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.9'

services:
redis:
container_name: intranet_redis
Expand Down Expand Up @@ -56,7 +54,7 @@ services:
"/bin/sh",
"-c",
"git config --global --add safe.directory /ion && \
celery --app intranet worker -l info --without-gossip --without-mingle --without-heartbeat -Ofair"
uv run celery --app intranet worker -l info --without-gossip --without-mingle --without-heartbeat -Ofair"
]
depends_on:
- django
Expand All @@ -73,7 +71,7 @@ services:
"/bin/sh",
"-c",
"git config --global --add safe.directory /ion && \
celery --app intranet beat -l info"
uv run celery --app intranet beat -l info"
]
depends_on:
- django
Expand Down
2 changes: 1 addition & 1 deletion config/docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export PYTHONUNBUFFERED=1 # Don't buffer Django output
# Wrap the run command in a loop so that it restarts if it crashes, e.g. due to a syntax error
while true
do
python3 manage.py run 0.0.0.0:8080 # Custom run command that skips system checks for performance
uv run manage.py run 0.0.0.0:8080 # Custom run command that skips system checks for performance
sleep 1
done
Loading