Skip to content
Draft
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
13 changes: 13 additions & 0 deletions .github/workflows/bandit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ on:
branches: [ develop, master ]
workflow_dispatch:

concurrency:
# Workflow-level admission: a job-level group never coalesces while the run
# is queued behind the organization job ceiling. Push scans share one group
# per protected branch so a newer develop/master head retires the older
# scan. workflow_dispatch keeps github.run_id and is not cancelled by a
# sibling. This is a security scan, not merge/release/deploy.
group: >-
bandit-security-scan-${{ github.repository }}-${{
github.event.pull_request.number ||
(github.event_name == 'push' && format('push-{0}', github.ref_name)) ||
github.run_id }}
cancel-in-progress: true

permissions:
contents: read

Expand Down
35 changes: 35 additions & 0 deletions backend/tests/test_workflow_concurrency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Regression tests for GitHub Actions concurrency boundaries."""

from __future__ import annotations

from pathlib import Path

import yaml


REPO_ROOT = Path(__file__).resolve().parents[2]


def _load_workflow(workflow_name: str) -> dict[str, object]:
path = REPO_ROOT / ".github" / "workflows" / workflow_name
assert path.exists(), f"workflow is missing: {workflow_name}"
parsed = yaml.safe_load(path.read_text(encoding="utf-8"))
assert isinstance(parsed, dict), (
f"workflow must parse as a mapping: {workflow_name}"
)
return parsed


def test_bandit_coalesces_pr_and_protected_branch_push_scans() -> None:
"""Cancel superseded PR and push scans; keep manual dispatch unique."""
concurrency = _load_workflow("bandit.yml").get("concurrency")

assert isinstance(concurrency, dict)
group = concurrency.get("group")
assert isinstance(group, str)
assert "bandit-security-scan-${{ github.repository }}-" in group
assert "github.event.pull_request.number" in group
assert "github.event_name == 'push' && format('push-{0}', github.ref_name)" in group
assert "github.run_id" in group
assert "github.run_attempt" not in group
assert concurrency.get("cancel-in-progress") is True
Loading