From 900ad68d156cd0e1048f6509e2485583610b8d97 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 12:05:18 +0900 Subject: [PATCH 01/11] fix(ci): skip docs-only changes for bandit, codeql, trivy Adds paths-ignore for docs/** and *.md to stop these workflows firing on every docs-only push/PR, per the org-wide Actions-queue-congestion audit. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/bandit.yml | 6 ++++++ .github/workflows/codeql.yml | 3 +++ .github/workflows/trivy.yml | 3 +++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index 6db7276da..84fd58d91 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -5,10 +5,16 @@ on: branches: - develop - main + paths-ignore: + - "docs/**" + - "*.md" pull_request: branches: - develop - main + paths-ignore: + - "docs/**" + - "*.md" permissions: contents: read diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 27c5b540f..b17c9cd87 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -5,6 +5,9 @@ on: branches: - develop - main + paths-ignore: + - "docs/**" + - "*.md" workflow_dispatch: permissions: diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index d79ec32e1..3c87ed795 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -5,6 +5,9 @@ on: branches: - develop - main + paths-ignore: + - "docs/**" + - "*.md" permissions: contents: read From 82eb38cb8c76b8903f42c5002dec69b15dc42b02 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 14:15:31 +0900 Subject: [PATCH 02/11] fix(ci): preserve protected security scans Keep Bandit, CodeQL, and Trivy running for every protected-branch push. Limit the docs-only optimization to Bandit's pull-request event, where the local job is not a required protected context, and match Markdown at any repository depth. --- .github/workflows/bandit.yml | 5 +---- .github/workflows/codeql.yml | 3 --- .github/workflows/trivy.yml | 3 --- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index 84fd58d91..28a8d76ab 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -5,16 +5,13 @@ on: branches: - develop - main - paths-ignore: - - "docs/**" - - "*.md" pull_request: branches: - develop - main paths-ignore: - "docs/**" - - "*.md" + - "**.md" permissions: contents: read diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index b17c9cd87..27c5b540f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -5,9 +5,6 @@ on: branches: - develop - main - paths-ignore: - - "docs/**" - - "*.md" workflow_dispatch: permissions: diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 3c87ed795..d79ec32e1 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -5,9 +5,6 @@ on: branches: - develop - main - paths-ignore: - - "docs/**" - - "*.md" permissions: contents: read From 0f1dd76bb04df378aaabe951d4211de890ae68f6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 02:16:48 +0900 Subject: [PATCH 03/11] fix(dependabot): group GitHub Actions updates --- .github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2df162d89..1f23b6357 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -39,3 +39,7 @@ updates: labels: - "dependencies" - "github-actions" + groups: + github-actions: + patterns: + - "*" From ac90d5a6bd4a35197285a9cd5eddef64112b7369 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 02:36:22 +0900 Subject: [PATCH 04/11] fix(dependabot): drop nonexistent github-actions label --- .github/dependabot.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1f23b6357..2e88e9db2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -38,7 +38,6 @@ updates: open-pull-requests-limit: 10 labels: - "dependencies" - - "github-actions" groups: github-actions: patterns: From f87338ce2becc1c2676eb0a188f0d2f2ab356236 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 03:09:09 +0900 Subject: [PATCH 05/11] test(dependabot): require bounded nonmajor dev grouping --- .../tests/test_dependabot_queue_policy.py | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 services/analysis-engine/tests/test_dependabot_queue_policy.py diff --git a/services/analysis-engine/tests/test_dependabot_queue_policy.py b/services/analysis-engine/tests/test_dependabot_queue_policy.py new file mode 100644 index 000000000..852fb566d --- /dev/null +++ b/services/analysis-engine/tests/test_dependabot_queue_policy.py @@ -0,0 +1,43 @@ +"""Executable queue-shaping contracts for Dependabot version updates.""" + +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[3] +DEPENDABOT_CONFIG = REPO_ROOT / ".github" / "dependabot.yml" + + +def _ecosystem_block(name: str) -> str: + """Return one Dependabot ecosystem block without parsing unrelated YAML.""" + content = DEPENDABOT_CONFIG.read_text(encoding="utf-8") + marker = f' - package-ecosystem: "{name}"' + if marker not in content: + raise AssertionError(f"Dependabot ecosystem is missing: {name}") + start = content.index(marker) + next_start = content.find("\n - package-ecosystem:", start + len(marker)) + return content[start:] if next_start == -1 else content[start:next_start] + + +def test_npm_development_nonmajor_updates_are_grouped() -> None: + """Keep routine npm tooling updates from recreating one-PR-per-package fanout.""" + block = _ecosystem_block("npm") + marker = " npm-development-nonmajor:" + + assert marker in block + group = block.split(marker, 1)[1] + assert ' dependency-type: "development"' in group + assert " update-types:" in group + assert ' - "minor"' in group + assert ' - "patch"' in group + assert ' - "major"' not in group + assert " patterns:" in group + assert ' - "*"' in group + + +def test_github_actions_updates_remain_grouped() -> None: + """Keep action updates consolidated inside their existing ecosystem boundary.""" + block = _ecosystem_block("github-actions") + + assert " github-actions:" in block + assert " patterns:" in block + assert ' - "*"' in block From d3dd53093f3185cb0da48ee3c995dfe8ca32b170 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 03:09:32 +0900 Subject: [PATCH 06/11] fix(dependabot): group nonmajor npm development updates --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2e88e9db2..3ef76da28 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,6 +9,14 @@ updates: labels: - "dependencies" - "javascript" + groups: + npm-development-nonmajor: + dependency-type: "development" + update-types: + - "minor" + - "patch" + patterns: + - "*" - package-ecosystem: "pip" directory: "/services/analysis-engine" From bda79575d5fbeee22f4ca01e7656bd36ef400972 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 04:04:38 +0900 Subject: [PATCH 07/11] test(dependabot): require grouped action security updates --- .../tests/test_dependabot_queue_policy.py | 37 ++++++++++++++----- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/services/analysis-engine/tests/test_dependabot_queue_policy.py b/services/analysis-engine/tests/test_dependabot_queue_policy.py index 852fb566d..91cb83652 100644 --- a/services/analysis-engine/tests/test_dependabot_queue_policy.py +++ b/services/analysis-engine/tests/test_dependabot_queue_policy.py @@ -1,4 +1,4 @@ -"""Executable queue-shaping contracts for Dependabot version updates.""" +"""Executable queue-shaping contracts for Dependabot update proposals.""" from pathlib import Path @@ -18,13 +18,21 @@ def _ecosystem_block(name: str) -> str: return content[start:] if next_start == -1 else content[start:next_start] +def _group_block(ecosystem_block: str, name: str) -> str: + """Return one group body, bounded before the next sibling group when present.""" + marker = f" {name}:" + if marker not in ecosystem_block: + raise AssertionError(f"Dependabot group is missing: {name}") + group = ecosystem_block.split(marker, 1)[1] + next_group = group.find("\n ") + return group if next_group == -1 else group[:next_group] + + def test_npm_development_nonmajor_updates_are_grouped() -> None: """Keep routine npm tooling updates from recreating one-PR-per-package fanout.""" block = _ecosystem_block("npm") - marker = " npm-development-nonmajor:" + group = _group_block(block, "npm-development-nonmajor") - assert marker in block - group = block.split(marker, 1)[1] assert ' dependency-type: "development"' in group assert " update-types:" in group assert ' - "minor"' in group @@ -34,10 +42,21 @@ def test_npm_development_nonmajor_updates_are_grouped() -> None: assert ' - "*"' in group -def test_github_actions_updates_remain_grouped() -> None: - """Keep action updates consolidated inside their existing ecosystem boundary.""" +def test_github_actions_version_updates_remain_grouped() -> None: + """Keep action version updates consolidated inside their ecosystem boundary.""" + block = _ecosystem_block("github-actions") + group = _group_block(block, "github-actions") + + assert ' applies-to: "version-updates"' in group + assert " patterns:" in group + assert ' - "*"' in group + + +def test_github_actions_security_updates_are_grouped_separately() -> None: + """Consolidate action security updates without mixing them with version updates.""" block = _ecosystem_block("github-actions") + group = _group_block(block, "github-actions-security") - assert " github-actions:" in block - assert " patterns:" in block - assert ' - "*"' in block + assert ' applies-to: "security-updates"' in group + assert " patterns:" in group + assert ' - "*"' in group From bb544357fa349fdf16060dccb02161fc6bfacff9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 04:04:47 +0900 Subject: [PATCH 08/11] fix(dependabot): group action security updates separately --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3ef76da28..014ece678 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -48,5 +48,10 @@ updates: - "dependencies" groups: github-actions: + applies-to: "version-updates" + patterns: + - "*" + github-actions-security: + applies-to: "security-updates" patterns: - "*" From 5eef6ec87c0df3696987fe65dd5bad0c75029212 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 04:05:21 +0900 Subject: [PATCH 09/11] fix(test): bound Dependabot group parsing by indentation --- .../tests/test_dependabot_queue_policy.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/services/analysis-engine/tests/test_dependabot_queue_policy.py b/services/analysis-engine/tests/test_dependabot_queue_policy.py index 91cb83652..f8e86a789 100644 --- a/services/analysis-engine/tests/test_dependabot_queue_policy.py +++ b/services/analysis-engine/tests/test_dependabot_queue_policy.py @@ -19,13 +19,18 @@ def _ecosystem_block(name: str) -> str: def _group_block(ecosystem_block: str, name: str) -> str: - """Return one group body, bounded before the next sibling group when present.""" + """Return one group body, stopping only at the next six-space sibling key.""" marker = f" {name}:" if marker not in ecosystem_block: raise AssertionError(f"Dependabot group is missing: {name}") group = ecosystem_block.split(marker, 1)[1] - next_group = group.find("\n ") - return group if next_group == -1 else group[:next_group] + lines = group.splitlines() + body: list[str] = [] + for line in lines: + if line.startswith(" ") and not line.startswith(" "): + break + body.append(line) + return "\n".join(body) def test_npm_development_nonmajor_updates_are_grouped() -> None: From 100c1e324c2aa654cc438dfa965a0fdbed60cd2b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 16:12:37 +0900 Subject: [PATCH 10/11] chore(ci): leave Bandit PR policy to canonical security dedupe lane --- .github/workflows/bandit.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index 28a8d76ab..31285786f 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -9,9 +9,6 @@ on: branches: - develop - main - paths-ignore: - - "docs/**" - - "**.md" permissions: contents: read @@ -35,4 +32,4 @@ jobs: run: uv sync --project services/analysis-engine --group dev --frozen - name: Run Bandit working-directory: services/analysis-engine - run: uv run bandit -c pyproject.toml -r src + run: uv run bandit -c pyproject.toml -r src \ No newline at end of file From c4fec43190dc124393b9d4b477a205f4f8ed8b52 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 4 Sep 2026 16:14:21 +0900 Subject: [PATCH 11/11] chore(ci): adopt protected Bandit blob --- .github/workflows/bandit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml index 31285786f..6db7276da 100644 --- a/.github/workflows/bandit.yml +++ b/.github/workflows/bandit.yml @@ -32,4 +32,4 @@ jobs: run: uv sync --project services/analysis-engine --group dev --frozen - name: Run Bandit working-directory: services/analysis-engine - run: uv run bandit -c pyproject.toml -r src \ No newline at end of file + run: uv run bandit -c pyproject.toml -r src