You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Server-side deployment notifications (deploy succeeded/failed → push), not polling-only #6
The deploy badge (GitHub Actions latest run) is polled by the console only while it's open. The user wants to be told when a DEPLOY finishes (so they can check the live version) — independent of whether they're watching, and distinct from the agent's reply.
Approach
A durable watcher (Cloudflare Workflow or cron) per repo-with-github that detects a run transitioning to completed (success/failure) and fires a notification via the existing notifyUser (in-app + web push), deep-linked to the repo + the run URL.
Dedup so one run notifies once; respect the per-device push dedup already in place.
Gated: only for repos with a github_repo + the GitHub App installed.
Scope
A poll/cron that tracks last-seen run id per repo in D1; on a new completed run, notifyUser("✅ Deployed #N" / "❌ Build failed #N", url=run.html_url).
Acceptance
Push a commit → CI runs → when it goes green/red you get ONE notification (even with the console closed) linking to the run.
Shipped in 11b60ba (migration 0076 applied on deploy).
A cron sweep (lib/deploy-watch.ts) walks repos with a github_repo, fetches the latest Actions run through the existing shared client, and fires the existing notifyUser (in-app + web push) deep-linked to the run.
The decision is a pure, separately-tested function because one case is genuinely dangerous: first sight of a repo must never notify. Every repo that already exists has a completed run behind it, so a watcher that notified on whatever it found first would — on the very deploy that shipped this — have pushed every user a notification about a build they ran days ago. It seeds the watermark silently and speaks only for the next run.
Meeting the acceptance criterion ("ONE notification") needed two things, not one: the watermark, and NOT advancing it on queued/in_progress — otherwise a run gets consumed before it has anything to report.
Bounded and rotating: 20 repos per sweep, least-recently-checked first, and last_deploy_checked_at is stamped on every check including silent ones. Leaving it unset on a no-op would pin the batch to the same repos and starve the tail. GitHub is rate-limited per installation and this runs on the per-minute cron.
Registered as a fourth independent waitUntil: it reaches an external API, making it the likeliest of the sweeps to be slow or rate-limited, and it must not be able to stop the trigger sweep or the delivery pump from draining.
Gating is by github_repo presence; the installation token is used when available (private repos need it, public ones otherwise burn the shared 60/hr cap). Per-device push dedup is unchanged — this rides the existing notifyUser path.
Activity
feat(notifications): tell the user when a deploy finishes, even with …
serge-ivo commentedon Aug 6, 2026
Shipped in 11b60ba (migration 0076 applied on deploy).
A cron sweep (
lib/deploy-watch.ts) walks repos with agithub_repo, fetches the latest Actions run through the existing shared client, and fires the existingnotifyUser(in-app + web push) deep-linked to the run.The decision is a pure, separately-tested function because one case is genuinely dangerous: first sight of a repo must never notify. Every repo that already exists has a completed run behind it, so a watcher that notified on whatever it found first would — on the very deploy that shipped this — have pushed every user a notification about a build they ran days ago. It seeds the watermark silently and speaks only for the next run.
Meeting the acceptance criterion ("ONE notification") needed two things, not one: the watermark, and NOT advancing it on
queued/in_progress— otherwise a run gets consumed before it has anything to report.Bounded and rotating: 20 repos per sweep, least-recently-checked first, and
last_deploy_checked_atis stamped on every check including silent ones. Leaving it unset on a no-op would pin the batch to the same repos and starve the tail. GitHub is rate-limited per installation and this runs on the per-minute cron.Registered as a fourth independent
waitUntil: it reaches an external API, making it the likeliest of the sweeps to be slow or rate-limited, and it must not be able to stop the trigger sweep or the delivery pump from draining.Gating is by
github_repopresence; the installation token is used when available (private repos need it, public ones otherwise burn the shared 60/hr cap). Per-device push dedup is unchanged — this rides the existingnotifyUserpath.feat(console): choose which notifications reach you, minus the ones y…
feat(mcp): tools/list says which tools only read, so a host stops tre…