Some checks failed
Main Confidence / confidence (push) Failing after 3m36s
## Summary - add explicit Gitea workflow files for PR Fast Feedback, `dev` Confidence, Heavy Governance, and Browser lanes - extend the repo-truth lane support seams with workflow profiles, trigger-aware budget enforcement, artifact publication contracts, CI summaries, and failure classification - add deterministic artifact staging, new CI governance guard coverage, and Spec 210 planning/contracts/docs updates ## Validation - `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Guards/CiFastFeedbackWorkflowContractTest.php tests/Feature/Guards/CiConfidenceWorkflowContractTest.php tests/Feature/Guards/CiHeavyBrowserWorkflowContractTest.php tests/Feature/Guards/CiLaneFailureClassificationContractTest.php tests/Feature/Guards/FastFeedbackLaneContractTest.php tests/Feature/Guards/ConfidenceLaneContractTest.php tests/Feature/Guards/HeavyGovernanceLaneContractTest.php tests/Feature/Guards/BrowserLaneIsolationTest.php tests/Feature/Guards/FixtureLaneImpactBudgetTest.php tests/Feature/Guards/TestLaneManifestTest.php tests/Feature/Guards/TestLaneArtifactsContractTest.php tests/Feature/Guards/TestLaneCommandContractTest.php` - `./scripts/platform-test-lane fast-feedback` - `./scripts/platform-test-lane confidence` - `./scripts/platform-test-lane heavy-governance` - `./scripts/platform-test-lane browser` - `./scripts/platform-test-report fast-feedback` - `./scripts/platform-test-report confidence` ## Notes - scheduled Heavy Governance and Browser workflows stay gated behind `TENANTATLAS_ENABLE_HEAVY_GOVERNANCE_SCHEDULE=1` and `TENANTATLAS_ENABLE_BROWSER_SCHEDULE=1` - the remaining rollout evidence task is capturing the live Gitea run set this PR enables: PR Fast Feedback, `dev` Confidence, manual and scheduled Heavy Governance, and manual and scheduled Browser runs Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #243
195 lines
9.3 KiB
PHP
195 lines
9.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use Tests\Support\TestLaneManifest;
|
|
|
|
it('declares the six checked-in lanes with a single fast-feedback default and the spec 208 plus 209 metadata surfaces', function (): void {
|
|
$manifest = TestLaneManifest::manifest();
|
|
$laneIds = array_column($manifest['lanes'], 'id');
|
|
$defaultLanes = array_values(array_filter(
|
|
$manifest['lanes'],
|
|
static fn (array $lane): bool => $lane['defaultEntryPoint'] === true,
|
|
));
|
|
|
|
expect($manifest['version'])->toBe(2)
|
|
->and($manifest['artifactDirectory'])->toBe('storage/logs/test-lanes')
|
|
->and($manifest['mainlineBranch'])->toBe('dev')
|
|
->and($manifest)->toHaveKeys([
|
|
'classifications',
|
|
'families',
|
|
'mixedFileResolutions',
|
|
'placementRules',
|
|
'driftGuards',
|
|
'budgetTargets',
|
|
'lanes',
|
|
'workflowProfiles',
|
|
'laneBindings',
|
|
'budgetEnforcementProfiles',
|
|
'artifactPublicationContracts',
|
|
'failureClasses',
|
|
'familyBudgets',
|
|
'heavyGovernanceBudgetContract',
|
|
'heavyGovernanceHotspotInventory',
|
|
'heavyGovernanceDecompositionRecords',
|
|
'heavyGovernanceSlimmingDecisions',
|
|
'heavyGovernanceBudgetSnapshots',
|
|
'heavyGovernanceBudgetOutcome',
|
|
'heavyGovernanceAuthorGuidance',
|
|
])
|
|
->and($laneIds)->toEqualCanonicalizing([
|
|
'fast-feedback',
|
|
'confidence',
|
|
'browser',
|
|
'heavy-governance',
|
|
'profiling',
|
|
'junit',
|
|
])
|
|
->and($defaultLanes)->toHaveCount(1)
|
|
->and($defaultLanes[0]['id'])->toBe('fast-feedback');
|
|
});
|
|
|
|
it('publishes the CI workflow matrix, lane bindings, artifact contracts, and failure classes from repo truth', function (): void {
|
|
$workflowProfiles = collect(TestLaneManifest::workflowProfiles())->keyBy('workflowId');
|
|
$laneBindings = collect(TestLaneManifest::laneBindings())->keyBy('laneId');
|
|
$artifactContracts = collect(TestLaneManifest::artifactPublicationContracts())->keyBy('laneId');
|
|
$failureClasses = collect(TestLaneManifest::failureClasses())->keyBy('failureClassId');
|
|
|
|
expect($workflowProfiles->keys()->all())->toEqualCanonicalizing([
|
|
'pr-fast-feedback',
|
|
'main-confidence',
|
|
'heavy-governance-manual',
|
|
'heavy-governance-scheduled',
|
|
'browser-manual',
|
|
'browser-scheduled',
|
|
])
|
|
->and($workflowProfiles->get('pr-fast-feedback')['laneBindings'])->toBe(['fast-feedback'])
|
|
->and($workflowProfiles->get('main-confidence')['branchFilters'])->toBe(['dev'])
|
|
->and($workflowProfiles->get('heavy-governance-scheduled')['scheduleCron'])->toBe('17 4 * * 1-5')
|
|
->and($workflowProfiles->get('browser-scheduled')['scheduleCron'])->toBe('43 4 * * 1-5')
|
|
->and($laneBindings->get('fast-feedback')['executionWrapper'])->toBe('scripts/platform-test-lane')
|
|
->and($laneBindings->get('confidence')['requiredArtifacts'])->toEqualCanonicalizing(['summary.md', 'budget.json', 'report.json', 'junit.xml'])
|
|
->and($artifactContracts->get('fast-feedback')['retentionClass'])->toBe('pr-short')
|
|
->and($artifactContracts->get('browser')['uploadGroupName'])->toBe('browser-artifacts')
|
|
->and($failureClasses->keys()->all())->toEqualCanonicalizing([
|
|
'test-failure',
|
|
'wrapper-failure',
|
|
'budget-breach',
|
|
'artifact-publication-failure',
|
|
'infrastructure-failure',
|
|
]);
|
|
});
|
|
|
|
it('keeps every lane declaration populated with governance metadata, selectors, and segmented family expectations', function (): void {
|
|
foreach (TestLaneManifest::manifest()['lanes'] as $lane) {
|
|
expect(trim($lane['description']))->not->toBe('')
|
|
->and(trim($lane['intendedAudience']))->not->toBe('')
|
|
->and($lane['includedFamilies'])->not->toBeEmpty()
|
|
->and($lane['ownershipExpectations'])->not->toBe('')
|
|
->and($lane['artifacts'])->not->toBeEmpty()
|
|
->and($lane['budget']['thresholdSeconds'])->toBeGreaterThan(0)
|
|
->and($lane['budget']['baselineSource'])->toBeString()
|
|
->and($lane['dbStrategy']['connectionMode'])->toBeString();
|
|
|
|
$selectors = $lane['selectors'];
|
|
|
|
foreach ([
|
|
'includeSuites',
|
|
'includePaths',
|
|
'includeGroups',
|
|
'includeFiles',
|
|
'excludeSuites',
|
|
'excludePaths',
|
|
'excludeGroups',
|
|
'excludeFiles',
|
|
] as $selectorKey) {
|
|
expect($selectors)->toHaveKey($selectorKey);
|
|
}
|
|
}
|
|
|
|
expect(TestLaneManifest::lane('confidence')['includedFamilies'])->toContain('ui-light', 'ui-workflow')
|
|
->and(TestLaneManifest::lane('confidence')['excludedFamilies'])->toContain('surface-guard', 'discovery-heavy')
|
|
->and(TestLaneManifest::lane('heavy-governance')['includedFamilies'])->toContain('surface-guard', 'discovery-heavy');
|
|
});
|
|
|
|
it('exposes the spec 208 classification catalog and seeded family inventory with required metadata', function (): void {
|
|
$classifications = collect(TestLaneManifest::classifications())->keyBy('classificationId');
|
|
$families = collect(TestLaneManifest::families())->keyBy('familyId');
|
|
|
|
expect($classifications->keys()->all())->toEqualCanonicalizing([
|
|
'ui-light',
|
|
'ui-workflow',
|
|
'surface-guard',
|
|
'discovery-heavy',
|
|
'browser',
|
|
])
|
|
->and($classifications->get('browser')['allowedLaneIds'])->toBe(['browser'])
|
|
->and($classifications->get('surface-guard')['defaultLaneId'])->toBe('heavy-governance')
|
|
->and($classifications->get('discovery-heavy')['forbiddenLaneIds'])->toContain('fast-feedback', 'confidence')
|
|
->and($families->has('baseline-profile-start-surfaces'))->toBeTrue()
|
|
->and($families->has('findings-workflow-surfaces'))->toBeTrue()
|
|
->and($families->has('finding-bulk-actions-workflow'))->toBeTrue()
|
|
->and($families->has('drift-bulk-triage-all-matching'))->toBeTrue()
|
|
->and($families->has('policy-resource-admin-search-parity'))->toBeTrue()
|
|
->and($families->has('workspace-only-admin-surface-independence'))->toBeTrue()
|
|
->and($families->has('workspace-settings-slice-management'))->toBeTrue()
|
|
->and($families->has('baseline-compare-matrix-workflow'))->toBeTrue()
|
|
->and($families->has('browser-smoke'))->toBeTrue();
|
|
|
|
foreach (TestLaneManifest::families() as $family) {
|
|
expect(trim($family['purpose']))->not->toBe('')
|
|
->and(trim($family['currentLaneId']))->not->toBe('')
|
|
->and(trim($family['targetLaneId']))->not->toBe('')
|
|
->and($family['selectors'])->not->toBeEmpty()
|
|
->and($family['hotspotFiles'])->not->toBeEmpty()
|
|
->and(trim($family['validationStatus']))->not->toBe('');
|
|
|
|
if ($family['targetLaneId'] === 'confidence') {
|
|
expect(trim((string) ($family['confidenceRationale'] ?? '')))->not->toBe('');
|
|
}
|
|
}
|
|
});
|
|
|
|
it('keeps family budgets derived from the generic budget targets for report consumers', function (): void {
|
|
$familyBudgets = TestLaneManifest::familyBudgets();
|
|
|
|
expect($familyBudgets)->not->toBeEmpty()
|
|
->and($familyBudgets[0])->toHaveKeys(['familyId', 'targetType', 'targetId', 'selectors', 'thresholdSeconds'])
|
|
->and(collect($familyBudgets)->pluck('familyId')->all())
|
|
->toContain('action-surface-contract', 'browser-smoke', 'baseline-compare-matrix-workflow', 'baseline-profile-start-surfaces', 'drift-bulk-triage-all-matching', 'finding-bulk-actions-workflow', 'findings-workflow-surfaces', 'workspace-only-admin-surface-independence', 'workspace-settings-slice-management');
|
|
});
|
|
|
|
it('publishes the heavy-governance contract, inventory, and guidance surfaces needed for honest rerun review', function (): void {
|
|
$contract = TestLaneManifest::heavyGovernanceBudgetContract();
|
|
$inventory = collect(TestLaneManifest::heavyGovernanceHotspotInventory());
|
|
|
|
expect($contract['summaryThresholdSeconds'])->toBe(300.0)
|
|
->and($contract['evaluationThresholdSeconds'])->toBe(200.0)
|
|
->and($contract['normalizedThresholdSeconds'])->toBeGreaterThanOrEqual(300.0)
|
|
->and($contract['decisionStatus'])->toBeIn(['recovered', 'recalibrated'])
|
|
->and($inventory)->toHaveCount(6)
|
|
->and($inventory->pluck('familyId')->all())->toEqual([
|
|
'baseline-profile-start-surfaces',
|
|
'action-surface-contract',
|
|
'ops-ux-governance',
|
|
'findings-workflow-surfaces',
|
|
'finding-bulk-actions-workflow',
|
|
'workspace-settings-slice-management',
|
|
])
|
|
->and(collect(TestLaneManifest::heavyGovernanceBudgetSnapshots()))->toHaveCount(2)
|
|
->and(TestLaneManifest::heavyGovernanceBudgetOutcome())->toHaveKeys([
|
|
'decisionStatus',
|
|
'finalThresholdSeconds',
|
|
'deltaSeconds',
|
|
'remainingOpenFamilies',
|
|
'followUpDebt',
|
|
])
|
|
->and(collect(TestLaneManifest::heavyGovernanceAuthorGuidance())->pluck('ruleId')->all())
|
|
->toEqualCanonicalizing([
|
|
'heavy-family-reuse-before-creation',
|
|
'heavy-family-create-only-for-new-trust',
|
|
'split-discovery-workflow-surface-concerns',
|
|
'retain-intentional-heavy-depth-explicitly',
|
|
'record-helper-or-fixture-residuals',
|
|
]);
|
|
}); |