From 3d7669f732ef9acbb41add4c7ef58c8466dad8d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 24 May 2026 05:33:04 +0000 Subject: [PATCH 1/2] Initial plan From 8f5f566086c2fb3ce02cdf4c9de963efd64ea8d2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 24 May 2026 05:41:08 +0000 Subject: [PATCH 2/2] Fix deferred file closes in cli readers Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- pkg/cli/mcp_logs_guardrail.go | 33 +++++++++++++++----------- pkg/cli/workflows.go | 44 +++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/pkg/cli/mcp_logs_guardrail.go b/pkg/cli/mcp_logs_guardrail.go index e11e9bbbeae..a424300a27e 100644 --- a/pkg/cli/mcp_logs_guardrail.go +++ b/pkg/cli/mcp_logs_guardrail.go @@ -84,21 +84,26 @@ func buildLogsFileResponse(outputStr string) string { mcpLogsGuardrailLog.Printf("Logs data already cached at: %s", filePath) } else if os.IsNotExist(err) { // Write with O_EXCL to avoid following symlinks or races. - f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, constants.FilePermPublic) - if err != nil { - mcpLogsGuardrailLog.Printf("Failed to create logs cache file: %v", err) - return buildLogsFileErrorResponse(fmt.Sprintf("failed to create logs cache file: %v", err)) - } - _, writeErr := f.WriteString(outputStr) - closeErr := f.Close() - if writeErr != nil || closeErr != nil { - _ = os.Remove(filePath) - errMsg := writeErr - if errMsg == nil { - errMsg = closeErr + writeErr := func() (err error) { + f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, constants.FilePermPublic) + if err != nil { + return fmt.Errorf("failed to create logs cache file: %w", err) } - mcpLogsGuardrailLog.Printf("Failed to write logs data to file: %v", errMsg) - return buildLogsFileErrorResponse(fmt.Sprintf("failed to write logs data to file: %v", errMsg)) + defer func() { + if closeErr := f.Close(); closeErr != nil && err == nil { + err = fmt.Errorf("failed to write logs data to file: %w", closeErr) + } + }() + + if _, err = f.WriteString(outputStr); err != nil { + return fmt.Errorf("failed to write logs data to file: %w", err) + } + return nil + }() + if writeErr != nil { + mcpLogsGuardrailLog.Printf("%v", writeErr) + _ = os.Remove(filePath) + return buildLogsFileErrorResponse(writeErr.Error()) } if chmodErr := os.Chmod(filePath, constants.FilePermPublic); chmodErr != nil { _ = os.Remove(filePath) diff --git a/pkg/cli/workflows.go b/pkg/cli/workflows.go index fffbcdd0c14..f23332e0144 100644 --- a/pkg/cli/workflows.go +++ b/pkg/cli/workflows.go @@ -304,19 +304,26 @@ func getMarkdownWorkflowFiles(workflowDir string) ([]string, error) { func filterMarkdownFilesWithFrontmatter(mdFiles []string) ([]string, error) { workflowFiles := make([]string, 0, len(mdFiles)) for _, file := range mdFiles { - fd, err := os.Open(file) + firstLine, err := func() (firstLine string, err error) { + fd, err := os.Open(file) + if err != nil { + return "", fmt.Errorf("failed to read workflow file %s: %w", file, err) + } + defer func() { + if closeErr := fd.Close(); closeErr != nil && err == nil { + err = fmt.Errorf("failed to close workflow file %s: %w", file, closeErr) + } + }() + + reader := bufio.NewReader(fd) + firstLine, err = reader.ReadString('\n') + if err != nil && !errors.Is(err, io.EOF) { + return "", fmt.Errorf("failed to read workflow file %s: %w", file, err) + } + return firstLine, nil + }() if err != nil { - return nil, fmt.Errorf("failed to read workflow file %s: %w", file, err) - } - - reader := bufio.NewReader(fd) - firstLine, readErr := reader.ReadString('\n') - closeErr := fd.Close() - if closeErr != nil { - return nil, fmt.Errorf("failed to close workflow file %s: %w", file, closeErr) - } - if readErr != nil && !errors.Is(readErr, io.EOF) { - return nil, fmt.Errorf("failed to read workflow file %s: %w", file, readErr) + return nil, err } if firstLine == "" { @@ -392,20 +399,21 @@ func fastParseTitleFromReader(r io.Reader) (string, error) { } // extractWorkflowNameFromFile extracts the workflow name from a file's H1 header -func extractWorkflowNameFromFile(filePath string) (string, error) { +func extractWorkflowNameFromFile(filePath string) (title string, err error) { fd, err := os.Open(filePath) if err != nil { return "", err } + defer func() { + if closeErr := fd.Close(); closeErr != nil && err == nil { + err = fmt.Errorf("failed to close workflow file %s: %w", filePath, closeErr) + } + }() - title, err := fastParseTitleFromReader(fd) - closeErr := fd.Close() + title, err = fastParseTitleFromReader(fd) if err != nil { return "", err } - if closeErr != nil { - return "", fmt.Errorf("failed to close workflow file %s: %w", filePath, closeErr) - } if title != "" { return title, nil }