From 304c98954e9cab98e9f0a9839ddfbc0a4cf844ac Mon Sep 17 00:00:00 2001 From: Alice Wong Date: Thu, 14 May 2026 14:02:41 +0100 Subject: [PATCH 1/3] Add specifiers to dependencies This is required for Renovate to manage our dependencies --- pyproject.toml | 16 ++++++++-------- uv.lock | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 152ba2c..7add4c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,9 +6,9 @@ requires-python = ">=3.14" dependencies = [ - "pymssql", - "structlog", - "sqlglot", + "pymssql<=2.3.13", + "sqlglot<=30.6.0", + "structlog<=25.5.0", ] [tool.coverage.run] @@ -64,9 +64,9 @@ exclude-newer-package = {} [dependency-groups] dev = [ - "coverage", - "docker", - "pre-commit", - "pytest", - "ruff", + "coverage<=7.13.5", + "docker<=7.1.0", + "pre-commit<=4.6.0", + "pytest<=9.0.3", + "ruff<=0.15.12", ] diff --git a/uv.lock b/uv.lock index 3d57c15..d2c22ae 100644 --- a/uv.lock +++ b/uv.lock @@ -382,18 +382,18 @@ dev = [ [package.metadata] requires-dist = [ - { name = "pymssql" }, - { name = "sqlglot" }, - { name = "structlog" }, + { name = "pymssql", specifier = "<=2.3.13" }, + { name = "sqlglot", specifier = "<=30.6.0" }, + { name = "structlog", specifier = "<=25.5.0" }, ] [package.metadata.requires-dev] dev = [ - { name = "coverage" }, - { name = "docker" }, - { name = "pre-commit" }, - { name = "pytest" }, - { name = "ruff" }, + { name = "coverage", specifier = "<=7.13.5" }, + { name = "docker", specifier = "<=7.1.0" }, + { name = "pre-commit", specifier = "<=4.6.0" }, + { name = "pytest", specifier = "<=9.0.3" }, + { name = "ruff", specifier = "<=0.15.12" }, ] [[package]] From e0f9cef856eedc8f7609ef5db1dec0da60671f25 Mon Sep 17 00:00:00 2001 From: Alice Wong Date: Thu, 14 May 2026 14:26:33 +0100 Subject: [PATCH 2/3] Remove `exclude-newer` and references to it - Remove `exclude-newer` from the `pyproject.toml` - Rewrite the `just` recipes that manage or use `exclude-newer` - Remove references to `exclude-newer` in the developer docs --- DEVELOPERS.md | 40 ++-------------------------------------- justfile | 45 +++++++-------------------------------------- pyproject.toml | 6 ------ uv.lock | 3 --- 4 files changed, 9 insertions(+), 85 deletions(-) diff --git a/DEVELOPERS.md b/DEVELOPERS.md index 6f20bc5..4dbb49c 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -66,54 +66,18 @@ just docker/build-for-os-cli ## Dependency management Dependencies are managed with `uv`. - -### Overview See the [uv documentation](https://docs.astral.sh/uv/concepts/projects/dependencies) for details on usage. -Commands for adding, removing or modifying constraints of dependencies will automatically respect the -global timestamp cutoff specified in the `pyproject.toml`: -```toml -[tool.uv] -exclude-newer = "YYYY-MM-DDTHH:MM:SSZ" -``` + Changes to dependencies should be made via `uv` commands, or by modifying `pyproject.toml` directly followed by [locking and syncing](https://docs.astral.sh/uv/concepts/projects/sync/) via `uv` or `just` commands like `just devenv` or `just upgrade-all`. You should not modify `uv.lock` manually. Note that `uv.lock` must be reproducible from `pyproject.toml`. Otherwise, `just check` will fail. -If `just check` errors saying that the timestamps must match, you might have modified one file but not the other: +If `just check` errors, you might have modified one file but not the other: - If you modified `pyproject.toml`, you must update `uv.lock` via `uv lock` / `just upgrade-all` or similar. - If you did not modify `pyproject.toml` but have changes in `uv.lock`, you should revert the changes to `uv.lock`, modify `pyproject.toml` as you require, then run `uv lock` to update `uv.lock`. -The timestamp cutoff should usually be set to midnight UTC of a past date. -In general, the date is expected to be between 7 and 14 days ago as a result of automated weekly dependency updates. - -If you require a package version that is newer than the cutoff allows, you can either manually bump the global cutoff -date or add a package-specific timestamp cutoff. Both options are described below. - -### Manually bumping the cutoff date -The cutoff timestamp can be modified to a more recent date either manually in the `pyproject.toml` -or with `just bump-uv-cutoff `. -For example, to set the cutoff to today's date and upgrade all dependencies, run: -``` -just bump-uv-cutoff 0 -just upgrade-all -``` - -### Adding a package-specific timestamp cutoff -It is possible to specify a package-specific timestamp cutoff in addition to the global cutoff. -This should be done in the `pyproject.toml` to ensure reproducible installs; -see the [uv documentation](https://docs.astral.sh/uv/reference/settings/#exclude-newer-package) for details. -If set, the package-specific cutoff will take precedence over the global cutoff regardless of which one is more recent. - -You should not set a package-specific cutoff that is older than the global cutoff - use a version -constraint instead. -If there is good reason to set a package-specific cutoff that is more recent than the global cutoff, -**care should be taken to ensure that the package-specific cutoff is manually removed once it is over 7 days old**, -as otherwise future automated updates of that package will be indefinitely blocked. -Currently no automated tooling is in place to enforce removal of stale package-specific cutoffs. - - ## Tagging a new version OpenSAFELY SQL Runner follows [Semantic Versioning, v2.0.0][2]. diff --git a/justfile b/justfile index 13a464b..0ad02b0 100644 --- a/justfile +++ b/justfile @@ -33,47 +33,20 @@ install-precommit: upgrade-package package: && uvmirror devenv uv lock --upgrade-package {{ package }} -# Upgrade all packages to the latest versions as of the cutoff in pyproject.toml -upgrade-all: && uvmirror devenv - uv lock --upgrade +# Upgrade all packages to the latest versions +upgrade-all cooldown="7 days ago": && devenv + uv lock --upgrade --exclude-newer "{{ cooldown }}" # update the uv mirror requirements file uvmirror file="requirements.uvmirror.txt": rm -f {{ file }} uv export --format requirements-txt --frozen --no-hashes --all-groups --all-extras > {{ file }} -# Move the cutoff date in pyproject.toml to N days ago (default: 7) at midnight UTC -bump-uv-cutoff days="7": - #!/usr/bin/env -S uvx --with tomlkit python3.13 - # Note we specify the python version here and we don't care if it's different to - # the .python-version; we need 3.11+ for the datetime code used. - - import datetime - import tomlkit - - with open("pyproject.toml", "rb") as f: - content = tomlkit.load(f) - - new_datetime = ( - datetime.datetime.now(datetime.UTC) - datetime.timedelta(days=int("{{ days }}")) - ).replace(hour=0, minute=0, second=0, microsecond=0) - new_timestamp = new_datetime.strftime("%Y-%m-%dT%H:%M:%SZ") - if existing_timestamp := content["tool"]["uv"].get("exclude-newer"): - if new_datetime < datetime.datetime.fromisoformat(existing_timestamp): - print( - f"Existing cutoff {existing_timestamp} is more recent than {new_timestamp}, not updating." - ) - exit(0) - content["tool"]["uv"]["exclude-newer"] = new_timestamp - - with open("pyproject.toml", "w") as f: - tomlkit.dump(content, f) - # This is the default input command to update-dependencies action # https://github.com/bennettoxford/update-dependencies-action -# Bump the timestamp cutoff to midnight UTC 7 days ago and upgrade all dependencies -update-dependencies: bump-uv-cutoff upgrade-all +# recipe is used for doing lockfileMaintenance via update-dependencies action, until min release age is respected fo uv +update-dependencies: upgrade-all && uvmirror # *args is variadic, 0 or more. This allows us to do `just test -k match`, for example. @@ -128,14 +101,10 @@ check: check-lockfile: #!/usr/bin/env bash set -euo pipefail - # Make sure dates in pyproject.toml and uv.lock are in sync + # Make sure lockfile is reproducible from pyproject.toml unset UV_EXCLUDE_NEWER rc=0 - uv lock --check || rc=$? - if test "$rc" != "0" ; then - echo "Timestamp cutoffs in uv.lock must match those in pyproject.toml. See DEVELOPERS.md for details and hints." >&2 - exit $rc - fi + uv lock --check # Fix formatting, import sort ordering, and justfile fix: diff --git a/pyproject.toml b/pyproject.toml index 7add4c0..cdc0594 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,12 +56,6 @@ extend-ignore = [ ] isort.lines-after-imports = 2 -# Note: any `exclude-newer-package` timestamps should be removed if > 7 days old -# See https://github.com/opensafely-core/repo-template/blob/main/DEVELOPERS.md for details -[tool.uv] -exclude-newer = "2026-04-29T00:00:00Z" -exclude-newer-package = {} - [dependency-groups] dev = [ "coverage<=7.13.5", diff --git a/uv.lock b/uv.lock index d2c22ae..2413b20 100644 --- a/uv.lock +++ b/uv.lock @@ -2,9 +2,6 @@ version = 1 revision = 3 requires-python = ">=3.14" -[options] -exclude-newer = "2026-04-29T00:00:00Z" - [[package]] name = "certifi" version = "2026.4.22" From 808a21162bd36057c4f05c6e8797c59c59c61a4e Mon Sep 17 00:00:00 2001 From: Alice Wong Date: Thu, 14 May 2026 14:12:40 +0100 Subject: [PATCH 3/3] Remove dependabot.yml We will use Renovate to manage our dependencies --- .github/dependabot.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 3dca800..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,17 +0,0 @@ -version: 2 - -updates: - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "monthly" - cooldown: - default-days: 7 - - - package-ecosystem: "uv" - directory: "/" - schedule: - interval: "daily" - # Security updates only - open-pull-requests-limit: 0