From b54ba9cd365c1b98a40091f9af21553981181a59 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Fri, 25 Sep 2026 18:38:56 +0300 Subject: [PATCH 1/2] docs(standard): run floors on pull requests only, not on the schedule --- docs/standard.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/standard.md b/docs/standard.md index 374c1a4..a29a797 100644 --- a/docs/standard.md +++ b/docs/standard.md @@ -117,8 +117,8 @@ a one-line change in every repo, made in one sweep. Two workflows per repo, both thin: - `ci.yml` on `push` to `main` and on `pull_request`, with `concurrency` cancelling superseded runs. -- `scheduled.yml` weekly and on `workflow_dispatch`, running the same checks and, on a scheduled - failure, opening or updating a tracking issue in the repo. This is how a dependency release or a +- `scheduled.yml` daily and on `workflow_dispatch`, running the same checks except `floors` and, + on a scheduled failure, opening or updating a tracking issue in the repo. This is how a dependency release or a new Python that breaks the build becomes a ticket without anyone watching. Both call the repo's own reusable `_checks.yml`, which has these jobs: @@ -148,11 +148,20 @@ same versions can still disagree on whether those versions install, which is wha The rest is the repo's call. Run the full suite at the floors where they can carry it and an import smoke test where they cannot; drop a matrix entry no upstream wheel covers, as `compose2pod` drops -`3.14t` for PyYAML. Like every other job, `floors` runs from both `ci.yml` and `scheduled.yml`. -Resolving direct dependencies low and transitive ones high does expose it to an upstream release -that no pull request caused, but that is not a difference in kind: `install` upgrades the lockfile -(section 2), so `pytest` resolves fresh on every run too, and the org already accepts that exposure -on a pull request. +`3.14t` for PyYAML. + +`floors` gates every pull request and is skipped on the schedule, with +`if: github.event_name != 'schedule'` on the job (a called workflow sees its caller's `github` +context). The gate belongs on the pull request because that is where a floor breaks: a diff starts +using an API newer than the declared floor. `lite-bootstrap` ran its floors only on the schedule +and shipped such a break to PyPI +([lite-bootstrap#245](https://github.com/modern-python/lite-bootstrap/issues/245)). A scheduled run +adds nothing a pull request did not already check. The direct dependencies sit at their floors, +which do not change, so all a cron run could newly catch is a transitive release breaking an old +floor, while the scheduled `pytest` already catches the newest releases, which are what users +install. Resolving transitive dependencies at their newest does expose a pull request to an +upstream release it did not cause, but `install` upgrades the lockfile (section 2), so `pytest` +carries the same exposure and the org already accepts it. `_checks.yml` is per repo by decision, not by omission. A shared workflow in `modern-python/.github` was built and proven From 4207816dbad144e515f0737fad58103649c520e3 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Fri, 25 Sep 2026 18:39:10 +0300 Subject: [PATCH 2/2] docs(standard): rewrap the scheduled.yml bullet --- docs/standard.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/standard.md b/docs/standard.md index a29a797..73b1eb4 100644 --- a/docs/standard.md +++ b/docs/standard.md @@ -118,8 +118,9 @@ Two workflows per repo, both thin: - `ci.yml` on `push` to `main` and on `pull_request`, with `concurrency` cancelling superseded runs. - `scheduled.yml` daily and on `workflow_dispatch`, running the same checks except `floors` and, - on a scheduled failure, opening or updating a tracking issue in the repo. This is how a dependency release or a - new Python that breaks the build becomes a ticket without anyone watching. + on a scheduled failure, opening or updating a tracking issue in the repo. This is how a + dependency release or a new Python that breaks the build becomes a ticket without anyone + watching. Both call the repo's own reusable `_checks.yml`, which has these jobs: