Skip to content

Notifier: report only a job the machine's CI runner is running; clear a reclaim the job survived - #46

Merged
sodre merged 5 commits into
mainfrom
fix/reclaim-notifier-running-job-44
Nov 14, 2026
Merged

sodre merged 5 commits into
mainfrom
fix/reclaim-notifier-running-job-44

Conversation

@sodre

@sodre sodre commented Nov 14, 2026

Copy link
Copy Markdown
Member

Summary

Refs #44. The notifier reported a Spot reclaim for jobs that were not lost. Two causes, two fixes:

 Spot interruption warning (EC2 or Fargate Spot)
   notifier
     read the machine's tags (the job it was launched for, or took in a swap)
+    GET the job from GitHub
+    ignore unless the job is in_progress on THIS machine's CI runner   # idle runner: nothing to report
     POST check run "ci-runner / <job>" = failure
+    GET the job again; if it already succeeded, clear the check run

 workflow_job `completed` (GitHub already delivers it, ~3 deliveries per job)
   webhook
+    if success on a runner of this stack: invoke notifier async
+  notifier
+    find the reclaim failure(s) under the job's run, set them neutral   # job survived the 2-minute warning, or a re-run passed
  • Idle CI runner: another CI runner took its launch job, so its tags still named a job it never ran.
  • Job survives the warning: AWS warns 2 minutes ahead and the job can finish inside that. The check run turns neutral. A re-run that passes clears the earlier attempt's report too.
  • Webhook gains lambda:InvokeFunction on the notifier only. Notifier timeout stays 30 s.

Evidence

  • Before: the live logs for the two stale checks on a consumer PR: i-0c718b… had no Swap and no job on its runner, yet the notifier reported its launch job. i-042f94… ran its job, which passed 95 s after the warning, and the check stayed failure.
    After: the tests that pin each case (make test: 182 pass, 0 skipped, including the aws-emulator ones):
idle runner (launch job taken by another runner)        -> no check run     (was: failure posted)
job queued / already completed                          -> no check run
swapped runner (re-tagged job in_progress on its runner)-> names the job it took
job succeeded after the warning (webhook word)          -> check run neutral (was: stays failure)
job already succeeded when the report is posted         -> neutral
re-run attempt succeeds, first attempt's report stands  -> neutral
job failed / cancelled                                  -> stays failure (webhook never forwards it)
success word for a repo outside the org                 -> ignored, no GitHub call

Merge Danger

Door: two-way

Merging to main deploys nothing: the live stack runs whatever was deployed last. Reverting the commits restores the old notifier.

Blast Radius: notifier

After the next deploy, every successful CI runner job invokes the notifier, which mints an App token and lists check runs (about 300 GitHub calls an hour at today's volume). A failed invoke makes the webhook answer 502 for that completed delivery; redeliver it from the App's settings. Known gap: a job that finishes just after the post-report re-read, with a failed invoke, stays failure until redelivered.

🤖 Generated with Claude Code

sodre and others added 5 commits November 14, 2026 18:24
… a reclaim the job survived (#44)

An idle CI runner (another one served its launch job) kept its launch tags,
so a reclaim was reported for a job it never ran. The notifier now reads the
tagged job from GitHub and posts only if it is in_progress on the machine's
own runner.

A job can also finish inside AWS's 2-minute warning. After posting, the
notifier watches the job for 150 s and turns the check run neutral when the
job ends with success. The Lambda's timeout goes from 30 s to 200 s.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…view fixes (#44)

A report left standing because the watch ended or a GitHub call failed
mid-watch is now turned neutral by a retry or a later event once its job has
finished with success. Names say what they hold (interval, looks, titles),
the glossary's Spot reclaim allows a surviving job, and tests that repeated
the EC2 fixtures share them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tches (#44)

Watching the job for 150 s inside the notifier held a Lambda per reclaim and
missed a job that ended after the watch. GitHub already delivers
workflow_job completed to the webhook (about 3 deliveries per job), so the
webhook now invokes the notifier when a job succeeds on a runner of this
stack, and the notifier turns that job's reclaim report neutral. The notifier
re-reads the job once after posting, to close the race with that word, and a
retry or later event still clears a standing report.

The notifier's timeout returns to 30 s. The webhook gains lambda:InvokeFunction
on the notifier.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…job name everywhere (#44)

A re-run's job has a new id, so its first attempt's reclaim report stayed
failure after the re-run passed. The webhook's word now clears every reclaim
failure under the job's run with the job's name. The notifier names the check
run from GitHub's job name for EC2 too, so a tag cut at 256 characters cannot
miss the webhook's word. One launchJobOf() reads a runner's name in the
webhook. stack.md lists the webhook's new grant and the failure path.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…n the notifier (#44)

jobSucceeded now ignores a repo outside GITHUB_ORG before any GitHub call, as
a reclaim event does. A template test pins the webhook's lambda:InvokeFunction
to the notifier alone, and NOTIFIER_FUNCTION on the webhook.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sodre
sodre merged commit 53b8fe1 into main Nov 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reclaim notifier reports a job its machine never ran, or one that survives the warning

1 participant