From 4f5d74e5f42e7c9bf5d797f71c44e08b9cd73ea0 Mon Sep 17 00:00:00 2001 From: Joshua Temple Date: Thu, 9 Jul 2026 22:17:06 -0400 Subject: [PATCH 1/2] fix(hotfix): match per-component env branches in finalize trigger The hotfix finalize pull_request trigger filtered branches on env/*, but a GitHub Actions branch glob stops at a slash. Per-component env branches carry two segments (env/api/staging), so env/* never matched them and the closed-PR finalize never fired for a multi-component pipeline: divergence went unrecorded and the component state leaf never advanced. Widen the filter to env/**, which matches both env/staging and env/api/staging with no change for single-component pipelines. Signed-off-by: Joshua Temple --- internal/generate/hotfix.go | 7 ++++++- internal/generate/hotfix_test.go | 21 ++++++++++++++++++- ...hub__workflows__cascade-hotfix.yaml.golden | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/internal/generate/hotfix.go b/internal/generate/hotfix.go index 811c262b..a5264554 100644 --- a/internal/generate/hotfix.go +++ b/internal/generate/hotfix.go @@ -238,7 +238,12 @@ func (g *HotfixGenerator) writeTriggers(sb *strings.Builder) { sb.WriteString(" pull_request:\n") sb.WriteString(" types: [closed]\n") sb.WriteString(" branches:\n") - sb.WriteString(" - 'env/*'\n") + // Double-star matches env branches at any depth. A GitHub Actions branch + // glob `*` stops at a slash, so a single-star `env/*` never matches a + // per-component branch like env/api/staging and the closed-PR finalize + // would never fire for a multi-component pipeline. `env/**` matches both + // the single-component branch (env/staging) and the per-component branch. + sb.WriteString(" - 'env/**'\n") sb.WriteString("\n") } diff --git a/internal/generate/hotfix_test.go b/internal/generate/hotfix_test.go index 6914a7ea..e28e3595 100644 --- a/internal/generate/hotfix_test.go +++ b/internal/generate/hotfix_test.go @@ -75,7 +75,7 @@ func TestHotfixGenerator_Triggers(t *testing.T) { assert.Contains(t, content, "pull_request:") assert.Contains(t, content, "types: [closed]") assert.Contains(t, content, "branches:") - assert.Contains(t, content, "'env/*'") + assert.Contains(t, content, "'env/**'") // Dispatch inputs. assert.Contains(t, content, "commit:") @@ -89,6 +89,25 @@ func TestHotfixGenerator_Triggers(t *testing.T) { assert.NotContains(t, content, "- dev") } +// TestHotfixGenerator_FinalizeTriggerMatchesNestedEnvBranches guards that the +// finalize pull_request trigger's branch filter matches multi-component env +// branches. Per-component env branches carry two path segments +// (env/api/staging), and a GitHub Actions `*` glob stops at a slash, so a +// single-star `env/*` filter never matches them and the closed-PR finalize +// never fires. A double-star `env/**` matches any depth, covering both the +// single-component branch (env/staging) and the per-component branch +// (env/api/staging). +func TestHotfixGenerator_FinalizeTriggerMatchesNestedEnvBranches(t *testing.T) { + gen := NewHotfixGenerator(threeEnvHotfixConfig(), "") + content, err := gen.Generate() + require.NoError(t, err) + + assert.Contains(t, content, " - 'env/**'", + "finalize trigger must use env/** so it matches per-component env branches like env/api/staging") + assert.NotContains(t, content, " - 'env/*'\n", + "finalize trigger must not use a single-star env/* filter, which a GitHub Actions glob will not match across the slash of env/api/staging") +} + // TestHotfixGenerator_CommitInputAcceptsMultiple guards that the dispatch // `commit` input documents comma-delimited multi-commit hotfixes, so an operator // can hand the workflow a stack of trunk fixes to cherry-pick as one chain. diff --git a/internal/generate/testdata/byte_identical_baseline/.github__workflows__cascade-hotfix.yaml.golden b/internal/generate/testdata/byte_identical_baseline/.github__workflows__cascade-hotfix.yaml.golden index 4b80dbf3..ae7d6e15 100644 --- a/internal/generate/testdata/byte_identical_baseline/.github__workflows__cascade-hotfix.yaml.golden +++ b/internal/generate/testdata/byte_identical_baseline/.github__workflows__cascade-hotfix.yaml.golden @@ -40,7 +40,7 @@ on: pull_request: types: [closed] branches: - - 'env/*' + - 'env/**' permissions: contents: read From 7a9ce4714e952b0da2d48201d08214835cb93d11 Mon Sep 17 00:00:00 2001 From: Joshua Temple Date: Thu, 9 Jul 2026 22:34:24 -0400 Subject: [PATCH 2/2] test(hotfix): match env/** finalize trigger in generation-threshold e2e scenario Signed-off-by: Joshua Temple --- e2e/scenarios/hotfix/hotfix-generation-threshold.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/scenarios/hotfix/hotfix-generation-threshold.yaml b/e2e/scenarios/hotfix/hotfix-generation-threshold.yaml index 8f516805..918e9f47 100644 --- a/e2e/scenarios/hotfix/hotfix-generation-threshold.yaml +++ b/e2e/scenarios/hotfix/hotfix-generation-threshold.yaml @@ -39,7 +39,7 @@ steps: - "target_env:" - "pull_request:" - "types: [closed]" - - "'env/*'" + - "'env/**'" - "format('hotfix-finalize-{0}', github.repository)" - "format('hotfix-{0}', github.event.inputs.target_env)" - " plan:"