Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/scripts/evaluate_required_checks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ for (const descriptor of required) {
candidate?.workflow_path === descriptor.workflow_path
);

if (candidates.length > 1) {
failed.push(`${descriptor.context}=duplicate correct-path candidates`);
if (candidates.length > 1 && candidates.some(candidate => !Number.isSafeInteger(candidate?.id))) {
failed.push(`${descriptor.context}=ambiguous correct-path candidates`);
continue;
}

const run = candidates[0];
const run = candidates.toSorted((left, right) => (right.id ?? 0) - (left.id ?? 0))[0];
if (!run || run.status !== 'completed') {
pending.push(descriptor.context);
continue;
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/org-quality-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ permissions:
jobs:
quality-gate:
name: quality-gate
uses: agiletec-inc/github-actions/.github/workflows/quality-gate.yml@cf4c5b43b92a704c9f3aa115bc7465879ddc9469
uses: agiletec-inc/github-actions/.github/workflows/quality-gate.yml@0cbb5acf07f1992b140d3c75e9e0da314378c74f
with:
source-ref: cf4c5b43b92a704c9f3aa115bc7465879ddc9469
source-ref: 0cbb5acf07f1992b140d3c75e9e0da314378c74f
linux-runs-on: ${{ github.event.repository.private && 'org-shared-ci-light' || 'ubuntu-latest' }}
swift-runs-on: macos-latest
1 change: 1 addition & 0 deletions .github/workflows/quality-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ jobs:
const enriched = (payload.check_runs ?? []).map(checkRun => {
const match = checkRun.details_url?.match(/\/actions\/runs\/(\d+)(?:\/|$)/);
return {
id: checkRun.id,
name: checkRun.name,
status: checkRun.status,
conclusion: checkRun.conclusion,
Expand Down
54 changes: 43 additions & 11 deletions tests/test_native_required_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,49 @@ def test_same_name_success_from_wrong_workflow_path_is_ignored(self) -> None:
)
self.assertEqual(result.returncode, 75, result.stderr)

def test_duplicate_candidates_from_correct_path_are_rejected(self) -> None:
run = {
"name": "repo-quality-gate",
"workflow_path": ".github/workflows/quality.yml",
"status": "completed",
"conclusion": "success",
}
result = self.evaluate([self.QUALITY_DESCRIPTOR], [run, run.copy()])
self.assertNotEqual(result.returncode, 0)
self.assertNotEqual(result.returncode, 75)
self.assertIn("duplicate", result.stderr.lower())
def test_latest_candidate_from_correct_path_is_authoritative(self) -> None:
result = self.evaluate(
[self.QUALITY_DESCRIPTOR],
[
{
"id": 100,
"name": "repo-quality-gate",
"workflow_path": ".github/workflows/quality.yml",
"status": "completed",
"conclusion": "failure",
},
{
"id": 101,
"name": "repo-quality-gate",
"workflow_path": ".github/workflows/quality.yml",
"status": "completed",
"conclusion": "success",
},
],
)
self.assertEqual(result.returncode, 0, result.stderr)

def test_latest_failure_from_correct_path_is_rejected(self) -> None:
result = self.evaluate(
[self.QUALITY_DESCRIPTOR],
[
{
"id": 100,
"name": "repo-quality-gate",
"workflow_path": ".github/workflows/quality.yml",
"status": "completed",
"conclusion": "success",
},
{
"id": 101,
"name": "repo-quality-gate",
"workflow_path": ".github/workflows/quality.yml",
"status": "completed",
"conclusion": "failure",
},
],
)
self.assertEqual(result.returncode, 1, result.stderr)

def test_pending_or_missing_check_requests_retry(self) -> None:
cases = {
Expand Down
1 change: 1 addition & 0 deletions tests/test_workflow_wiring.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def test_native_gate_checks_pr_head_and_merge_group_sha(self) -> None:
def test_native_gate_payload_excludes_unneeded_check_run_fields(self) -> None:
source = QUALITY_GATE.read_text()
self.assertNotIn("return { ...checkRun", source)
self.assertIn("id: checkRun.id", source)
self.assertIn("name: checkRun.name", source)
self.assertIn("workflow_path: match ? runIds.get(match[1]) ?? null : null", source)

Expand Down