From 2c4fc9a758fbfe44cec1340941a6336e7f4f444f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 08:01:01 +0900 Subject: [PATCH 1/7] fix(ci): serialize Internal Mail Smoke without cancelling it Bandit and Docker publish already have owner PRs. Mail smoke still queued overlapping credentialed runs. Keep one repository-wide group and leave cancel-in-progress false so an in-flight mailbox/DAV smoke is not discarded. Signed-off-by: Seongho Bae --- .github/workflows/mail-smoke.yml | 7 +++++++ backend/tests/test_release_governance.py | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/.github/workflows/mail-smoke.yml b/.github/workflows/mail-smoke.yml index 6a3a3fdc9..890dabf1e 100644 --- a/.github/workflows/mail-smoke.yml +++ b/.github/workflows/mail-smoke.yml @@ -6,6 +6,13 @@ on: permissions: contents: read +concurrency: + # One live mailbox/DAV smoke at a time. Do not cancel an in-flight run: + # this workflow holds seeded credentials and talks to customer-adjacent + # servers, and it is not a merge/release/deploy publication path. + group: mail-smoke-${{ github.repository }} + cancel-in-progress: false + jobs: smoke: runs-on: [self-hosted, mail-egress] diff --git a/backend/tests/test_release_governance.py b/backend/tests/test_release_governance.py index a23c70746..ecad3ad3d 100644 --- a/backend/tests/test_release_governance.py +++ b/backend/tests/test_release_governance.py @@ -400,6 +400,10 @@ def test_stepsecurity_remediation_adds_pinned_audit_hardening() -> None: assert harden_runner_ref in mail_smoke_workflow assert "egress-policy: block" in mail_smoke_workflow assert "allowed-endpoints:" in mail_smoke_workflow + assert "concurrency:" in mail_smoke_workflow + assert "mail-smoke-${{ github.repository }}" in mail_smoke_workflow + assert "cancel-in-progress: false" in mail_smoke_workflow + assert "cancel-in-progress: true" not in mail_smoke_workflow.split("jobs:", 1)[0] dependency_review_workflow = read_repo_text( ".github/workflows/dependency-review.yml" From 127ce20fca1c0f160f7842f220f2b7fb3627bb64 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 08:53:51 +0900 Subject: [PATCH 2/7] test(ci): require queued Internal Mail Smoke runs --- backend/tests/test_mail_smoke_concurrency.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 backend/tests/test_mail_smoke_concurrency.py diff --git a/backend/tests/test_mail_smoke_concurrency.py b/backend/tests/test_mail_smoke_concurrency.py new file mode 100644 index 000000000..c5d7192ce --- /dev/null +++ b/backend/tests/test_mail_smoke_concurrency.py @@ -0,0 +1,20 @@ +"""Regression tests for Internal Mail Smoke concurrency semantics.""" + +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] + + +def test_mail_smoke_concurrency_queues_without_discarding_pending_runs() -> None: + """Require FIFO-style queuing instead of replacing an already-pending smoke.""" + workflow = (REPO_ROOT / ".github/workflows/mail-smoke.yml").read_text( + encoding="utf-8" + ) + workflow_header = workflow.split("jobs:", 1)[0] + + assert "concurrency:" in workflow_header + assert "group: mail-smoke-${{ github.repository }}" in workflow_header + assert "cancel-in-progress: false" in workflow_header + assert "queue: max" in workflow_header + assert "cancel-in-progress: true" not in workflow_header From 8043923c5161fa75c40444bac307bac36ee4761d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 08:54:53 +0900 Subject: [PATCH 3/7] fix(ci): queue Internal Mail Smoke dispatches --- .github/workflows/mail-smoke.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mail-smoke.yml b/.github/workflows/mail-smoke.yml index 890dabf1e..3501d1b1d 100644 --- a/.github/workflows/mail-smoke.yml +++ b/.github/workflows/mail-smoke.yml @@ -7,11 +7,12 @@ permissions: contents: read concurrency: - # One live mailbox/DAV smoke at a time. Do not cancel an in-flight run: + # One live mailbox/DAV smoke at a time. Keep every requested run queued: # this workflow holds seeded credentials and talks to customer-adjacent # servers, and it is not a merge/release/deploy publication path. group: mail-smoke-${{ github.repository }} cancel-in-progress: false + queue: max jobs: smoke: @@ -85,4 +86,4 @@ jobs: # NARUON_TEST_POP3_ADDR2: ${{ secrets.NARUON_TEST_POP3_ADDR2 }} # NARUON_TEST_SMTP_ADDR2: ${{ secrets.NARUON_TEST_SMTP_ADDR2 }} # NARUON_TEST_CALDAV_ADDR2: ${{ secrets.NARUON_TEST_CALDAV_ADDR2 }} - # NARUON_TEST_CARDDAV_ADDR2: ${{ secrets.NARUON_TEST_CARDDAV_ADDR2 }} + # NARUON_TEST_CARDDAV_ADDR2: ${{ secrets.NARUON_TEST_CARDDAV_ADDR2 }} \ No newline at end of file From 7e18da7fc930114a959a74f7238ae48af19d7f9b Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 09:18:33 +0900 Subject: [PATCH 4/7] docs(ci): bound mail smoke queue semantics --- .github/workflows/mail-smoke.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mail-smoke.yml b/.github/workflows/mail-smoke.yml index 3501d1b1d..3f952ffa1 100644 --- a/.github/workflows/mail-smoke.yml +++ b/.github/workflows/mail-smoke.yml @@ -7,9 +7,10 @@ permissions: contents: read concurrency: - # One live mailbox/DAV smoke at a time. Keep every requested run queued: - # this workflow holds seeded credentials and talks to customer-adjacent - # servers, and it is not a merge/release/deploy publication path. + # One live mailbox/DAV smoke at a time. Keep pending requests up to GitHub's + # concurrency-group limit (currently 100); requests beyond that bound may be + # canceled. This workflow holds seeded credentials and talks to + # customer-adjacent servers, and it is not a merge/release/deploy path. group: mail-smoke-${{ github.repository }} cancel-in-progress: false queue: max @@ -86,4 +87,4 @@ jobs: # NARUON_TEST_POP3_ADDR2: ${{ secrets.NARUON_TEST_POP3_ADDR2 }} # NARUON_TEST_SMTP_ADDR2: ${{ secrets.NARUON_TEST_SMTP_ADDR2 }} # NARUON_TEST_CALDAV_ADDR2: ${{ secrets.NARUON_TEST_CALDAV_ADDR2 }} - # NARUON_TEST_CARDDAV_ADDR2: ${{ secrets.NARUON_TEST_CARDDAV_ADDR2 }} \ No newline at end of file + # NARUON_TEST_CARDDAV_ADDR2: ${{ secrets.NARUON_TEST_CARDDAV_ADDR2 }} From c1127bd2032e5d088446f2d7dc4cc68c70d2c0aa Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 09:18:42 +0900 Subject: [PATCH 5/7] test(ci): describe bounded mail smoke queue --- backend/tests/test_mail_smoke_concurrency.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tests/test_mail_smoke_concurrency.py b/backend/tests/test_mail_smoke_concurrency.py index c5d7192ce..84e8caa58 100644 --- a/backend/tests/test_mail_smoke_concurrency.py +++ b/backend/tests/test_mail_smoke_concurrency.py @@ -6,8 +6,8 @@ REPO_ROOT = Path(__file__).resolve().parents[2] -def test_mail_smoke_concurrency_queues_without_discarding_pending_runs() -> None: - """Require FIFO-style queuing instead of replacing an already-pending smoke.""" +def test_mail_smoke_concurrency_uses_bounded_pending_queue() -> None: + """Require bounded queuing instead of single-pending replacement.""" workflow = (REPO_ROOT / ".github/workflows/mail-smoke.yml").read_text( encoding="utf-8" ) From df45697865ebe0dbfa505906277cde0c4c9f4cf2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 17:51:39 +0900 Subject: [PATCH 6/7] fix(ci): use valid mail smoke concurrency syntax Signed-off-by: Seongho Bae --- .github/workflows/mail-smoke.yml | 7 +++---- backend/tests/test_mail_smoke_concurrency.py | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/mail-smoke.yml b/.github/workflows/mail-smoke.yml index 3f952ffa1..339d40519 100644 --- a/.github/workflows/mail-smoke.yml +++ b/.github/workflows/mail-smoke.yml @@ -7,13 +7,12 @@ permissions: contents: read concurrency: - # One live mailbox/DAV smoke at a time. Keep pending requests up to GitHub's - # concurrency-group limit (currently 100); requests beyond that bound may be - # canceled. This workflow holds seeded credentials and talks to + # One live mailbox/DAV smoke at a time. GitHub retains at most one pending + # run per concurrency group; cancel-in-progress stays false so a live run + # is never interrupted. This workflow holds seeded credentials and talks to # customer-adjacent servers, and it is not a merge/release/deploy path. group: mail-smoke-${{ github.repository }} cancel-in-progress: false - queue: max jobs: smoke: diff --git a/backend/tests/test_mail_smoke_concurrency.py b/backend/tests/test_mail_smoke_concurrency.py index 84e8caa58..dcc4ea1be 100644 --- a/backend/tests/test_mail_smoke_concurrency.py +++ b/backend/tests/test_mail_smoke_concurrency.py @@ -6,8 +6,8 @@ REPO_ROOT = Path(__file__).resolve().parents[2] -def test_mail_smoke_concurrency_uses_bounded_pending_queue() -> None: - """Require bounded queuing instead of single-pending replacement.""" +def test_mail_smoke_concurrency_uses_non_canceling_group() -> None: + """Keep a live smoke run intact under GitHub's standard concurrency contract.""" workflow = (REPO_ROOT / ".github/workflows/mail-smoke.yml").read_text( encoding="utf-8" ) @@ -16,5 +16,5 @@ def test_mail_smoke_concurrency_uses_bounded_pending_queue() -> None: assert "concurrency:" in workflow_header assert "group: mail-smoke-${{ github.repository }}" in workflow_header assert "cancel-in-progress: false" in workflow_header - assert "queue: max" in workflow_header + assert "queue:" not in workflow_header assert "cancel-in-progress: true" not in workflow_header From c0823f3891d21787417b1a0ddda9c563736c304e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 8 Sep 2026 22:10:24 +0900 Subject: [PATCH 7/7] repair(ci): restore supported mail smoke queue contract Current GitHub Actions documentation explicitly supports concurrency.queue: max, retaining up to 100 pending runs in a group. The intervening child removed that supported queue contract and reverted the focused regression to default single-pending replacement. Preserve that commit in ancestry, but restore the bounded non-cancelling queue tree. --- .github/workflows/mail-smoke.yml | 7 ++++--- backend/tests/test_mail_smoke_concurrency.py | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/mail-smoke.yml b/.github/workflows/mail-smoke.yml index 339d40519..3f952ffa1 100644 --- a/.github/workflows/mail-smoke.yml +++ b/.github/workflows/mail-smoke.yml @@ -7,12 +7,13 @@ permissions: contents: read concurrency: - # One live mailbox/DAV smoke at a time. GitHub retains at most one pending - # run per concurrency group; cancel-in-progress stays false so a live run - # is never interrupted. This workflow holds seeded credentials and talks to + # One live mailbox/DAV smoke at a time. Keep pending requests up to GitHub's + # concurrency-group limit (currently 100); requests beyond that bound may be + # canceled. This workflow holds seeded credentials and talks to # customer-adjacent servers, and it is not a merge/release/deploy path. group: mail-smoke-${{ github.repository }} cancel-in-progress: false + queue: max jobs: smoke: diff --git a/backend/tests/test_mail_smoke_concurrency.py b/backend/tests/test_mail_smoke_concurrency.py index dcc4ea1be..84e8caa58 100644 --- a/backend/tests/test_mail_smoke_concurrency.py +++ b/backend/tests/test_mail_smoke_concurrency.py @@ -6,8 +6,8 @@ REPO_ROOT = Path(__file__).resolve().parents[2] -def test_mail_smoke_concurrency_uses_non_canceling_group() -> None: - """Keep a live smoke run intact under GitHub's standard concurrency contract.""" +def test_mail_smoke_concurrency_uses_bounded_pending_queue() -> None: + """Require bounded queuing instead of single-pending replacement.""" workflow = (REPO_ROOT / ".github/workflows/mail-smoke.yml").read_text( encoding="utf-8" ) @@ -16,5 +16,5 @@ def test_mail_smoke_concurrency_uses_non_canceling_group() -> None: assert "concurrency:" in workflow_header assert "group: mail-smoke-${{ github.repository }}" in workflow_header assert "cancel-in-progress: false" in workflow_header - assert "queue:" not in workflow_header + assert "queue: max" in workflow_header assert "cancel-in-progress: true" not in workflow_header