Skip to content

feat(AF-985): escalate idle deployment reviews and nudge reviewers - #1189

Merged
babltiga merged 2 commits into
mainfrom
feature/AF-985-deploygov-review-escalation
Oct 23, 2026
Merged

babltiga merged 2 commits into
mainfrom
feature/AF-985-deploygov-review-escalation

Conversation

@babltiga

Copy link
Copy Markdown
Contributor

Closes #985 (part of epic #983).

What

  • V204: deployment_requests.escalated_at / last_nudged_at and two partial scan indexes (no index on last_nudged_at, same reasoning as V144).
  • DeploygovProperties + DeploygovConfiguration: the module's single @ConfigurationProperties("accessflow.deploygov") record (timeoutCheck, releaseCheck, escalationPollInterval; one constructor). New key escalation-poll-interval / ACCESSFLOW_DEPLOYGOV_ESCALATION_POLL_INTERVAL (PT5M).
  • DeploymentReviewEscalationJob (ShedLock deploymentReviewEscalationJob, injected Clock, per-row failures swallowed), the twin of ApiReviewEscalationJob. Native scans resolve the plan exactly as the timeout scan does (environment override, else pipeline) and use created_at as the clock.
  • DeploymentRequestStateService.markEscalated / markNudged: row-locked, status re-checked, stamp → save → system audit row (DEPLOYMENT_REVIEW_ESCALATED / DEPLOYMENT_REVIEW_NUDGED, null actor, trigger=escalation|nudge) → DeploymentReviewEscalatedEvent / DeploymentReviewNudgedEvent. Notify-only.
  • Notifications reuse REVIEW_ESCALATED / REVIEW_NUDGE (no new NotificationEventType). deploymentRecipients gets explicit cases: nudge goes to the eligible reviewers minus anyone who has decided (new DeploymentNotificationLookupService.findDecidedReviewerUserIds); escalation goes to those plus active org admins; the submitter is never a recipient.

Beyond the issue text (found while wiring it)

  • Org-wide channels for deployment contexts. resolveChannels looked up plan channels by datasourceId, which is the pipeline id on a deployment context, so these would have reached zero Slack/PagerDuty channels. Deployment contexts now fan out org-wide like every other deployment event, which is what makes REVIEW_STALLED page as the issue intends.
  • No email for deployment reminders. The review-escalated / review-nudge templates are query-shaped (SQL preview, query type). The existing apigov carve-out in EmailNotificationStrategy is extended to deployment contexts for these two types. Deployment events with their own templates still mail. An org whose only channel is email gets these reminders in-app only.
  • Wording.
    • The chat-factory and ticket nudge title changes from "Query" to "Request" (this also applies to query/API nudges).
    • The PagerDuty REVIEW_ESCALATED summary names the pipeline on a deployment.
    • The bell routes deployment escalations and nudges to /reviews?tab=deployments and renders a deployment-worded nudge (new REVIEW_NUDGE_deployment key in all 7 locales).
  • The audit log filter list gains the two new actions.

Tests

  • Unit tests:
    • DeploymentReviewEscalationJobTest and DeploygovPropertiesTest (Binder + defaults).
    • Extended DeploymentRequestStateServiceTest, NotificationContextBuilderTest (nudge = undecided only; escalation + admins; submitter-admin excluded) and DeploymentNotificationListenerTest.
    • DefaultDeploymentNotificationLookupServiceTest, NotificationDispatcherTest, EmailNotificationStrategyTest, DeploymentNotificationTest, PagerDutyPayloadFactoryTest and NotificationBell.test.tsx.
  • DeploymentReviewEscalationIntegrationTest (Testcontainers):
    • seeds a plan with escalation_after_hours=1 and a 2h-old request, then runs the job;
    • asserts the stamps, the trigger=escalation / nudge audit rows with a null actor, and that a second pass is a no-op;
    • asserts eligibility is unchanged and the reviewer can still approve afterwards;
    • plus a plan with escalation off is never scanned.
  • mvn -o verify -Pcoverage: 11,499 tests, BUILD SUCCESS (95.2% lines / 84.0% branches). The late notification and bell fixes were re-run in isolation. ApplicationModulesTest, ApiPackageDependencyTest and MessagesParityTest pass. Frontend npm run build, typecheck and lint pass, as do the website guard tests. The help-corpus has no drift.

Docs

docs/03-data-model.md, 05-backend.md (job registry and #622 escalation prose), 08-notifications.md, 09-deployment.md (env var), 18-deployment-governance.md, CLAUDE.md, website/docs/configuration/review-workflows/index.html (dates already current), and regenerated help-corpus/.

Screenshots

No new screen. The only visible change is the wording and click target of a notification-bell row for deployment reminders, which NotificationBell.test.tsx covers. No screenshots.

Review notes

Independent reviewers ran before this PR. Fixed in response:

  • the website sentence that claimed reminders page PagerDuty (af-content-reviewer, blocker);
  • the bell routing deployment reminders to the queries tab and calling them "a query" (af-reviewer, blocker);
  • the PagerDuty summary calling a deployment "a query" (af-java-reviewer, af-reviewer);
  • the overstated row-lock claim for nudges (af-content-reviewer);
  • the event Javadoc width (af-java-reviewer, af-reviewer);
  • a missing email deliver() skip test (af-java-reviewer).

Remaining items:

  • af-reviewer: the scope grew beyond the issue (the org-wide routing, email suppression and "Request" wording listed above). Each is intentional and documented here.
  • af-content-reviewer: the docs/08 table cell for REVIEW_ESCALATED is dense.
  • af-frontend-reviewer: audit actions show as raw enum values in the filter. This is pre-existing for every action and out of scope.
  • af-verifier: DeploymentReviewEscalationJob has 6/8 branch coverage. This is advisory; there is no JaCoCo check rule.

@github-actions

Copy link
Copy Markdown
Contributor

Frontend Test Results

    1 files    342 suites   7m 11s ⏱️
2 982 tests 2 982 ✅ 0 💤 0 ❌
2 983 runs  2 983 ✅ 0 💤 0 ❌

Results for commit b1f0e90.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Frontend Coverage (frontend)

Status Category Percentage Covered / Total
🟢 Lines 96.56% (🎯 90%) 4333 / 4487
🟢 Statements 95.31% (🎯 90%) 4785 / 5020
🟢 Functions 94.84% (🎯 90%) 1324 / 1396
🟢 Branches 89.12% (🎯 80%) 3106 / 3485
File CoverageNo changed files found.
Generated in workflow #1607 for commit b1f0e90 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Backend Test Results

11 503 tests  +28   11 503 ✅ +28   12m 47s ⏱️ +57s
 1 226 suites + 3        0 💤 ± 0 
 1 226 files   + 3        0 ❌ ± 0 

Results for commit b1f0e90. ± Comparison against base commit 5a2d2be.

@github-actions

Copy link
Copy Markdown
Contributor

@babltiga
babltiga merged commit ce505dd into main Oct 23, 2026
35 checks passed
@babltiga
babltiga deleted the feature/AF-985-deploygov-review-escalation branch October 23, 2026 13:00
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.

deploygov: DeploymentReviewEscalationJob, reviewer nudges and DeploygovProperties

1 participant