From f12fddfda9e95b585761d7f3b36da371950648a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:50:50 +0000 Subject: [PATCH 1/6] Initial plan From bb84fcf8f555e5f345d53e4ae3f5a9b4b4e817b2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 02:55:18 +0000 Subject: [PATCH 2/6] fix: enforce non-empty COPILOT_MODEL fallback in BYOK smoke postprocess Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/de450c36-9674-4ba2-9fa8-4fbf7d96f0af --- .../ci/postprocess-smoke-workflows.test.ts | 23 ++++++++++++++++ scripts/ci/postprocess-smoke-workflows.ts | 26 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/scripts/ci/postprocess-smoke-workflows.test.ts b/scripts/ci/postprocess-smoke-workflows.test.ts index e94e51d8..0c452fde 100644 --- a/scripts/ci/postprocess-smoke-workflows.test.ts +++ b/scripts/ci/postprocess-smoke-workflows.test.ts @@ -245,6 +245,9 @@ const sessionStateDirInjectionRegex = const copySessionStateStepRegex = /^(\s+)- name: Copy Copilot session state files to logs\n\1 if: always\(\)\n\1 continue-on-error: true\n\1 run: bash "\$\{RUNNER_TEMP\}\/gh-aw\/actions\/copy_copilot_session_state\.sh"\n/m; +const copilotModelEmptyFallbackRegex = + /(COPILOT_MODEL:\s*\$\{\{\s*vars\.GH_AW_MODEL_AGENT_COPILOT\s*\|\|\s*)''(\s*\}\})/g; + function buildCopySessionStateStep(indent: string): string { const i = indent; const ri = `${i} `; @@ -355,3 +358,23 @@ describe('buildCopySessionStateStep', () => { }); }); +describe('copilotModelEmptyFallbackRegex', () => { + beforeEach(() => { + copilotModelEmptyFallbackRegex.lastIndex = 0; + }); + + it('should replace empty fallback with claude-opus-4.6 fallback', () => { + const input = " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}\n"; + const result = input.replace(copilotModelEmptyFallbackRegex, "$1'claude-opus-4.6'$2"); + expect(result).toBe( + " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-opus-4.6' }}\n" + ); + }); + + it('should not modify already-correct fallback', () => { + const input = + " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-opus-4.6' }}\n"; + const result = input.replace(copilotModelEmptyFallbackRegex, "$1'claude-opus-4.6'$2"); + expect(result).toBe(input); + }); +}); diff --git a/scripts/ci/postprocess-smoke-workflows.ts b/scripts/ci/postprocess-smoke-workflows.ts index 07ef5920..1e231ffc 100644 --- a/scripts/ci/postprocess-smoke-workflows.ts +++ b/scripts/ci/postprocess-smoke-workflows.ts @@ -94,6 +94,14 @@ const sessionStateDirInjectionRegex = /--audit-dir \/tmp\/gh-aw\/sandbox\/firewall\/audit(?! --session-state-dir)/g; const SESSION_STATE_DIR = '/tmp/gh-aw/sandbox/agent/session-state'; +// Work around gh-aw compiler bug (gh-aw#26565) where Copilot model fallback is +// emitted as an empty string: +// COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }} +// In BYOK smoke workflows, this overrides workflow-level COPILOT_MODEL when the +// repo variable is unset, causing Copilot CLI startup failure. +const copilotModelEmptyFallbackRegex = + /(COPILOT_MODEL:\s*\$\{\{\s*vars\.GH_AW_MODEL_AGENT_COPILOT\s*\|\|\s*)''(\s*\}\})/g; + // Sentinel used to detect whether the "Copy Copilot session state" step has // already been replaced with the AWF-aware inline script. const copySessionStateSentinel = 'SESSION_STATE_SRC='; @@ -445,6 +453,24 @@ for (const workflowPath of workflowPaths) { } } + // For smoke-copilot-byok: preserve explicit model fallback when the repo + // variable is unset. This keeps BYOK startup stable until upstream compiler + // emits a non-empty fallback. + const isCopilotByokSmoke = workflowPath.includes('smoke-copilot-byok.lock.yml'); + if (isCopilotByokSmoke) { + const emptyFallbackMatches = content.match(copilotModelEmptyFallbackRegex); + if (emptyFallbackMatches) { + content = content.replace( + copilotModelEmptyFallbackRegex, + "$1'claude-opus-4.6'$2" + ); + modified = true; + console.log( + ` Replaced ${emptyFallbackMatches.length} empty COPILOT_MODEL fallback(s) for BYOK smoke` + ); + } + } + // For smoke-services: inject GitHub Actions services block (Redis + PostgreSQL) into the // agent job and replace --enable-host-access with --allow-host-service-ports 6379,5432. // The gh-aw compiler does not natively support GitHub Actions `services:` in the From de1439a3254ffaff37b26567c86f1c5408c2e659 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Thu, 16 Apr 2026 20:04:31 -0700 Subject: [PATCH 3/6] Update scripts/ci/postprocess-smoke-workflows.test.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- scripts/ci/postprocess-smoke-workflows.test.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/ci/postprocess-smoke-workflows.test.ts b/scripts/ci/postprocess-smoke-workflows.test.ts index 0c452fde..d3468753 100644 --- a/scripts/ci/postprocess-smoke-workflows.test.ts +++ b/scripts/ci/postprocess-smoke-workflows.test.ts @@ -359,22 +359,30 @@ describe('buildCopySessionStateStep', () => { }); describe('copilotModelEmptyFallbackRegex', () => { + const EXPECTED_COPILOT_MODEL_FALLBACK = 'claude-opus-4.6'; + beforeEach(() => { copilotModelEmptyFallbackRegex.lastIndex = 0; }); it('should replace empty fallback with claude-opus-4.6 fallback', () => { const input = " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}\n"; - const result = input.replace(copilotModelEmptyFallbackRegex, "$1'claude-opus-4.6'$2"); + const result = input.replace( + copilotModelEmptyFallbackRegex, + `$1'${EXPECTED_COPILOT_MODEL_FALLBACK}'$2` + ); expect(result).toBe( - " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-opus-4.6' }}\n" + ` COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '${EXPECTED_COPILOT_MODEL_FALLBACK}' }}\n` ); }); it('should not modify already-correct fallback', () => { const input = - " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-opus-4.6' }}\n"; - const result = input.replace(copilotModelEmptyFallbackRegex, "$1'claude-opus-4.6'$2"); + ` COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '${EXPECTED_COPILOT_MODEL_FALLBACK}' }}\n`; + const result = input.replace( + copilotModelEmptyFallbackRegex, + `$1'${EXPECTED_COPILOT_MODEL_FALLBACK}'$2` + ); expect(result).toBe(input); }); }); From 51889c9ccca6494e282ccbb73be84cbd158e8d20 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Thu, 16 Apr 2026 20:04:42 -0700 Subject: [PATCH 4/6] Update scripts/ci/postprocess-smoke-workflows.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- scripts/ci/postprocess-smoke-workflows.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/ci/postprocess-smoke-workflows.ts b/scripts/ci/postprocess-smoke-workflows.ts index 1e231ffc..06ba7945 100644 --- a/scripts/ci/postprocess-smoke-workflows.ts +++ b/scripts/ci/postprocess-smoke-workflows.ts @@ -453,16 +453,16 @@ for (const workflowPath of workflowPaths) { } } - // For smoke-copilot-byok: preserve explicit model fallback when the repo - // variable is unset. This keeps BYOK startup stable until upstream compiler - // emits a non-empty fallback. + // For smoke-copilot-byok: replace empty model fallbacks with the workflow- + // level COPILOT_MODEL env so the generated step inherits the shared default + // without hardcoding a duplicate model string here. const isCopilotByokSmoke = workflowPath.includes('smoke-copilot-byok.lock.yml'); if (isCopilotByokSmoke) { const emptyFallbackMatches = content.match(copilotModelEmptyFallbackRegex); if (emptyFallbackMatches) { content = content.replace( copilotModelEmptyFallbackRegex, - "$1'claude-opus-4.6'$2" + '$1env.COPILOT_MODEL$2' ); modified = true; console.log( From 82681d77295e272b445b12e57f2727b280e78494 Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Thu, 16 Apr 2026 20:06:55 -0700 Subject: [PATCH 5/6] Potential fix for pull request finding 'CodeQL / Syntax error' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- scripts/ci/postprocess-smoke-workflows.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/postprocess-smoke-workflows.test.ts b/scripts/ci/postprocess-smoke-workflows.test.ts index d3468753..b7b0b882 100644 --- a/scripts/ci/postprocess-smoke-workflows.test.ts +++ b/scripts/ci/postprocess-smoke-workflows.test.ts @@ -378,7 +378,7 @@ describe('copilotModelEmptyFallbackRegex', () => { it('should not modify already-correct fallback', () => { const input = - ` COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '${EXPECTED_COPILOT_MODEL_FALLBACK}' }}\n`; + " COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-opus-4.6' }}\n"; const result = input.replace( copilotModelEmptyFallbackRegex, `$1'${EXPECTED_COPILOT_MODEL_FALLBACK}'$2` From f4c0a4a956911c9f4750c0fc1d860a196dfe0d2b Mon Sep 17 00:00:00 2001 From: Landon Cox Date: Thu, 16 Apr 2026 20:07:04 -0700 Subject: [PATCH 6/6] Potential fix for pull request finding 'CodeQL / Syntax error' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- scripts/ci/postprocess-smoke-workflows.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/postprocess-smoke-workflows.test.ts b/scripts/ci/postprocess-smoke-workflows.test.ts index b7b0b882..d86cd4f5 100644 --- a/scripts/ci/postprocess-smoke-workflows.test.ts +++ b/scripts/ci/postprocess-smoke-workflows.test.ts @@ -372,7 +372,7 @@ describe('copilotModelEmptyFallbackRegex', () => { `$1'${EXPECTED_COPILOT_MODEL_FALLBACK}'$2` ); expect(result).toBe( - ` COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '${EXPECTED_COPILOT_MODEL_FALLBACK}' }}\n` + ` COPILOT_MODEL: \${{ vars.GH_AW_MODEL_AGENT_COPILOT || '${EXPECTED_COPILOT_MODEL_FALLBACK}' }}\n` ); });