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
2 changes: 1 addition & 1 deletion .github/workflows/links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
fail: false
# create-issue-from-file does not deduplicate — it calls issues.create
# unconditionally, so six weeks of one dead link is six identical issues. This is
# the same find-or-comment shape every repo's report-scheduled-failure.sh uses.
# the same find-or-comment shape as the shared report-scheduled-failure.yml.
- name: Open or update the tracking issue
if: steps.lychee.outputs.exit_code != 0
env:
Expand Down
33 changes: 33 additions & 0 deletions .github/workflows/report-scheduled-failure.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: report-scheduled-failure

# Called by every repo's scheduled.yml when its scheduled checks fail (standard CI2).
on:
workflow_call: {}

jobs:
report:
runs-on: ubuntu-latest
steps:
- name: Open or update the tracking issue
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
set -euo pipefail
LABEL="scheduled-failure"
# --force makes this idempotent: it creates the label, or updates it in place.
gh label create "$LABEL" \
--color "FBCA04" \
--description "Scheduled dependency check failures" \
--force
existing=$(gh issue list --label "$LABEL" --state open --json number --jq '.[0].number // empty')
if [ -z "$existing" ]; then
gh issue create --title "Scheduled dependency check failed" --label "$LABEL" --body "$(printf '%s\n\n%s\n\n%s\n\n%s' \
"The scheduled dependency check failed." \
"First failing run: ${RUN_URL}" \
"Likely cause: a new release of a dependency or of Python broke the build; the failing job in the run shows where. Reproduce locally with \`just install\`, then \`just lint\` and \`just test\`." \
"Close this issue once fixed. The next scheduled failure will open a fresh issue.")"
else
gh issue comment "$existing" --body "Failed again: ${RUN_URL}"
fi
18 changes: 16 additions & 2 deletions docs/standard.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,24 @@ superseded runs.

`scheduled.yml` MUST run daily and on `workflow_dispatch`, running the same checks as `ci.yml`
except `floors` ([CI6](#CI6)). On a scheduled failure it MUST open or update a tracking issue in the
repo.
repo with this job, byte for byte, and a repo MUST NOT keep its own report script:

```yaml
report-failure:
needs: checks
if: failure() && github.event_name == 'schedule'
permissions:
issues: write
uses: modern-python/.github/.github/workflows/report-scheduled-failure.yml@main
```

*Why:* a dependency release or a new Python that breaks the build becomes a ticket without anyone
watching.
watching. The report is shared because the per-repo copies drifted: each named its own list of
likely culprits, and several listed a dependency the repo does not have. The issue links the failing
run, which shows the failing job, so the shared text stays generic. It takes no inputs,
so it does not hit what sank a shared `_checks.yml` ([CI3](#CI3)). Like the ADR check
([CI9](#CI9)), it tracks `main` unpinned, so a change reaches every repo's next scheduled failure at
once.

### CI3 · Per-repo `_checks.yml` { #CI3 }

Expand Down
Loading