From 0956d5361966ca0c27cc9e805009c6983cf1daec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:07:47 +0000 Subject: [PATCH 1/5] Initial plan From 6ca3e0424ebb51f1350becb17e3a22ae6fc42882 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:13:11 +0000 Subject: [PATCH 2/5] Initial plan for devcontainer build field support Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .devcontainer/devcontainer.json | 4 +--- .github/aw/actions-lock.json | 14 +++++++------- .github/workflows/go-pattern-detector.lock.yml | 2 +- .github/workflows/release.lock.yml | 4 ++-- .github/workflows/super-linter.lock.yml | 2 +- .github/workflows/unbloat-docs.lock.yml | 2 +- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 16a665fe02..b58d2aa394 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,8 +1,6 @@ { "name": "Go", - "build": { - "dockerfile": "Dockerfile" - }, + "image": "", "customizations": { "vscode": { "extensions": [ diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index 464eacf6d5..9031fe9490 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -25,11 +25,16 @@ "version": "v5.0.2", "sha": "8b402f58fbc84540c8b491a91e594a4576fec3d7" }, - "actions/checkout@v5": { + "actions/checkout@v5.0.1": { "repo": "actions/checkout", - "version": "v5", + "version": "v5.0.1", "sha": "93cb6efe18208431cddfb8368fd83d5badbf9bfd" }, + "actions/checkout@v6": { + "repo": "actions/checkout", + "version": "v6", + "sha": "8e8c483db84b4bee98b60c0593521ed34d9990e8" + }, "actions/checkout@v6.0.2": { "repo": "actions/checkout", "version": "v6.0.2", @@ -174,11 +179,6 @@ "repo": "super-linter/super-linter", "version": "v8.3.2", "sha": "d5b0a2ab116623730dd094f15ddc1b6b25bf7b99" - }, - "actions/checkout@v5.0.1": { - "repo": "actions/checkout", - "version": "v5.0.1", - "sha": "93cb6efe18208431cddfb8368fd83d5badbf9bfd" } } } diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml index 74e3186e89..4f1f47c0f0 100644 --- a/.github/workflows/go-pattern-detector.lock.yml +++ b/.github/workflows/go-pattern-detector.lock.yml @@ -951,7 +951,7 @@ jobs: found_patterns: ${{ steps.detect.outputs.found_patterns }} steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: persist-credentials: false - name: Install ast-grep diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index ff46298bf2..109c53266d 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -993,7 +993,7 @@ jobs: release_tag: ${{ steps.compute_config.outputs.release_tag }} steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: fetch-depth: 0 persist-credentials: false @@ -1286,7 +1286,7 @@ jobs: release_id: ${{ steps.get_release.outputs.release_id }} steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: fetch-depth: 0 persist-credentials: true diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index de718df7d3..f98115c35f 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -1291,7 +1291,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: fetch-depth: 0 persist-credentials: false diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index e5f19052d5..2f9db8c334 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -132,7 +132,7 @@ jobs: - name: Create gh-aw temp directory run: bash /opt/gh-aw/actions/create_gh_aw_tmp_dir.sh - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: persist-credentials: false - name: Setup Node.js From a94e1de56088ef941927db43b8bcbae203d3f421 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:15:04 +0000 Subject: [PATCH 3/5] Add support for devcontainer build field Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/devcontainer.go | 10 ++- pkg/cli/devcontainer_test.go | 152 +++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 1 deletion(-) diff --git a/pkg/cli/devcontainer.go b/pkg/cli/devcontainer.go index 6cd33dbb48..307314f532 100644 --- a/pkg/cli/devcontainer.go +++ b/pkg/cli/devcontainer.go @@ -37,10 +37,18 @@ type DevcontainerRepoPermissions struct { // DevcontainerFeatures represents features to install in the devcontainer type DevcontainerFeatures map[string]any +// DevcontainerBuild represents the build configuration for a devcontainer +type DevcontainerBuild struct { + Dockerfile string `json:"dockerfile,omitempty"` + Context string `json:"context,omitempty"` + Args map[string]string `json:"args,omitempty"` +} + // DevcontainerConfig represents the structure of devcontainer.json type DevcontainerConfig struct { Name string `json:"name"` - Image string `json:"image"` + Image string `json:"image,omitempty"` + Build *DevcontainerBuild `json:"build,omitempty"` Customizations *DevcontainerCustomizations `json:"customizations,omitempty"` Features DevcontainerFeatures `json:"features,omitempty"` PostCreateCommand string `json:"postCreateCommand,omitempty"` diff --git a/pkg/cli/devcontainer_test.go b/pkg/cli/devcontainer_test.go index a1b6c51e69..a3f7903165 100644 --- a/pkg/cli/devcontainer_test.go +++ b/pkg/cli/devcontainer_test.go @@ -588,6 +588,158 @@ func TestEnsureDevcontainerConfigMergesWithExisting(t *testing.T) { } } +func TestEnsureDevcontainerConfigWithBuildField(t *testing.T) { + tmpDir := testutil.TempDir(t, "test-*") + + originalDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current directory: %v", err) + } + defer func() { + _ = os.Chdir(originalDir) + }() + + if err := os.Chdir(tmpDir); err != nil { + t.Fatalf("Failed to change to temp directory: %v", err) + } + + // Initialize git repo + if err := exec.Command("git", "init").Run(); err != nil { + t.Skip("Git not available") + } + + // Configure git and add remote + exec.Command("git", "config", "user.name", "Test User").Run() + exec.Command("git", "config", "user.email", "test@example.com").Run() + exec.Command("git", "remote", "add", "origin", "https://github.com/testorg/testrepo.git").Run() + + // Create .devcontainer directory + devcontainerDir := ".devcontainer" + if err := os.MkdirAll(devcontainerDir, 0755); err != nil { + t.Fatalf("Failed to create directory: %v", err) + } + + // Create an existing devcontainer.json with "build" field instead of "image" + existingConfig := DevcontainerConfig{ + Name: "Custom Build Environment", + Build: &DevcontainerBuild{ + Dockerfile: "Dockerfile", + }, + Customizations: &DevcontainerCustomizations{ + VSCode: &DevcontainerVSCode{ + Extensions: []string{ + "golang.go", + }, + }, + }, + Features: DevcontainerFeatures{ + "ghcr.io/devcontainers/features/docker-in-docker:2": map[string]any{}, + }, + PostCreateCommand: "make setup", + } + + devcontainerPath := filepath.Join(devcontainerDir, "devcontainer.json") + data, err := json.MarshalIndent(existingConfig, "", " ") + if err != nil { + t.Fatalf("Failed to marshal existing config: %v", err) + } + data = append(data, '\n') + + if err := os.WriteFile(devcontainerPath, data, 0644); err != nil { + t.Fatalf("Failed to write existing config: %v", err) + } + + // Run ensureDevcontainerConfig - should merge with existing config and preserve build field + err = ensureDevcontainerConfig(false, []string{}) + if err != nil { + t.Fatalf("ensureDevcontainerConfig() failed: %v", err) + } + + // Read and verify the merged config + mergedData, err := os.ReadFile(devcontainerPath) + if err != nil { + t.Fatalf("Failed to read merged config: %v", err) + } + + var mergedConfig DevcontainerConfig + if err := json.Unmarshal(mergedData, &mergedConfig); err != nil { + t.Fatalf("Failed to parse merged config: %v", err) + } + + // Verify the build field is preserved + if mergedConfig.Build == nil { + t.Fatal("Expected build field to be preserved") + } + + if mergedConfig.Build.Dockerfile != "Dockerfile" { + t.Errorf("Expected build.dockerfile to be 'Dockerfile', got %q", mergedConfig.Build.Dockerfile) + } + + // Verify image field is not set + if mergedConfig.Image != "" { + t.Errorf("Expected image field to be empty when build is present, got %q", mergedConfig.Image) + } + + // Verify existing properties were preserved + if mergedConfig.Name != "Custom Build Environment" { + t.Errorf("Expected name to be preserved, got %q", mergedConfig.Name) + } + + // Verify existing extensions were preserved and new ones added + extensions := mergedConfig.Customizations.VSCode.Extensions + hasGolang := false + hasGitHubCopilot := false + hasCopilotChat := false + + for _, ext := range extensions { + switch ext { + case "golang.go": + hasGolang = true + case "GitHub.copilot": + hasGitHubCopilot = true + case "GitHub.copilot-chat": + hasCopilotChat = true + } + } + + if !hasGolang { + t.Error("Expected existing golang.go extension to be preserved") + } + if !hasGitHubCopilot { + t.Error("Expected GitHub.copilot extension to be added") + } + if !hasCopilotChat { + t.Error("Expected GitHub.copilot-chat extension to be added") + } + + // Verify existing features were preserved and new ones added + if _, exists := mergedConfig.Features["ghcr.io/devcontainers/features/docker-in-docker:2"]; !exists { + t.Error("Expected existing docker-in-docker feature to be preserved") + } + if _, exists := mergedConfig.Features["ghcr.io/devcontainers/features/github-cli:1"]; !exists { + t.Error("Expected github-cli feature to be added") + } + if _, exists := mergedConfig.Features["ghcr.io/devcontainers/features/copilot-cli:latest"]; !exists { + t.Error("Expected copilot-cli feature to be added") + } + + // Verify postCreateCommand was updated to include gh-aw + if !strings.Contains(mergedConfig.PostCreateCommand, "make setup") { + t.Error("Expected postCreateCommand to preserve existing command") + } + if !strings.Contains(mergedConfig.PostCreateCommand, "install-gh-aw.sh") { + t.Error("Expected postCreateCommand to include gh-aw installation") + } + + // Verify codespaces repository permissions were added + if mergedConfig.Customizations.Codespaces == nil { + t.Fatal("Expected Codespaces configuration to be added") + } + if _, exists := mergedConfig.Customizations.Codespaces.Repositories["testorg/testrepo"]; !exists { + t.Error("Expected testorg/testrepo to be in repositories") + } +} + func TestGetCurrentRepoName(t *testing.T) { tmpDir := testutil.TempDir(t, "test-*") From 10cd846de03a178d3d35a94594269dd3460647ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 26 Jan 2026 21:21:02 +0000 Subject: [PATCH 4/5] Complete devcontainer build field support Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/devcontainer.go | 4 ++-- pkg/workflow/data/action_pins.json | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/cli/devcontainer.go b/pkg/cli/devcontainer.go index 307314f532..7cef9fd4c3 100644 --- a/pkg/cli/devcontainer.go +++ b/pkg/cli/devcontainer.go @@ -39,8 +39,8 @@ type DevcontainerFeatures map[string]any // DevcontainerBuild represents the build configuration for a devcontainer type DevcontainerBuild struct { - Dockerfile string `json:"dockerfile,omitempty"` - Context string `json:"context,omitempty"` + Dockerfile string `json:"dockerfile,omitempty"` + Context string `json:"context,omitempty"` Args map[string]string `json:"args,omitempty"` } diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index 464eacf6d5..9031fe9490 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -25,11 +25,16 @@ "version": "v5.0.2", "sha": "8b402f58fbc84540c8b491a91e594a4576fec3d7" }, - "actions/checkout@v5": { + "actions/checkout@v5.0.1": { "repo": "actions/checkout", - "version": "v5", + "version": "v5.0.1", "sha": "93cb6efe18208431cddfb8368fd83d5badbf9bfd" }, + "actions/checkout@v6": { + "repo": "actions/checkout", + "version": "v6", + "sha": "8e8c483db84b4bee98b60c0593521ed34d9990e8" + }, "actions/checkout@v6.0.2": { "repo": "actions/checkout", "version": "v6.0.2", @@ -174,11 +179,6 @@ "repo": "super-linter/super-linter", "version": "v8.3.2", "sha": "d5b0a2ab116623730dd094f15ddc1b6b25bf7b99" - }, - "actions/checkout@v5.0.1": { - "repo": "actions/checkout", - "version": "v5.0.1", - "sha": "93cb6efe18208431cddfb8368fd83d5badbf9bfd" } } } From 78df4243a9cc7ffa7516f4add238fd3cb304ce95 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 26 Jan 2026 21:29:40 +0000 Subject: [PATCH 5/5] Add build configuration to devcontainer for Dockerfile --- .devcontainer/devcontainer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b58d2aa394..16a665fe02 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,8 @@ { "name": "Go", - "image": "", + "build": { + "dockerfile": "Dockerfile" + }, "customizations": { "vscode": { "extensions": [