Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/scripts/report-scheduled-failure.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ gh label create "$LABEL" \
existing=$(gh issue list --label "$LABEL" --state open --json number --jq '.[0].number // empty')

if [ -z "$existing" ]; then
body=$(printf '%s\n\n%s\n\n%s\n\n%s\n\n%s' \
body=$(printf '%s\n\n%s\n\n%s\n\n%s' \
"The scheduled dependency check failed." \
"First failing run: ${RUN_URL}" \
"Likely cause, if a lint or pytest job failed: a dev or lint dependency (ruff, ty, eof-fixer, pytest, typing-extensions) released a breaking change. Reproduce locally with \`just install\` then \`just lint\` and \`just test\`." \
"Likely cause, if a lowest-direct job failed: a declared floor in \`pyproject.toml\` no longer installs or bootstraps, usually because an upstream package changed metadata under it. Reproduce with \`uv pip install --resolution lowest-direct '.[<extras>]'\` then \`python scripts/floor_smoke.py <target>\`, reading both off the failing job's matrix." \
"Close this issue once fixed. The next scheduled failure will open a fresh issue.")
gh issue create --title "$TITLE" --label "$LABEL" --body "$body"
else
Expand Down
41 changes: 0 additions & 41 deletions .github/scripts/require-floor-run.sh

This file was deleted.

15 changes: 3 additions & 12 deletions .github/workflows/_checks.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
name: checks
on:
workflow_call:
inputs:
lowest-direct:
description: >-
Run the declared dependency floors. Off for PRs: the job resolves direct dependencies at
their floor and transitives at their newest, so a release published upstream today can
turn it red for reasons no PR here caused. scheduled.yml turns it on, where that failure
opens a tracking issue instead of blocking a merge.
type: boolean
default: false
workflow_call: {}

jobs:
lint:
Expand Down Expand Up @@ -131,7 +122,7 @@ jobs:
if [ -n "$failed" ]; then echo "::error::extras failed isolated install+import:$failed"; exit 1; fi
echo "all extras install and import in isolation"

lowest-direct:
floors:
# Every other job resolves newest, so a declared floor is a claim nothing checks. This one
# pins each direct dependency to the floor pyproject.toml declares and bootstraps against it.
# Per framework rather than all-extras at once: a floor declared in one extra pulls the shared
Expand All @@ -141,7 +132,7 @@ jobs:
# deliberately did not install as unresolved. So nothing type-checks at the floor - an
# annotation naming an optional dependency's internals has to span the declared range, and only
# a human checks that.
if: inputs.lowest-direct
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand Down
30 changes: 5 additions & 25 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,22 @@ name: Release
# GitHub Release. Replaces the old `on: release: published` publish.yml — that
# trigger is removed so the published Release this workflow creates can't re-fire
# it (double-publish). The tag is the sole entry point; by convention a tag is
# only cut off a green main, so the sole in-workflow gate is floors-gate below,
# covering the one check that never runs on pull requests.
# only cut off a green main, so there is no in-workflow CI gate.
on:
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+' # stable: 2.7.2
- '[0-9]+.[0-9]+.[0-9]+[a-z]+[0-9]+' # pre-release: 2.0.0rc1, 4.0.0a2

permissions: {}
# contents: write -> create the GitHub Release; id-token: write -> OIDC for PyPI Trusted Publishing.
permissions:
contents: write
id-token: write

jobs:
# Gates the tag on the dependency floors, which _checks.yml runs only for scheduled.yml, never
# for pull requests. A floor break can therefore merge with every check green, which is how the
# crash in 1.8.0 reached PyPI (#245). Placed before release so a failure costs nothing.
floors-gate:
runs-on: ubuntu-latest
# contents: read -> the history the ancestor check walks; actions: read -> list workflow runs.
permissions:
contents: read
actions: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # the ancestor check needs history, not just the tagged commit
- run: .github/scripts/require-floor-run.sh
env:
GH_TOKEN: ${{ github.token }}

release:
needs: floors-gate
runs-on: ubuntu-latest
environment: pypi # scopes the PyPI Trusted Publisher; hook for approval rules
# contents: write -> create the GitHub Release; id-token: write -> OIDC for PyPI Trusted Publishing.
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v6
- uses: extractions/setup-just@v4
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/scheduled.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: scheduled-dep-check
on:
schedule:
# Daily: both resolutions here are unpinned, so an upstream release can break main
# Daily: the resolution here is unpinned, so an upstream release can break main
# between runs. Daily bounds that window at a day and attributes the failure to upstream
# (a tracking issue) instead of to whichever pull request happens to run next.
- cron: "0 6 * * *" # daily 06:00 UTC
Expand All @@ -14,8 +14,6 @@ concurrency:
jobs:
checks:
uses: ./.github/workflows/_checks.yml
with:
lowest-direct: true

report-failure:
needs: checks
Expand Down
Loading