diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index c850e9e2aba..e1d50d8636b 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -180,21 +180,41 @@ "digest": "sha256:2f1f6d53dd798911aa7b0b849de1b5caae27d928cf6d4b12513d21a853b7ae79", "pinned_image": "ghcr.io/github/gh-aw-firewall/agent-act:0.27.41@sha256:2f1f6d53dd798911aa7b0b849de1b5caae27d928cf6d4b12513d21a853b7ae79" }, + "ghcr.io/github/gh-aw-firewall/agent:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/agent:0.27.11", + "digest": "sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7", + "pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7" + }, "ghcr.io/github/gh-aw-firewall/agent:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/agent:0.27.41", "digest": "sha256:e39efa0edf10c0d0bfc572b59a186dfccb1973f0f77e224bcf6e5a7d81ee95c8", "pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.27.41@sha256:e39efa0edf10c0d0bfc572b59a186dfccb1973f0f77e224bcf6e5a7d81ee95c8" }, + "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11", + "digest": "sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d", + "pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d" + }, "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41", "digest": "sha256:6e2200dcb6a62b183cdcf7ed86e44713ba5ed8eeaf8de143319458898b6e8118", "pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41@sha256:6e2200dcb6a62b183cdcf7ed86e44713ba5ed8eeaf8de143319458898b6e8118" }, + "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11", + "digest": "sha256:1f989a7f2869c6a1b5f76bbbc645027966aa7e87b066d94734a901a7f371dfcd", + "pinned_image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11@sha256:1f989a7f2869c6a1b5f76bbbc645027966aa7e87b066d94734a901a7f371dfcd" + }, "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41", "digest": "sha256:5338ee1b80ebf194436d9368deb376296c09a833ca4d80293dee249f94c7ff73", "pinned_image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41@sha256:5338ee1b80ebf194436d9368deb376296c09a833ca4d80293dee249f94c7ff73" }, + "ghcr.io/github/gh-aw-firewall/squid:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/squid:0.27.11", + "digest": "sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d", + "pinned_image": "ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d" + }, "ghcr.io/github/gh-aw-firewall/squid:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/squid:0.27.41", "digest": "sha256:cfadaba80ad857ecb6603727296b42d92a9e0ff2f956276c4a46bb35f6f1ac24", diff --git a/pkg/actionpins/data/action_pins.json b/pkg/actionpins/data/action_pins.json index c850e9e2aba..e1d50d8636b 100644 --- a/pkg/actionpins/data/action_pins.json +++ b/pkg/actionpins/data/action_pins.json @@ -180,21 +180,41 @@ "digest": "sha256:2f1f6d53dd798911aa7b0b849de1b5caae27d928cf6d4b12513d21a853b7ae79", "pinned_image": "ghcr.io/github/gh-aw-firewall/agent-act:0.27.41@sha256:2f1f6d53dd798911aa7b0b849de1b5caae27d928cf6d4b12513d21a853b7ae79" }, + "ghcr.io/github/gh-aw-firewall/agent:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/agent:0.27.11", + "digest": "sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7", + "pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7" + }, "ghcr.io/github/gh-aw-firewall/agent:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/agent:0.27.41", "digest": "sha256:e39efa0edf10c0d0bfc572b59a186dfccb1973f0f77e224bcf6e5a7d81ee95c8", "pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.27.41@sha256:e39efa0edf10c0d0bfc572b59a186dfccb1973f0f77e224bcf6e5a7d81ee95c8" }, + "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11", + "digest": "sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d", + "pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d" + }, "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41", "digest": "sha256:6e2200dcb6a62b183cdcf7ed86e44713ba5ed8eeaf8de143319458898b6e8118", "pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41@sha256:6e2200dcb6a62b183cdcf7ed86e44713ba5ed8eeaf8de143319458898b6e8118" }, + "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11", + "digest": "sha256:1f989a7f2869c6a1b5f76bbbc645027966aa7e87b066d94734a901a7f371dfcd", + "pinned_image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11@sha256:1f989a7f2869c6a1b5f76bbbc645027966aa7e87b066d94734a901a7f371dfcd" + }, "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41", "digest": "sha256:5338ee1b80ebf194436d9368deb376296c09a833ca4d80293dee249f94c7ff73", "pinned_image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41@sha256:5338ee1b80ebf194436d9368deb376296c09a833ca4d80293dee249f94c7ff73" }, + "ghcr.io/github/gh-aw-firewall/squid:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/squid:0.27.11", + "digest": "sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d", + "pinned_image": "ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d" + }, "ghcr.io/github/gh-aw-firewall/squid:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/squid:0.27.41", "digest": "sha256:cfadaba80ad857ecb6603727296b42d92a9e0ff2f956276c4a46bb35f6f1ac24", diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index c850e9e2aba..e1d50d8636b 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -180,21 +180,41 @@ "digest": "sha256:2f1f6d53dd798911aa7b0b849de1b5caae27d928cf6d4b12513d21a853b7ae79", "pinned_image": "ghcr.io/github/gh-aw-firewall/agent-act:0.27.41@sha256:2f1f6d53dd798911aa7b0b849de1b5caae27d928cf6d4b12513d21a853b7ae79" }, + "ghcr.io/github/gh-aw-firewall/agent:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/agent:0.27.11", + "digest": "sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7", + "pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7" + }, "ghcr.io/github/gh-aw-firewall/agent:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/agent:0.27.41", "digest": "sha256:e39efa0edf10c0d0bfc572b59a186dfccb1973f0f77e224bcf6e5a7d81ee95c8", "pinned_image": "ghcr.io/github/gh-aw-firewall/agent:0.27.41@sha256:e39efa0edf10c0d0bfc572b59a186dfccb1973f0f77e224bcf6e5a7d81ee95c8" }, + "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11", + "digest": "sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d", + "pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d" + }, "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41", "digest": "sha256:6e2200dcb6a62b183cdcf7ed86e44713ba5ed8eeaf8de143319458898b6e8118", "pinned_image": "ghcr.io/github/gh-aw-firewall/api-proxy:0.27.41@sha256:6e2200dcb6a62b183cdcf7ed86e44713ba5ed8eeaf8de143319458898b6e8118" }, + "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11", + "digest": "sha256:1f989a7f2869c6a1b5f76bbbc645027966aa7e87b066d94734a901a7f371dfcd", + "pinned_image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.11@sha256:1f989a7f2869c6a1b5f76bbbc645027966aa7e87b066d94734a901a7f371dfcd" + }, "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41", "digest": "sha256:5338ee1b80ebf194436d9368deb376296c09a833ca4d80293dee249f94c7ff73", "pinned_image": "ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.41@sha256:5338ee1b80ebf194436d9368deb376296c09a833ca4d80293dee249f94c7ff73" }, + "ghcr.io/github/gh-aw-firewall/squid:0.27.11": { + "image": "ghcr.io/github/gh-aw-firewall/squid:0.27.11", + "digest": "sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d", + "pinned_image": "ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d" + }, "ghcr.io/github/gh-aw-firewall/squid:0.27.41": { "image": "ghcr.io/github/gh-aw-firewall/squid:0.27.41", "digest": "sha256:cfadaba80ad857ecb6603727296b42d92a9e0ff2f956276c4a46bb35f6f1ac24", diff --git a/pkg/workflow/docker_firewall_pin_compile_test.go b/pkg/workflow/docker_firewall_pin_compile_test.go index 864bd461c82..8d9f21aa984 100644 --- a/pkg/workflow/docker_firewall_pin_compile_test.go +++ b/pkg/workflow/docker_firewall_pin_compile_test.go @@ -99,6 +99,96 @@ Test workflow.` } } +// TestCompileWorkflow_FirewallImagesPinnedForAWF02711WithGhProxy is a regression test for +// gh-aw#47765: the embedded fallback pin table must include cli-proxy for the historical +// 0.27.11 firewall image set so compiles without a local action-cache still emit +// digest-pinned references for all four sidecars. +func TestCompileWorkflow_FirewallImagesPinnedForAWF02711WithGhProxy(t *testing.T) { + imageTag := "0.27.11" + + frontmatter := `--- +on: workflow_dispatch +engine: claude +sandbox: + agent: + id: awf + version: v0.27.11 +network: + allowed: + - defaults +tools: + github: + mode: gh-proxy +--- + +# Test +Test workflow.` + + tmpDir := testutil.TempDir(t, "docker-firewall-pins-02711-test") + testFile := filepath.Join(tmpDir, "test-workflow.md") + if err := os.WriteFile(testFile, []byte(frontmatter), 0644); err != nil { + t.Fatal(err) + } + + compiler := NewCompiler() + if err := compiler.CompileWorkflow(testFile); err != nil { + t.Fatalf("Failed to compile workflow: %v", err) + } + + lockFile := stringutil.MarkdownToLockFile(testFile) + yaml, err := os.ReadFile(lockFile) + if err != nil { + t.Fatalf("Failed to read lock file: %v", err) + } + + yamlStr := string(yaml) + + expectedPins := []struct { + name string + image string + }{ + {name: "agent", image: constants.DefaultFirewallRegistry + "/agent:" + imageTag}, + {name: "api-proxy", image: constants.DefaultFirewallRegistry + "/api-proxy:" + imageTag}, + {name: "cli-proxy", image: constants.DefaultFirewallRegistry + "/cli-proxy:" + imageTag}, + {name: "squid", image: constants.DefaultFirewallRegistry + "/squid:" + imageTag}, + } + + for _, expectedPin := range expectedPins { + pin, ok := getEmbeddedContainerPin(expectedPin.image) + if !ok { + t.Fatalf("Expected embedded pin for %s", expectedPin.image) + } + pinnedImage := pin.Image + "@" + pin.Digest + if !strings.Contains(yamlStr, `"image":"`+pin.Image+`","digest":"`+pin.Digest+`","pinned_image":"`+pinnedImage+`"`) { + t.Errorf("Expected manifest header to include pinned metadata for %s", pin.Image) + } + if !strings.Contains(yamlStr, "# - "+pinnedImage) { + t.Errorf("Expected pinned container comment for %s", pin.Image) + } + if !strings.Contains(yamlStr, pinnedImage) { + t.Errorf("Expected pinned download reference for %s", pin.Image) + } + } + + imageTagParts := []string{ + `imageTag`, + imageTag + `,`, + } + for _, expectedPin := range expectedPins { + pin, ok := getEmbeddedContainerPin(expectedPin.image) + if !ok { + t.Fatalf("Expected embedded pin for %s", expectedPin.image) + } + imageTagParts = append(imageTagParts, expectedPin.name+"="+pin.Digest) + } + + for _, imageTagPart := range imageTagParts { + if !strings.Contains(yamlStr, imageTagPart) { + t.Errorf("Expected AWF config JSON to include %s", imageTagPart) + } + } +} + // TestCompileWorkflow_FirewallImagesPinnedForDefaultVersion is a regression test for // gh-aw#43307: the four gh-aw-firewall images at the current default version // (constants.DefaultFirewallVersion) must all be digest-pinned in consumer lock files