Skip to content

Commit bcdcf25

Browse files
authored
ci: Migrate to uv (#6546)
1 parent 938b609 commit bcdcf25

15 files changed

Lines changed: 6004 additions & 7603 deletions
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Install uv
2+
description: |
3+
Install uv with the version pinned in api/pyproject.toml's
4+
[tool.uv] required-version, with the uv cache enabled and
5+
invalidated against api/uv.lock.
6+
7+
inputs:
8+
python-version:
9+
description: Python version to install
10+
required: true
11+
12+
runs:
13+
using: composite
14+
steps:
15+
- uses: astral-sh/setup-uv@v6
16+
with:
17+
version-file: api/pyproject.toml
18+
python-version: ${{ inputs.python-version }}
19+
enable-cache: true
20+
cache-dependency-glob: api/uv.lock

.github/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
version: 2
55
updates:
6-
- package-ecosystem: "pip"
6+
- package-ecosystem: "uv"
77
# we only want security updates from dependabot, so we set the limit to 0
88
# for regular updates. See documentation for further information here:
99
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference#open-pull-requests-limit-

.github/workflows/api-deploy-production-ecs.yml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,16 @@ jobs:
3030
steps:
3131
- uses: actions/checkout@v4
3232

33-
- name: Install Poetry
34-
run: make install-poetry
35-
36-
- name: Set up Python
37-
uses: actions/setup-python@v5
33+
- name: Install uv
34+
uses: ./.github/actions/install-uv
3835
with:
3936
python-version: "3.12"
40-
cache: poetry
4137

4238
- name: Install dependencies
4339
run: |
4440
echo "https://${{ secrets.GH_PRIVATE_ACCESS_TOKEN }}:@github.com" > ${HOME}/.git-credentials
4541
git config --global credential.helper store
46-
make install-packages opts="--with saml,auth-controller,workflows,release-pipelines"
42+
make install-packages opts="--extra saml --extra auth-controller --extra workflows --extra release-pipelines"
4743
make install-private-modules
4844
rm -rf ${HOME}/.git-credentials
4945

.github/workflows/api-pull-request.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,13 @@ jobs:
4242
- name: Cloning repo
4343
uses: actions/checkout@v5
4444

45-
- name: Install Poetry
46-
run: make install-poetry
47-
48-
- uses: actions/setup-python@v5
45+
- name: Install uv
46+
uses: ./.github/actions/install-uv
4947
with:
5048
python-version: ${{ matrix.python-version }}
51-
cache: poetry
5249

5350
- name: Install Dependencies
54-
run: make install-packages
51+
run: make install-packages opts='--extra dev'
5552

5653
- name: Check for missing migrations
5754
env:

.github/workflows/api-run-makefile-target.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,13 @@ jobs:
3333
steps:
3434
- uses: actions/checkout@v5
3535

36-
- name: Install Poetry
37-
run: make install-poetry
38-
39-
- uses: actions/setup-python@v5
36+
- name: Install uv
37+
uses: ./.github/actions/install-uv
4038
with:
4139
python-version: 3.13
42-
cache: poetry
4340

4441
- name: Install Dependencies
45-
run: make install-packages
42+
run: make install-packages opts='--extra dev'
4643

4744
- name: Run `make ${{ inputs.target }} opts=${{ inputs.opts }}`
4845
env:

.github/workflows/api-tests-with-private-packages.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,10 @@ jobs:
4040
- name: Cloning repo
4141
uses: actions/checkout@v5
4242

43-
- name: Install Poetry
44-
run: make install-poetry
45-
46-
- uses: actions/setup-python@v5
43+
- name: Install uv
44+
uses: ./.github/actions/install-uv
4745
with:
4846
python-version: ${{ matrix.python-version }}
49-
cache: poetry
5047

5148
- name: Install SAML Dependencies
5249
run: sudo apt-get install -y xmlsec1
@@ -56,7 +53,7 @@ jobs:
5653
run: |
5754
echo "https://${{ secrets.GH_PRIVATE_ACCESS_TOKEN }}:@github.com" > ${HOME}/.git-credentials
5855
git config --global credential.helper store
59-
make install-packages opts="--with saml,auth-controller,workflows"
56+
make install-packages opts="--extra dev --extra saml --extra auth-controller --extra workflows"
6057
make install-private-modules
6158
make integrate-private-tests
6259
rm -rf ${HOME}/.git-credentials

.github/workflows/update-flagsmith-environment.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,16 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@v5
2222

23-
- name: Set up Python 3.12
24-
uses: actions/setup-python@v5
23+
- name: Install uv
24+
uses: ./.github/actions/install-uv
2525
with:
2626
python-version: 3.12
27-
cache: pip
2827

2928
- name: Install Dependencies
30-
run: make install
29+
run: make install-packages
3130

3231
- name: Update defaults
33-
run: poetry run python manage.py updateflagsmithenvironment
32+
run: uv run python manage.py updateflagsmithenvironment
3433

3534
- name: Create Pull Request
3635
uses: peter-evans/create-pull-request@v8

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ repos:
3737
- id: python-typecheck
3838
name: python-typecheck
3939
language: system
40-
entry: poetry -C api run mypy .
40+
entry: uv run --directory api mypy .
4141
require_serial: true
4242
pass_filenames: false
4343
types: [python]
@@ -48,11 +48,11 @@ repos:
4848
hooks:
4949
- id: flagsmith-lint-tests
5050

51-
- repo: https://github.com/python-poetry/poetry
52-
rev: 2.4.0
51+
- repo: https://github.com/astral-sh/uv-pre-commit
52+
rev: 0.8.14
5353
hooks:
54-
- id: poetry-check
55-
args: ["-C", "api"]
54+
- id: uv-lock
55+
args: ["--project", "api", "--check"]
5656

5757
default_install_hook_types: [pre-commit, pre-push]
5858
default_stages: [pre-commit]

Dockerfile

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,15 @@ RUN apk add build-base linux-headers curl git \
9393
python-${PYTHON_VERSION}-dev \
9494
py${PYTHON_VERSION}-pip
9595

96-
COPY api/pyproject.toml api/poetry.lock api/Makefile ./
97-
ENV POETRY_VIRTUALENVS_IN_PROJECT=true \
98-
POETRY_VIRTUALENVS_OPTIONS_ALWAYS_COPY=true \
99-
POETRY_VIRTUALENVS_OPTIONS_NO_PIP=true \
100-
POETRY_VIRTUALENVS_OPTIONS_NO_SETUPTOOLS=true \
101-
POETRY_HOME=/opt/poetry \
102-
PATH="/opt/poetry/bin:$PATH"
103-
RUN make install opts='--without dev'
96+
COPY api/pyproject.toml api/uv.lock api/Makefile ./
97+
ENV UV_PROJECT_ENVIRONMENT=/build/.venv \
98+
UV_PYTHON_PREFERENCE=only-system \
99+
UV_PYTHON=python${PYTHON_VERSION} \
100+
UV_LINK_MODE=copy \
101+
UV_NO_SYNC=1 \
102+
UV_CACHE_DIR=/root/.cache/uv
103+
RUN --mount=type=cache,target=/root/.cache/uv \
104+
make install opts='--no-install-project'
104105

105106
# * build-python-private [build-python]
106107
FROM build-python AS build-python-private
@@ -109,11 +110,12 @@ FROM build-python AS build-python-private
109110
# and integrate private modules
110111
ARG SAML_REVISION
111112
ARG RBAC_REVISION
112-
ARG WITH="saml,auth-controller,ldap,workflows,licensing,release-pipelines"
113+
ARG EXTRAS="--extra saml --extra auth-controller --extra ldap --extra workflows --extra licensing --extra release-pipelines"
113114
RUN --mount=type=secret,id=github_private_cloud_token \
115+
--mount=type=cache,target=/root/.cache/uv \
114116
echo "https://$(cat /run/secrets/github_private_cloud_token):@github.com" > ${HOME}/.git-credentials && \
115117
git config --global credential.helper store && \
116-
make install-packages opts='--without dev --with ${WITH}' && \
118+
make install-packages opts="--no-install-project ${EXTRAS}" && \
117119
make install-private-modules
118120

119121
# * api-runtime
@@ -161,7 +163,8 @@ FROM build-python AS api-test
161163

162164
COPY api /build/
163165

164-
RUN make install-packages opts='--with dev'
166+
RUN --mount=type=cache,target=/root/.cache/uv \
167+
make install-packages opts='--extra dev'
165168

166169
CMD ["make", "test"]
167170

@@ -170,7 +173,8 @@ FROM build-python-private AS api-private-test
170173

171174
COPY api /build/
172175

173-
RUN make install-packages opts='--with dev' && \
176+
RUN --mount=type=cache,target=/root/.cache/uv \
177+
make install-packages opts='--extra dev --extra saml --extra auth-controller --extra ldap --extra workflows --extra licensing --extra release-pipelines' && \
174178
make integrate-private-tests && \
175179
git config --global --unset credential.helper && \
176180
rm -f ${HOME}/.git-credentials

api/Makefile

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ COMPOSE_PROJECT_NAME ?= flagsmith
77

88
DOTENV_OVERRIDE_FILE ?= .env
99

10-
POETRY_VERSION ?= 2.2.1
10+
UV_VERSION ?= $(shell python -c 'import tomllib; print(tomllib.load(open("pyproject.toml","rb"))["tool"]["uv"]["required-version"].lstrip("="))')
1111

1212
SAML_REVISION ?= v1.6.6
1313
RBAC_REVISION ?= v0.13.0
@@ -21,32 +21,32 @@ OPENAPI_FORMAT_VERSION ?= 1.23.0
2121
install-pip:
2222
python -m pip -q install --upgrade pip
2323

24-
.PHONY: install-poetry
25-
install-poetry:
26-
python -m pip -q install poetry==${POETRY_VERSION}
24+
.PHONY: install-uv
25+
install-uv:
26+
python -m pip -q install uv==${UV_VERSION}
2727

2828
.PHONY: install-packages
2929
install-packages:
30-
poetry install --no-root $(opts)
30+
uv sync --frozen $(opts)
3131

3232
.PHONY: install-private-modules
3333
install-private-modules:
34-
$(eval SITE_PACKAGES_DIR := $(shell poetry run python -c 'import site; print(site.getsitepackages()[0])'))
34+
$(eval SITE_PACKAGES_DIR := $(shell uv run python -c 'import site; print(site.getsitepackages()[0])'))
3535
rm -rf $(SITE_PACKAGES_DIR)/saml $(SITE_PACKAGES_DIR)/rbac
3636
git clone https://github.com/flagsmith/flagsmith-saml --depth 1 --branch ${SAML_REVISION} && mv ./flagsmith-saml/saml $(SITE_PACKAGES_DIR)
3737
git clone https://github.com/flagsmith/flagsmith-rbac --depth 1 --branch ${RBAC_REVISION} && mv ./flagsmith-rbac/rbac $(SITE_PACKAGES_DIR)
3838
rm -rf ./flagsmith-saml ./flagsmith-rbac
3939

4040
.PHONY: install
41-
install: install-pip install-poetry install-packages
41+
install: install-pip install-uv install-packages
4242

4343
.PHONY: lint
4444
lint:
45-
poetry run pre-commit run -a
45+
uv run pre-commit run -a
4646

4747
.PHONY: typecheck
4848
typecheck:
49-
poetry run mypy .
49+
uv run mypy .
5050

5151
.PHONY: docker-up
5252
docker-up:
@@ -71,44 +71,44 @@ docker-build:
7171

7272
.PHONY: wait-for-db
7373
wait-for-db:
74-
poetry run python manage.py waitfordb
75-
poetry run python manage.py waitfordb --database analytics
74+
uv run python manage.py waitfordb
75+
uv run python manage.py waitfordb --database analytics
7676

7777
.PHONY: test
7878
test: docker-up wait-for-db
79-
poetry run pytest $(opts)
79+
uv run pytest $(opts)
8080

8181
.PHONY: django-make-migrations
8282
django-make-migrations: docker-up wait-for-db
83-
poetry run python manage.py waitfordb
84-
poetry run python manage.py makemigrations $(opts)
83+
uv run python manage.py waitfordb
84+
uv run python manage.py makemigrations $(opts)
8585

8686
.PHONY: django-squash-migrations
8787
django-squash-migrations: docker-up wait-for-db
88-
poetry run python manage.py waitfordb
89-
poetry run python manage.py squashmigrations $(opts)
88+
uv run python manage.py waitfordb
89+
uv run python manage.py squashmigrations $(opts)
9090

9191
.PHONY: django-migrate
9292
django-migrate: docker-up wait-for-db
93-
poetry run python manage.py waitfordb
94-
poetry run python manage.py migrate
95-
poetry run python manage.py createcachetable
93+
uv run python manage.py waitfordb
94+
uv run python manage.py migrate
95+
uv run python manage.py createcachetable
9696

9797
.PHONY: django-shell
9898
django-shell:
99-
poetry run python manage.py shell_plus
99+
uv run python manage.py shell_plus
100100

101101
.PHONY: django-collect-static
102102
django-collect-static:
103-
poetry run python manage.py collectstatic --noinput
103+
uv run python manage.py collectstatic --noinput
104104

105105
.PHONY: serve
106106
serve: docker-up wait-for-db
107-
poetry run flagsmith start --reload api
107+
uv run flagsmith start --reload api
108108

109109
.PHONY: run-task-processor
110110
run-task-processor: docker-up wait-for-db
111-
poetry run flagsmith start --reload --bind 0.0.0.0:8001 task-processor
111+
uv run flagsmith start --reload --bind 0.0.0.0:8001 task-processor
112112

113113
.PHONY: serve-with-task-processor
114114
serve-with-task-processor: TASK_RUN_METHOD=TASK_PROCESSOR
@@ -118,7 +118,7 @@ serve-with-task-processor:
118118
.PHONY: generate-flagsmith-sdk-openapi
119119
generate-flagsmith-sdk-openapi: OPENAPI_SERVERS=[{"url": "https://edge.api.flagsmith.com", "description": "Flagsmith Edge API"}]
120120
generate-flagsmith-sdk-openapi:
121-
poetry run python manage.py spectacular | \
121+
uv run python manage.py spectacular | \
122122
npx openapi-format@${OPENAPI_FORMAT_VERSION} /dev/fd/0 \
123123
--filterFile openapi-filter-flagsmith-sdk.yml \
124124
--output ../sdk/openapi.yaml
@@ -153,8 +153,8 @@ generate-grafana-client-types:
153153

154154
.PHONY: integrate-private-tests
155155
integrate-private-tests:
156-
$(eval WORKFLOW_REVISION := $(shell grep -A 1 "\[tool.poetry.group.workflows.dependencies\]" pyproject.toml | awk -F '"' '{printf $$4}'))
157-
$(eval AUTH_CONTROLLER_REVISION := $(shell grep -A 1 "\[tool.poetry.group.auth-controller.dependencies\]" pyproject.toml | awk -F '"' '{printf $$4}'))
156+
$(eval WORKFLOW_REVISION := $(shell uv run python -c 'import tomllib; d=tomllib.load(open("pyproject.toml","rb")); s=d.get("tool",{}).get("uv",{}).get("sources",{}).get("workflows-logic",{}); print(s.get("tag") or s.get("rev") or "")'))
157+
$(eval AUTH_CONTROLLER_REVISION := $(shell uv run python -c 'import tomllib; d=tomllib.load(open("pyproject.toml","rb")); s=d.get("tool",{}).get("uv",{}).get("sources",{}).get("auth-controller",{}); print(s.get("tag") or s.get("rev") or "")'))
158158

159159
git clone https://github.com/flagsmith/flagsmith-saml --depth 1 --branch ${SAML_REVISION} && mv ./flagsmith-saml/tests tests/saml_tests
160160
git clone https://github.com/flagsmith/flagsmith-rbac --depth 1 --branch ${RBAC_REVISION} && mv ./flagsmith-rbac/tests tests/rbac_tests
@@ -164,13 +164,13 @@ integrate-private-tests:
164164

165165
.PHONY: generate-docs
166166
generate-docs: generate-flagsmith-sdk-openapi
167-
poetry run flagsmith docgen metrics > ../docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md
168-
poetry run flagsmith docgen events > ../docs/docs/deployment-self-hosting/observability/_events-catalogue.md
167+
uv run flagsmith docgen metrics > ../docs/docs/deployment-self-hosting/observability/_metrics-catalogue.md
168+
uv run flagsmith docgen events > ../docs/docs/deployment-self-hosting/observability/_events-catalogue.md
169169

170170
.PHONY: add-known-sdk-version
171171
add-known-sdk-version:
172-
poetry run python scripts/add-known-sdk-version.py $(opts)
172+
uv run python scripts/add-known-sdk-version.py $(opts)
173173

174174
.PHONY: generate-mcp-spec
175175
generate-mcp-spec:
176-
poetry run python manage.py spectacular --generator-class api.openapi.MCPSchemaGenerator --file mcp_openapi.yaml
176+
uv run python manage.py spectacular --generator-class api.openapi.MCPSchemaGenerator --file mcp_openapi.yaml

0 commit comments

Comments
 (0)