From 8290c3face8bf5d6580f07bb9892bcbb9af90b37 Mon Sep 17 00:00:00 2001 From: konstin Date: Mon, 25 Aug 2025 18:20:46 +0200 Subject: [PATCH 01/11] Update uv_build version automatically In https://github.com/pypa/packaging.python.org/pull/1880, the concern was raised that the uv_build upper bound in the docs will go stale. This PR adds a GitHub Actions workflow that automatically updates the version daily with the latest uv(-build) version. I tested this change on my fork, but I unfortunately can't test this in pypa/packaging.python.org itself. --- .github/workflows/cron.yml | 26 ++++++++++++++ scripts/update_uv_build_version.py | 56 ++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 scripts/update_uv_build_version.py diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 8870bb70b..6074c3fbb 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -5,10 +5,36 @@ name: Cron on: schedule: - cron: "0 6 * * *" # daily at 6am + workflow_dispatch: jobs: test: if: github.repository_owner == 'pypa' # suppress noise in forks uses: ./.github/workflows/test.yml + update-uv-build-version: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 + - name: Update uv_build version + id: update_script + run: uv run scripts/update_uv_build_version.py + - # If there are no changes, no pull request will be created and the action exits silently. + name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Update uv_build version to ${{ steps.update_script.outputs.version }} + title: Update uv_build version to ${{ steps.update_script.outputs.version }} + body: | + Automated update of uv_build version bounds for uv ${{ steps.update_script.outputs.version }}. + + This PR was created automatically by the cron workflow, ping `@konstin` for problems. + branch: bot/update-uv-build-version + delete-branch: true + ... diff --git a/scripts/update_uv_build_version.py b/scripts/update_uv_build_version.py new file mode 100644 index 000000000..f71cb821a --- /dev/null +++ b/scripts/update_uv_build_version.py @@ -0,0 +1,56 @@ +# /// script +# requires-python = ">=3.12" +# dependencies = [ +# "httpx>=0.28.1,<0.29", +# "packaging>=25.0", +# ] +# /// +import re +from pathlib import Path + +import httpx +from packaging.utils import parse_wheel_filename +from packaging.version import Version + + +def main(): + response = httpx.get( + "https://pypi.org/simple/uv-build/", + headers={"Accept": "application/vnd.pypi.simple.v1+json"}, + ) + response.raise_for_status() + data = response.json() + current_release = None + for file in data["files"]: + if not file["filename"].endswith(".whl"): + continue + _name, version, _build, _tags = parse_wheel_filename(file["filename"]) + if version.is_prerelease: + continue + if current_release is None or version > current_release: + current_release = version + + [major, minor, _patch] = current_release.release + if major != 0: + raise NotImplementedError("The script needs to be updated for uv 1.x") + upper_bound = Version(f"{major}.{minor + 1}.{0}") + + repository_root = Path(__file__).parent.parent + existing = repository_root.joinpath("source/shared/build-backend-tabs.rst").read_text() + replacement = f'requires = ["uv_build >= {current_release}, <{upper_bound}"]' + searcher = re.compile(re.escape('requires = ["uv_build') + ".*" + re.escape('"]')) + if not searcher.search(existing): + raise RuntimeError("Could not `uv-build` entry") + updated = searcher.sub(replacement, existing) + + if existing != updated: + print("Updating source/shared/build-backend-tabs.rst") + Path("source/shared/build-backend-tabs.rst").write_text(updated) + print(f"::set-output name=version::{current_release}") + print(f"::set-output name=updated::true") + else: + print("Already up-to-date source/shared/build-backend-tabs.rst") + print(f"::set-output name=updated::false") + +if __name__ == '__main__': + main() From a23f1a2d451339755fed3e96bf70a7cb7972378e Mon Sep 17 00:00:00 2001 From: konsti Date: Tue, 26 Aug 2025 11:08:09 +0200 Subject: [PATCH 02/11] Update scripts/update_uv_build_version.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- scripts/update_uv_build_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_uv_build_version.py b/scripts/update_uv_build_version.py index f71cb821a..02eee3434 100644 --- a/scripts/update_uv_build_version.py +++ b/scripts/update_uv_build_version.py @@ -1,5 +1,5 @@ # /// script -# requires-python = ">=3.12" +# requires-python = ">= 3.12" # dependencies = [ # "httpx>=0.28.1,<0.29", # "packaging>=25.0", From 7500df28a55d361c11f971c842beaf30a97995f2 Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 26 Aug 2025 11:12:28 +0200 Subject: [PATCH 03/11] Review --- .github/workflows/cron.yml | 27 ------------- .github/workflows/update-uv-build-version.yml | 39 +++++++++++++++++++ scripts/update_uv_build_version.py | 18 ++++++--- 3 files changed, 52 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/update-uv-build-version.yml diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 6074c3fbb..18a63caba 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -11,30 +11,3 @@ jobs: test: if: github.repository_owner == 'pypa' # suppress noise in forks uses: ./.github/workflows/test.yml - - update-uv-build-version: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - steps: - - uses: actions/checkout@v4 - - uses: astral-sh/setup-uv@v5 - - name: Update uv_build version - id: update_script - run: uv run scripts/update_uv_build_version.py - - # If there are no changes, no pull request will be created and the action exits silently. - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 - with: - token: ${{ secrets.GITHUB_TOKEN }} - commit-message: Update uv_build version to ${{ steps.update_script.outputs.version }} - title: Update uv_build version to ${{ steps.update_script.outputs.version }} - body: | - Automated update of uv_build version bounds for uv ${{ steps.update_script.outputs.version }}. - - This PR was created automatically by the cron workflow, ping `@konstin` for problems. - branch: bot/update-uv-build-version - delete-branch: true - -... diff --git a/.github/workflows/update-uv-build-version.yml b/.github/workflows/update-uv-build-version.yml new file mode 100644 index 000000000..8586ecd11 --- /dev/null +++ b/.github/workflows/update-uv-build-version.yml @@ -0,0 +1,39 @@ +--- + +name: Cron + +on: + schedule: + - cron: "0 6 * * 1" # mondays at 6am + workflow_dispatch: + +jobs: + update-uv-build-version: + name: Update uv_build version + if: github.repository_owner == 'pypa' # suppress noise in forks + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + - name: Set up uv + uses: astral-sh/setup-uv@v5 + - name: Update uv_build version + id: update_script + run: uv run scripts/update_uv_build_version.py + - # If there are no changes, no pull request will be created and the action exits silently. + name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Update uv_build version to ${{ steps.update_script.outputs.version }} + title: Update uv_build version to ${{ steps.update_script.outputs.version }} + body: | + Automated update of uv_build version bounds for uv ${{ steps.update_script.outputs.version }}. + + This PR was created automatically by the cron workflow, ping `@konstin` for problems. + branch: bot/update-uv-build-version + delete-branch: true + +... diff --git a/scripts/update_uv_build_version.py b/scripts/update_uv_build_version.py index 02eee3434..8dfd90da8 100644 --- a/scripts/update_uv_build_version.py +++ b/scripts/update_uv_build_version.py @@ -5,6 +5,7 @@ # "packaging>=25.0", # ] # /// +import os import re from pathlib import Path @@ -36,7 +37,9 @@ def main(): upper_bound = Version(f"{major}.{minor + 1}.{0}") repository_root = Path(__file__).parent.parent - existing = repository_root.joinpath("source/shared/build-backend-tabs.rst").read_text() + existing = repository_root.joinpath( + "source/shared/build-backend-tabs.rst" + ).read_text() replacement = f'requires = ["uv_build >= {current_release}, <{upper_bound}"]' searcher = re.compile(re.escape('requires = ["uv_build') + ".*" + re.escape('"]')) if not searcher.search(existing): @@ -46,11 +49,16 @@ def main(): if existing != updated: print("Updating source/shared/build-backend-tabs.rst") Path("source/shared/build-backend-tabs.rst").write_text(updated) - print(f"::set-output name=version::{current_release}") - print(f"::set-output name=updated::true") + if github_output := os.environ.get("GITHUB_OUTPUT"): + with open(github_output, "a") as f: + f.write(f"version={current_release}\n") + f.write(f"updated=true\n") else: print("Already up-to-date source/shared/build-backend-tabs.rst") - print(f"::set-output name=updated::false") + if github_output := os.environ.get("GITHUB_OUTPUT"): + with open(github_output, "a") as f: + f.write(f"updated=false\n") -if __name__ == '__main__': + +if __name__ == "__main__": main() From 77d8c71c11a55da7c26b251b4c61cb5d0d957fd7 Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 26 Aug 2025 11:14:06 +0200 Subject: [PATCH 04/11] Use same `actions/checkout@v4` as zizmor job --- .github/workflows/update-uv-build-version.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/update-uv-build-version.yml b/.github/workflows/update-uv-build-version.yml index 8586ecd11..54f5ad211 100644 --- a/.github/workflows/update-uv-build-version.yml +++ b/.github/workflows/update-uv-build-version.yml @@ -16,7 +16,10 @@ jobs: contents: write pull-requests: write steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false - name: Set up uv uses: astral-sh/setup-uv@v5 - name: Update uv_build version From 7df08f4ed3a9788801c99635de0ef276389c64cd Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 26 Aug 2025 11:17:32 +0200 Subject: [PATCH 05/11] Linters --- .github/workflows/update-uv-build-version.yml | 2 +- scripts/update_uv_build_version.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/update-uv-build-version.yml b/.github/workflows/update-uv-build-version.yml index 54f5ad211..184497047 100644 --- a/.github/workflows/update-uv-build-version.yml +++ b/.github/workflows/update-uv-build-version.yml @@ -34,7 +34,7 @@ jobs: title: Update uv_build version to ${{ steps.update_script.outputs.version }} body: | Automated update of uv_build version bounds for uv ${{ steps.update_script.outputs.version }}. - + This PR was created automatically by the cron workflow, ping `@konstin` for problems. branch: bot/update-uv-build-version delete-branch: true diff --git a/scripts/update_uv_build_version.py b/scripts/update_uv_build_version.py index 8dfd90da8..816ab9061 100644 --- a/scripts/update_uv_build_version.py +++ b/scripts/update_uv_build_version.py @@ -52,12 +52,12 @@ def main(): if github_output := os.environ.get("GITHUB_OUTPUT"): with open(github_output, "a") as f: f.write(f"version={current_release}\n") - f.write(f"updated=true\n") + f.write("updated=true\n") else: print("Already up-to-date source/shared/build-backend-tabs.rst") if github_output := os.environ.get("GITHUB_OUTPUT"): with open(github_output, "a") as f: - f.write(f"updated=false\n") + f.write("updated=false\n") if __name__ == "__main__": From 64977629a37b34ab04876706069a88846134cf26 Mon Sep 17 00:00:00 2001 From: konstin Date: Tue, 26 Aug 2025 11:18:25 +0200 Subject: [PATCH 06/11] Undo accidental cosmetic change --- .github/workflows/cron.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 18a63caba..f1eddccb5 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -11,3 +11,5 @@ jobs: test: if: github.repository_owner == 'pypa' # suppress noise in forks uses: ./.github/workflows/test.yml + +... From 31d727712bb38af2513dc7f741e47f188ed96f98 Mon Sep 17 00:00:00 2001 From: konsti Date: Thu, 28 Aug 2025 16:51:57 +0200 Subject: [PATCH 07/11] Update .github/workflows/update-uv-build-version.yml Co-authored-by: Alyssa Coghlan --- .github/workflows/update-uv-build-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-uv-build-version.yml b/.github/workflows/update-uv-build-version.yml index 184497047..a3cead001 100644 --- a/.github/workflows/update-uv-build-version.yml +++ b/.github/workflows/update-uv-build-version.yml @@ -1,6 +1,6 @@ --- -name: Cron +name: Update uv build version on: schedule: From ce4251e775d04f5577ad9b7a843703c3b87bd06c Mon Sep 17 00:00:00 2001 From: konstin Date: Mon, 15 Sep 2025 20:57:37 +0200 Subject: [PATCH 08/11] Create PR as draft --- .github/workflows/update-uv-build-version.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/update-uv-build-version.yml b/.github/workflows/update-uv-build-version.yml index a3cead001..8aadc7052 100644 --- a/.github/workflows/update-uv-build-version.yml +++ b/.github/workflows/update-uv-build-version.yml @@ -32,6 +32,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} commit-message: Update uv_build version to ${{ steps.update_script.outputs.version }} title: Update uv_build version to ${{ steps.update_script.outputs.version }} + draft: true # Trigger CI by un-drafting the PR, otherwise `GITHUB_TOKEN` PRs don't trigger CI. body: | Automated update of uv_build version bounds for uv ${{ steps.update_script.outputs.version }}. From bceb2644a302db55733492e4489883699f961921 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 15 Sep 2025 21:59:01 -0400 Subject: [PATCH 09/11] ci: remove workflow_dispatch from cron.yml Signed-off-by: William Woodruff --- .github/workflows/cron.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index f1eddccb5..8870bb70b 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -5,7 +5,6 @@ name: Cron on: schedule: - cron: "0 6 * * *" # daily at 6am - workflow_dispatch: jobs: test: From c7ffbccf513399c2cddd0dbed7183d4835429419 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 15 Sep 2025 22:06:31 -0400 Subject: [PATCH 10/11] ci: add pull_request event subtypes Signed-off-by: William Woodruff --- .github/workflows/test.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8503ca720..172fed713 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,12 +6,19 @@ on: branches-ignore: - gh-readonly-queue/** # Temporary merge queue-related GH-made branches pull_request: + types: + - opened # default + - synchronize # default + - reopened # default + - ready_for_review # used in PRs created from GitHub Actions workflows workflow_call: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true +permissions: {} + jobs: build: name: ${{ matrix.noxenv }} From b036f24d6fefac29c3b95a7b8810b62117529f5c Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Mon, 15 Sep 2025 22:06:53 -0400 Subject: [PATCH 11/11] update_uv_build_version: remove unneeded format Signed-off-by: William Woodruff --- scripts/update_uv_build_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_uv_build_version.py b/scripts/update_uv_build_version.py index 816ab9061..69fefba27 100644 --- a/scripts/update_uv_build_version.py +++ b/scripts/update_uv_build_version.py @@ -34,7 +34,7 @@ def main(): [major, minor, _patch] = current_release.release if major != 0: raise NotImplementedError("The script needs to be updated for uv 1.x") - upper_bound = Version(f"{major}.{minor + 1}.{0}") + upper_bound = Version(f"{major}.{minor + 1}.0") repository_root = Path(__file__).parent.parent existing = repository_root.joinpath(