diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e2fbfd17..0643b2b4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,14 @@ jobs: unlocked-resolution: name: Unlocked resolution uses: ./.github/workflows/unlocked-resolution.yml + # unlocked-resolution.yml's `report-scheduled-failure` job declares + # `issues: write` (#1242). It never fires here — it is gated on the schedule + # event — but a reusable call must grant every scope the callee declares or + # GitHub refuses the run as a `startup_failure` with no log + # (check-workflow-calls.yml; same as deploy.yml's call of test.yml, #1241). + permissions: + contents: read + issues: write build: name: Build sdist + wheel diff --git a/.github/workflows/unlocked-resolution.yml b/.github/workflows/unlocked-resolution.yml index bde05ecf..55fe15a2 100644 --- a/.github/workflows/unlocked-resolution.yml +++ b/.github/workflows/unlocked-resolution.yml @@ -16,8 +16,9 @@ name: Unlocked Resolution # The schedule is the point: this break arrives from upstream, not from a commit # of ours, so it can appear on a day nobody pushed anything. # -# Known limitation: a red scheduled run notifies via GitHub's normal workflow -# notifications; it does not open an issue. Deliberate — one moving part. +# A red scheduled run opens or updates an issue (#1239, #1242) via the shared +# scheduled-failure-issue.yml job below — the Actions tab alone is not a signal +# anyone reads on a day nobody pushed. on: schedule: @@ -80,3 +81,15 @@ jobs: tests/adapters/test_sdk_kwargs_guard_614.py \ tests/adapters/test_model_defaults_guard_1112.py \ -q + + # Same signal test.yml and web-ui-audit.yml use (#1239): a red scheduled run + # has no PR to be red on, so open or update the one issue for this workflow. + # `failure()` only, as in the other two callers: a cancelled run is usually a + # deliberate cancel, and the next morning's run reports on its own. + report-scheduled-failure: + name: Report scheduled failure + needs: [unlocked-install] + if: failure() && github.event_name == 'schedule' + uses: ./.github/workflows/scheduled-failure-issue.yml + permissions: + issues: write diff --git a/CLAUDE.md b/CLAUDE.md index 685758ee..79609d56 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -205,7 +205,9 @@ the lock. Before that, the **Unlocked Resolution** workflow throwaway env, and runs `cf --help` plus both SDK guards against *that* env. It runs daily on a schedule — this break arrives from upstream, so it can appear on a day nobody pushed — on PRs touching `pyproject.toml` or the guards, and as a -required gate on `release.yml`. `tests/ci/test_unlocked_resolution_guard_1169.py` +required gate on `release.yml`. A red *scheduled* run opens or updates an issue +via `scheduled-failure-issue.yml` (#1239, #1242), like the other two daily +checks. `tests/ci/test_unlocked_resolution_guard_1169.py` pins those properties. #1170 moved where the risk lives, so the #614 guard now carries two halves. The diff --git a/tests/ci/test_scheduled_failure_signal_1239.py b/tests/ci/test_scheduled_failure_signal_1239.py index b6bceff9..74de83d1 100644 --- a/tests/ci/test_scheduled_failure_signal_1239.py +++ b/tests/ci/test_scheduled_failure_signal_1239.py @@ -29,6 +29,7 @@ CALLERS = { "test.yml": ["test-summary", "e2e-browser-full", "e2e-backend-tests"], "web-ui-audit.yml": ["npm-audit"], + "unlocked-resolution.yml": ["unlocked-install"], }