Skip to content

Commit 7d14a97

Browse files
authored
ci(github): centralize uv setup and update certifi (#721)
* ci: constrain uv and update certifi * ci: update uv pins to 0.13.4 * ci: verify uv project version requirement * ci: format dependency sync verifier * ci: centralize uv setup on project constraint * ci: format dependency sync checker
1 parent 5d965dd commit 7d14a97

15 files changed

Lines changed: 87 additions & 70 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: Set up uv
2+
description: Install the lowest uv version allowed by the root pyproject.toml.
3+
runs:
4+
using: composite
5+
steps:
6+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
7+
with:
8+
version-file: pyproject.toml
9+
resolution-strategy: lowest

‎.github/dependabot.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ updates:
5959
patterns:
6060
- "*"
6161
# Compose manifests live at the root; Dockerfiles live under src/.
62-
# Update uv in the Dockerfiles together with every workflow's UV_VERSION manually.
62+
# Keep the Dockerfile uv image tags at the lower bound in pyproject.toml.
6363
- package-ecosystem: "docker-compose"
6464
directory: "/"
6565
schedule:

‎.github/verify_deps_sync.py‎

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
PRECOMMIT_CONFIG = ".pre-commit-config.yaml"
2424
PYPROJECTS = ["./pyproject.toml", "./client/pyproject.toml"]
2525
TRACKED_DEPS = ("uv", "ruff", "ty", "prek")
26+
UV_REQUIRED_VERSION_PROJECTS = {"./pyproject.toml"}
2627

2728
logger = logging.getLogger(__name__)
2829
logger.setLevel(logging.DEBUG)
@@ -52,10 +53,31 @@ def add_dep(deps: dict[str, list[dict[str, str]]], dep: str, file: str, group: s
5253
deps[pkg].append({"file": file, "version": parsed["version"], "group": group})
5354

5455

55-
def add_pyproject_deps(deps: dict[str, list[dict[str, str]]], pyproject_path: str) -> None:
56+
def uv_lower_bound(required_version: str, source: str, troubles: list[str]) -> str | None:
57+
versions = re.findall(r"(?:^|,)\s*>=\s*(\d+(?:\.\d+){1,2})(?=\s*(?:,|$))", required_version)
58+
if len(versions) != 1:
59+
troubles.append(
60+
f"{source}: [tool.uv].required-version must have one >= lower bound, found {required_version!r}"
61+
)
62+
return None
63+
return versions[0]
64+
65+
66+
def add_pyproject_deps(deps: dict[str, list[dict[str, str]]], pyproject_path: str, troubles: list[str]) -> None:
5667
with Path(pyproject_path).open("rb") as f:
5768
pyproject: dict[str, Any] = tomllib.load(f)
5869

70+
tool_config = pyproject.get("tool", {})
71+
uv_config = tool_config.get("uv") if isinstance(tool_config, dict) else None
72+
if pyproject_path in UV_REQUIRED_VERSION_PROJECTS or uv_config is not None:
73+
required_version = uv_config.get("required-version") if isinstance(uv_config, dict) else None
74+
if isinstance(required_version, str):
75+
lower_bound = uv_lower_bound(required_version, pyproject_path, troubles)
76+
if lower_bound is not None:
77+
deps["uv"].append({"file": pyproject_path, "version": f"=={lower_bound}", "group": "required-version"})
78+
else:
79+
troubles.append(f"{pyproject_path}: [tool.uv].required-version is missing")
80+
5981
project = pyproject.get("project", {})
6082
if isinstance(project, dict):
6183
dependencies = project.get("dependencies", [])
@@ -80,6 +102,8 @@ def add_pyproject_deps(deps: dict[str, list[dict[str, str]]], pyproject_path: st
80102

81103
def main() -> None:
82104
deps: dict[str, list[dict[str, str]]] = {dep: [] for dep in TRACKED_DEPS}
105+
troubles = []
106+
setup_action_calls = 0
83107

84108
for dockerfile in DOCKERFILES:
85109
dockerfile_content = Path(dockerfile).read_text(encoding="utf-8")
@@ -105,20 +129,41 @@ def main() -> None:
105129
})
106130

107131
for pyproject_path in PYPROJECTS:
108-
add_pyproject_deps(deps, pyproject_path)
132+
add_pyproject_deps(deps, pyproject_path, troubles)
109133

110134
for workflow_file in Path(".github/workflows").glob("*.yml"):
111-
with workflow_file.open("r", encoding="utf-8") as f:
112-
workflow = yaml.safe_load(f) or {}
113-
env = workflow.get("env", {})
114-
if "UV_VERSION" in env:
115-
deps["uv"].append({
116-
"file": str(workflow_file),
117-
"version": f"=={env['UV_VERSION'].lstrip('v')}",
118-
"group": "workflow",
119-
})
135+
workflow_content = workflow_file.read_text(encoding="utf-8")
136+
if "astral-sh/setup-uv@" in workflow_content:
137+
troubles.append(f"{workflow_file}: use the shared .github/actions/setup-uv action")
138+
setup_action_calls += workflow_content.count("./.github/actions/setup-uv")
139+
140+
action_path = Path(".github/actions/setup-uv/action.yml")
141+
action = yaml.safe_load(action_path.read_text(encoding="utf-8"))
142+
setup_steps = [
143+
step
144+
for step in action.get("runs", {}).get("steps", [])
145+
if str(step.get("uses", "")).startswith("astral-sh/setup-uv@")
146+
]
147+
if setup_action_calls == 0:
148+
troubles.append(".github/workflows: no shared .github/actions/setup-uv calls found")
149+
if len(setup_steps) != 1:
150+
troubles.append(f"{action_path}: expected one astral-sh/setup-uv step")
151+
else:
152+
setup = setup_steps[0].get("with", {})
153+
if (
154+
"version" in setup
155+
or setup.get("version-file") != "pyproject.toml"
156+
or setup.get("resolution-strategy") != "lowest"
157+
):
158+
troubles.append(f"{action_path}: install uv from pyproject.toml with resolution-strategy: lowest")
159+
else:
160+
root = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
161+
required = root.get("tool", {}).get("uv", {}).get("required-version")
162+
if isinstance(required, str):
163+
lower_bound = uv_lower_bound(required, "pyproject.toml", troubles)
164+
if lower_bound is not None:
165+
deps["uv"].append({"file": str(action_path), "version": f"=={lower_bound}", "group": "setup-uv"})
120166

121-
troubles = []
122167
for dep, versions in deps.items():
123168
if not versions:
124169
troubles.append(f"{dep}: no tracked version found")

‎.github/workflows/builds.yml‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ on:
88

99
env:
1010
PYTHON_VERSION: "3.11"
11-
UV_VERSION: "0.11.14"
1211

1312
jobs:
1413
docker:
@@ -19,9 +18,7 @@ jobs:
1918
with:
2019
python-version: ${{ env.PYTHON_VERSION }}
2120
architecture: x64
22-
- uses: astral-sh/setup-uv@v7
23-
with:
24-
version: ${{ env.UV_VERSION }}
21+
- uses: ./.github/actions/setup-uv
2522
- name: Build, run & check docker
2623
env:
2724
SUPERADMIN_LOGIN: dummy_login
@@ -51,9 +48,7 @@ jobs:
5148
with:
5249
python-version: ${{ matrix.python }}
5350
architecture: x64
54-
- uses: astral-sh/setup-uv@v7
55-
with:
56-
version: ${{ env.UV_VERSION }}
51+
- uses: ./.github/actions/setup-uv
5752
- name: Install project
5853
run: |
5954
uv pip install --system -e client/.

‎.github/workflows/docs.yml‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ on:
33
push:
44
branches: main
55

6-
env:
7-
UV_VERSION: "0.11.14"
8-
96
jobs:
107
gh-pages:
118
runs-on: ubuntu-latest
@@ -17,9 +14,7 @@ jobs:
1714
with:
1815
python-version: "3.10"
1916
architecture: x64
20-
- uses: astral-sh/setup-uv@v7
21-
with:
22-
version: ${{ env.UV_VERSION }}
17+
- uses: ./.github/actions/setup-uv
2318
- name: Install dependencies
2419
run: uv pip install --system -e "client/.[docs]"
2520

‎.github/workflows/publish.yml‎

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ on:
66

77
env:
88
PYTHON_VERSION: "3.11"
9-
UV_VERSION: "0.11.14"
109

1110
jobs:
1211
pypi:
@@ -18,9 +17,7 @@ jobs:
1817
with:
1918
python-version: ${{ env.PYTHON_VERSION }}
2019
architecture: x64
21-
- uses: astral-sh/setup-uv@v7
22-
with:
23-
version: ${{ env.UV_VERSION }}
20+
- uses: ./.github/actions/setup-uv
2421
- name: Install dependencies
2522
run: uv pip install --system setuptools wheel twine --upgrade
2623
- name: Build and publish
@@ -47,9 +44,7 @@ jobs:
4744
with:
4845
python-version: ${{ matrix.python }}
4946
architecture: x64
50-
- uses: astral-sh/setup-uv@v7
51-
with:
52-
version: ${{ env.UV_VERSION }}
47+
- uses: ./.github/actions/setup-uv
5348
- name: Install package
5449
run: |
5550
uv pip install --system pyroclient

‎.github/workflows/pull_requests.yml‎

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ on:
44
pull_request:
55
branches: main
66

7-
env:
8-
UV_VERSION: "0.11.14"
9-
107
jobs:
118
docs-client:
129
runs-on: ubuntu-latest
@@ -18,9 +15,7 @@ jobs:
1815
with:
1916
python-version: "3.10"
2017
architecture: x64
21-
- uses: astral-sh/setup-uv@v7
22-
with:
23-
version: ${{ env.UV_VERSION }}
18+
- uses: ./.github/actions/setup-uv
2419
- name: Install dependencies
2520
run: uv pip install --system -e "client/.[docs]"
2621

‎.github/workflows/push.yml‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ env:
99
BACKEND_IMAGE_NAME: alert-api
1010
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_LOGIN }}
1111
PYTHON_VERSION: "3.11"
12-
UV_VERSION: "0.11.14"
1312

1413
jobs:
1514
docker:
@@ -20,9 +19,7 @@ jobs:
2019
with:
2120
python-version: ${{ env.PYTHON_VERSION }}
2221
architecture: x64
23-
- uses: astral-sh/setup-uv@v7
24-
with:
25-
version: ${{ env.UV_VERSION }}
22+
- uses: ./.github/actions/setup-uv
2623
- name: Resolve image tag
2724
run: |
2825
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then

‎.github/workflows/scripts.yml‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ on:
88

99
env:
1010
PYTHON_VERSION: "3.11"
11-
UV_VERSION: "0.11.14"
1211

1312
jobs:
1413
end-to-end:
@@ -19,9 +18,7 @@ jobs:
1918
with:
2019
python-version: ${{ env.PYTHON_VERSION }}
2120
architecture: x64
22-
- uses: astral-sh/setup-uv@v7
23-
with:
24-
version: ${{ env.UV_VERSION }}
21+
- uses: ./.github/actions/setup-uv
2522
- name: Run the backend & the test
2623
env:
2724
SUPERUSER_LOGIN: dummy_login

‎.github/workflows/style.yml‎

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ on:
88

99
env:
1010
PYTHON_VERSION: "3.11"
11-
UV_VERSION: "0.11.14"
1211

1312
jobs:
1413
ruff:
@@ -19,9 +18,7 @@ jobs:
1918
with:
2019
python-version: ${{ env.PYTHON_VERSION }}
2120
architecture: x64
22-
- uses: astral-sh/setup-uv@v7
23-
with:
24-
version: ${{ env.UV_VERSION }}
21+
- uses: ./.github/actions/setup-uv
2522
- name: Run ruff
2623
run: |
2724
uv run --group quality ruff --version
@@ -35,9 +32,7 @@ jobs:
3532
with:
3633
python-version: ${{ env.PYTHON_VERSION }}
3734
architecture: x64
38-
- uses: astral-sh/setup-uv@v7
39-
with:
40-
version: ${{ env.UV_VERSION }}
35+
- uses: ./.github/actions/setup-uv
4136
- name: Run ty
4237
run: |
4338
uv run --group quality ty --version
@@ -51,9 +46,7 @@ jobs:
5146
with:
5247
python-version: ${{ env.PYTHON_VERSION }}
5348
architecture: x64
54-
- uses: astral-sh/setup-uv@v7
55-
with:
56-
version: ${{ env.UV_VERSION }}
49+
- uses: ./.github/actions/setup-uv
5750
- name: Run prek hooks
5851
run: |
5952
uv run --group quality prek --version

0 commit comments

Comments
 (0)