Skip to content

Commit c7129c2

Browse files
lpcoxCopilot
andauthored
fix: add cli-proxy image to Docker pre-download list (#25558)
When features.cli-proxy is enabled, the compiler generates --skip-pull for AWF but does not include the cli-proxy image in the download_docker_images.sh pre-pull step. This causes AWF to fail at runtime with 'No such image: ghcr.io/github/gh-aw-firewall/cli-proxy'. Add the cli-proxy image to collectDockerImages() when the cli-proxy feature flag is enabled and the AWF version supports it. Closes #25555 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e9a378d commit c7129c2

2 files changed

Lines changed: 105 additions & 0 deletions

File tree

pkg/workflow/docker.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,18 @@ func collectDockerImages(tools map[string]any, workflowData *WorkflowData, actio
9999
dockerLog.Printf("Added AWF api-proxy sidecar container: %s", apiProxyImage)
100100
}
101101
}
102+
103+
// Add cli-proxy sidecar container when the cli-proxy feature flag is enabled
104+
// and the AWF version supports it. Without this, --skip-pull causes AWF to fail
105+
// because the cli-proxy image was never pulled.
106+
if isFeatureEnabled(constants.CliProxyFeatureFlag, workflowData) && awfSupportsCliProxy(firewallConfig) {
107+
cliProxyImage := constants.DefaultFirewallRegistry + "/cli-proxy:" + awfImageTag
108+
if !imageSet[cliProxyImage] {
109+
images = append(images, cliProxyImage)
110+
imageSet[cliProxyImage] = true
111+
dockerLog.Printf("Added AWF cli-proxy sidecar container: %s", cliProxyImage)
112+
}
113+
}
102114
}
103115

104116
// Collect sandbox.mcp container (MCP gateway)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package workflow
2+
3+
import (
4+
"slices"
5+
"testing"
6+
7+
"github.com/github/gh-aw/pkg/constants"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestCollectDockerImages_CliProxy(t *testing.T) {
13+
// Use a version without "v" prefix — getAWFImageTag strips it
14+
awfImageTag := "0.25.18"
15+
16+
t.Run("includes cli-proxy image when feature flag is enabled", func(t *testing.T) {
17+
workflowData := &WorkflowData{
18+
AI: "claude",
19+
NetworkPermissions: &NetworkPermissions{
20+
Firewall: &FirewallConfig{
21+
Enabled: true,
22+
Version: awfImageTag,
23+
},
24+
},
25+
Features: map[string]any{"cli-proxy": true},
26+
}
27+
28+
images := collectDockerImages(nil, workflowData, ActionModeRelease)
29+
30+
cliProxyImage := constants.DefaultFirewallRegistry + "/cli-proxy:" + awfImageTag
31+
assert.True(t, slices.Contains(images, cliProxyImage),
32+
"Expected cli-proxy image %q in collected images, got: %v", cliProxyImage, images)
33+
})
34+
35+
t.Run("excludes cli-proxy image when feature flag is absent", func(t *testing.T) {
36+
workflowData := &WorkflowData{
37+
AI: "claude",
38+
NetworkPermissions: &NetworkPermissions{
39+
Firewall: &FirewallConfig{
40+
Enabled: true,
41+
Version: awfImageTag,
42+
},
43+
},
44+
}
45+
46+
images := collectDockerImages(nil, workflowData, ActionModeRelease)
47+
48+
cliProxyImage := constants.DefaultFirewallRegistry + "/cli-proxy:" + awfImageTag
49+
assert.False(t, slices.Contains(images, cliProxyImage),
50+
"Did not expect cli-proxy image %q in collected images without feature flag, got: %v", cliProxyImage, images)
51+
})
52+
53+
t.Run("excludes cli-proxy image when AWF version is too old", func(t *testing.T) {
54+
workflowData := &WorkflowData{
55+
AI: "claude",
56+
NetworkPermissions: &NetworkPermissions{
57+
Firewall: &FirewallConfig{
58+
Enabled: true,
59+
Version: "v0.25.16", // older than AWFCliProxyMinVersion
60+
},
61+
},
62+
Features: map[string]any{"cli-proxy": true},
63+
}
64+
65+
images := collectDockerImages(nil, workflowData, ActionModeRelease)
66+
67+
// Should not include cli-proxy for an old AWF version
68+
for _, img := range images {
69+
assert.NotContains(t, img, "/cli-proxy:",
70+
"Should not include cli-proxy image when AWF version is too old")
71+
}
72+
})
73+
74+
t.Run("cli-proxy image uses correct AWF image tag", func(t *testing.T) {
75+
customTag := "0.26.0"
76+
workflowData := &WorkflowData{
77+
AI: "copilot",
78+
NetworkPermissions: &NetworkPermissions{
79+
Firewall: &FirewallConfig{
80+
Enabled: true,
81+
Version: customTag,
82+
},
83+
},
84+
Features: map[string]any{"cli-proxy": true},
85+
}
86+
87+
images := collectDockerImages(nil, workflowData, ActionModeRelease)
88+
89+
expectedImage := constants.DefaultFirewallRegistry + "/cli-proxy:" + customTag
90+
require.True(t, slices.Contains(images, expectedImage),
91+
"Expected cli-proxy image %q with custom tag, got: %v", expectedImage, images)
92+
})
93+
}

0 commit comments

Comments
 (0)