Skip to content

Commit 518b5cd

Browse files
Pin operator_metrics.schedules.* scheduler-role keys on the dashboard payload
Add a feature test in V2DashboardStatsControllerTest that asserts the frozen operator_metrics.schedules.* keys exposed by the workflow v2 package — active, paused, missed, oldest_overdue_at, max_overdue_ms, fires_total, failures_total — so contract drift between the workflow snapshot and the Waterline scheduler-role section of the dashboard fails loudly in CI once a workflow alpha that emits the keys is published. The test self-skips when the resolved workflow alpha predates the scheduler-role metrics surface (today's alpha.8 does not expose the keys). The assertions pin automatically at the moment an alpha that exposes operator_metrics.schedules lands, following the same pattern used for the HealthCheck category contract.
1 parent dabe8eb commit 518b5cd

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

tests/Feature/V2DashboardStatsControllerTest.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,4 +660,53 @@ public function testIndexIncludesCommandContractBackfillMetrics(): void
660660
->assertJsonPath('operator_metrics.command_contracts.backfill_available_runs', 1)
661661
->assertJsonPath('operator_metrics.command_contracts.backfill_unavailable_runs', 1);
662662
}
663+
664+
public function testIndexExposesSchedulerRoleMetricsWhenWorkflowAlphaSupportsThem(): void
665+
{
666+
config()->set('waterline.engine_source', 'v2');
667+
668+
$response = $this->get('/waterline/api/stats')->assertStatus(200);
669+
670+
$schedules = $response->json('operator_metrics.schedules');
671+
672+
if ($schedules === null) {
673+
// Older workflow alpha releases predate the scheduler-role
674+
// metrics contract frozen in docs/architecture/rollout-safety.md.
675+
// The dashboard gracefully hides the scheduler-role section when
676+
// those keys are absent. Skip until an alpha that emits the
677+
// schedules snapshot is published; the assertions below will
678+
// pin automatically at that point.
679+
$this->markTestSkipped(
680+
'Resolved workflow package does not yet expose operator_metrics.schedules; '
681+
. 'test is a no-op until a workflow alpha that emits the scheduler-role '
682+
. 'metrics contract is published.'
683+
);
684+
}
685+
686+
$this->assertIsArray($schedules);
687+
foreach (
688+
['active', 'paused', 'missed', 'oldest_overdue_at', 'max_overdue_ms', 'fires_total', 'failures_total']
689+
as $key
690+
) {
691+
$this->assertArrayHasKey(
692+
$key,
693+
$schedules,
694+
sprintf('operator_metrics.schedules.%s must be present in the dashboard payload', $key),
695+
);
696+
}
697+
698+
$this->assertIsInt($schedules['active']);
699+
$this->assertIsInt($schedules['paused']);
700+
$this->assertIsInt($schedules['missed']);
701+
$this->assertIsInt($schedules['fires_total']);
702+
$this->assertIsInt($schedules['failures_total']);
703+
$this->assertTrue(
704+
$schedules['oldest_overdue_at'] === null || is_string($schedules['oldest_overdue_at']),
705+
'operator_metrics.schedules.oldest_overdue_at must be null or ISO-8601 string',
706+
);
707+
$this->assertTrue(
708+
$schedules['max_overdue_ms'] === null || is_int($schedules['max_overdue_ms']),
709+
'operator_metrics.schedules.max_overdue_ms must be null or integer milliseconds',
710+
);
711+
}
663712
}

0 commit comments

Comments
 (0)