From a16660cdf055b5b2d94329ef84fd68e260f75c9d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 4 Jul 2026 05:28:04 +0000
Subject: [PATCH] fix: await runLogParser in async tests and fix Go modernize
 lint

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
---
 .../setup/js/log_parser_bootstrap.test.cjs    | 51 ++++++++++---------
 pkg/workflow/arc_dind_artifacts.go            |  4 +-
 2 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/actions/setup/js/log_parser_bootstrap.test.cjs b/actions/setup/js/log_parser_bootstrap.test.cjs
index f8e703f1b59..19f9685a9f8 100644
--- a/actions/setup/js/log_parser_bootstrap.test.cjs
+++ b/actions/setup/js/log_parser_bootstrap.test.cjs
@@ -63,14 +63,14 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.unlinkSync(logFile),
             fs.rmdirSync(tmpDir));
         }),
-        it("should fail Claude runs when no structured log entries are parsed", () => {
+        it("should fail Claude runs when no structured log entries are parsed", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           try {
             fs.writeFileSync(logFile, "unstructured log output");
             process.env.GH_AW_AGENT_OUTPUT = logFile;
             const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: false, logEntries: [] });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_CONFIG}: Claude execution failed: no structured log entries were produced. This usually indicates a startup or configuration error before tool execution.`);
           } finally {
             fs.unlinkSync(logFile);
@@ -105,14 +105,17 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.unlinkSync(logFile),
             fs.rmdirSync(tmpDir));
         }),
-        it("should handle MCP failures", () => {
+        it("should handle MCP failures", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-")),
             logFile = path.join(tmpDir, "test.log");
           (fs.writeFileSync(logFile, "content"), (process.env.GH_AW_AGENT_OUTPUT = logFile));
           const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: ["server1", "server2"], maxTurnsHit: !1 });
-          (runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }), expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_API}: MCP server(s) failed to launch: server1, server2`), fs.unlinkSync(logFile), fs.rmdirSync(tmpDir));
+          (await runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
+            expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_API}: MCP server(s) failed to launch: server1, server2`),
+            fs.unlinkSync(logFile),
+            fs.rmdirSync(tmpDir));
         }),
-        it("should warn instead of failing MCP failures when safe outputs exist", () => {
+        it("should warn instead of failing MCP failures when safe outputs exist", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           const safeOutputsFile = path.join(tmpDir, "safe-outputs.jsonl");
@@ -124,14 +127,14 @@ describe("log_parser_bootstrap.cjs", () => {
 
           const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: ["server1"], maxTurnsHit: !1 });
 
-          (runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
+          (await runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
             expect(mockCore.warning).toHaveBeenCalledWith("MCP server(s) failed to launch (server1), but agent completed with 1 safe output entry"),
             expect(mockCore.setFailed).not.toHaveBeenCalled(),
             fs.unlinkSync(logFile),
             fs.unlinkSync(safeOutputsFile),
             fs.rmdirSync(tmpDir));
         }),
-        it("should warn (non-fatal) when MCP fails but agent ran turns (legacy result entry)", () => {
+        it("should warn (non-fatal) when MCP fails but agent ran turns (legacy result entry)", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           try {
@@ -149,7 +152,7 @@ describe("log_parser_bootstrap.cjs", () => {
                 { type: "result", num_turns: 34, duration_ms: 60000 },
               ],
             });
-            runLogParser({ parseLog: mockParseLog, parserName: "TestParser" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "TestParser" });
             expect(mockCore.warning).toHaveBeenCalledWith("MCP server(s) failed to launch (github), but agent completed turns — treating as non-fatal post-completion relaunch");
             expect(mockCore.setFailed).not.toHaveBeenCalled();
           } finally {
@@ -157,7 +160,7 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should warn (non-fatal) when MCP fails but agent ran turns (Copilot event session.result)", () => {
+        it("should warn (non-fatal) when MCP fails but agent ran turns (Copilot event session.result)", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           try {
@@ -175,7 +178,7 @@ describe("log_parser_bootstrap.cjs", () => {
                 { type: "session.result", data: { numTurns: 34, durationMs: 60000 } },
               ],
             });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             expect(mockCore.warning).toHaveBeenCalledWith("MCP server(s) failed to launch (github), but agent completed turns — treating as non-fatal post-completion relaunch");
             expect(mockCore.setFailed).not.toHaveBeenCalled();
           } finally {
@@ -183,7 +186,7 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should still fail when MCP fails and agent ran no turns", () => {
+        it("should still fail when MCP fails and agent ran no turns", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           try {
@@ -196,14 +199,14 @@ describe("log_parser_bootstrap.cjs", () => {
               maxTurnsHit: false,
               logEntries: [{ type: "system", subtype: "init" }],
             });
-            runLogParser({ parseLog: mockParseLog, parserName: "TestParser" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "TestParser" });
             expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_API}: MCP server(s) failed to launch: github`);
           } finally {
             fs.unlinkSync(logFile);
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should warn (non-fatal) when Claude has empty logEntries but safe outputs exist", () => {
+        it("should warn (non-fatal) when Claude has empty logEntries but safe outputs exist", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           const safeOutputsFile = path.join(tmpDir, "safe-outputs.jsonl");
@@ -215,7 +218,7 @@ describe("log_parser_bootstrap.cjs", () => {
             // Parser returns markdown but no structured logEntries — simulates sandbox teardown
             // race leaving agent-stdio.log unreadable after the agent completed successfully.
             const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: false, logEntries: [] });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             expect(mockCore.setFailed).not.toHaveBeenCalled();
             expect(mockCore.warning).toHaveBeenCalledWith("Claude produced no structured log entries, but agent completed with 1 safe output entry — treating as non-fatal post-completion infrastructure failure");
           } finally {
@@ -225,7 +228,7 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should fail when Claude has empty logEntries and no safe outputs (startup failure)", () => {
+        it("should fail when Claude has empty logEntries and no safe outputs (startup failure)", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           try {
@@ -233,14 +236,14 @@ describe("log_parser_bootstrap.cjs", () => {
             process.env.GH_AW_AGENT_OUTPUT = logFile;
             delete process.env.GH_AW_SAFE_OUTPUTS;
             const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: false, logEntries: [] });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_CONFIG}: Claude execution failed: no structured log entries were produced. This usually indicates a startup or configuration error before tool execution.`);
           } finally {
             fs.unlinkSync(logFile);
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should not print 'parsed successfully' for Claude when logEntries is empty", () => {
+        it("should not print 'parsed successfully' for Claude when logEntries is empty", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           const safeOutputsFile = path.join(tmpDir, "safe-outputs.jsonl");
@@ -250,7 +253,7 @@ describe("log_parser_bootstrap.cjs", () => {
             process.env.GH_AW_AGENT_OUTPUT = logFile;
             process.env.GH_AW_SAFE_OUTPUTS = safeOutputsFile;
             const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: false, logEntries: [] });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             const infoCalls = mockCore.info.mock.calls.map(c => c[0]);
             expect(infoCalls.some(msg => msg.includes("Claude log parsed successfully"))).toBe(false);
             expect(mockCore.setFailed).not.toHaveBeenCalled();
@@ -262,7 +265,7 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should treat logEntries: null as missing entries for Claude guardrail (no safe outputs → setFailed)", () => {
+        it("should treat logEntries: null as missing entries for Claude guardrail (no safe outputs → setFailed)", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           try {
@@ -270,7 +273,7 @@ describe("log_parser_bootstrap.cjs", () => {
             process.env.GH_AW_AGENT_OUTPUT = logFile;
             delete process.env.GH_AW_SAFE_OUTPUTS;
             const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: false, logEntries: null });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_CONFIG}: Claude execution failed: no structured log entries were produced. This usually indicates a startup or configuration error before tool execution.`);
           } finally {
             fs.unlinkSync(logFile);
@@ -278,7 +281,7 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should treat logEntries: null as missing entries for Claude guardrail (safe outputs → warning)", () => {
+        it("should treat logEntries: null as missing entries for Claude guardrail (safe outputs → warning)", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-"));
           const logFile = path.join(tmpDir, "test.log");
           const safeOutputsFile = path.join(tmpDir, "safe-outputs.jsonl");
@@ -288,7 +291,7 @@ describe("log_parser_bootstrap.cjs", () => {
             process.env.GH_AW_AGENT_OUTPUT = logFile;
             process.env.GH_AW_SAFE_OUTPUTS = safeOutputsFile;
             const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: false, logEntries: null });
-            runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
+            await runLogParser({ parseLog: mockParseLog, parserName: "Claude" });
             expect(mockCore.setFailed).not.toHaveBeenCalled();
             expect(mockCore.warning).toHaveBeenCalledWith("Claude produced no structured log entries, but agent completed with 1 safe output entry — treating as non-fatal post-completion infrastructure failure");
           } finally {
@@ -299,12 +302,12 @@ describe("log_parser_bootstrap.cjs", () => {
             fs.rmdirSync(tmpDir);
           }
         }),
-        it("should handle max-turns limit reached", () => {
+        it("should handle max-turns limit reached", async () => {
           const tmpDir = fs.mkdtempSync(path.join(__dirname, "test-")),
             logFile = path.join(tmpDir, "test.log");
           (fs.writeFileSync(logFile, "content"), (process.env.GH_AW_AGENT_OUTPUT = logFile));
           const mockParseLog = vi.fn().mockReturnValue({ markdown: "## Result\n", mcpFailures: [], maxTurnsHit: !0 });
-          (runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
+          (await runLogParser({ parseLog: mockParseLog, parserName: "TestParser" }),
             expect(mockCore.setFailed).toHaveBeenCalledWith(`${ERR_VALIDATION}: Agent execution stopped: max-turns limit reached. The agent did not complete its task successfully.`),
             fs.unlinkSync(logFile),
             fs.rmdirSync(tmpDir));
diff --git a/pkg/workflow/arc_dind_artifacts.go b/pkg/workflow/arc_dind_artifacts.go
index 2e460acb8e4..46ab9cc6d75 100644
--- a/pkg/workflow/arc_dind_artifacts.go
+++ b/pkg/workflow/arc_dind_artifacts.go
@@ -20,9 +20,9 @@ func rewriteTmpGhAwPathsForArcDind(paths []string) []string {
 	result := make([]string, len(paths))
 	rewritten := 0
 	for i, p := range paths {
-		if strings.HasPrefix(p, constants.TmpGhAwDirSlash) {
+		if after, ok := strings.CutPrefix(p, constants.TmpGhAwDirSlash); ok {
 			// /tmp/gh-aw/foo → ${{ runner.temp }}/gh-aw/foo
-			result[i] = constants.GhAwRootDir + "/" + strings.TrimPrefix(p, constants.TmpGhAwDirSlash)
+			result[i] = constants.GhAwRootDir + "/" + after
 			rewritten++
 		} else if p == constants.TmpGhAwDir {
 			result[i] = constants.GhAwRootDir
