Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion pkg/cli/fix_codemods.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package cli

import "github.com/github/gh-aw/pkg/logger"

var fixCodemodsLog = logger.New("cli:fix_codemods")

// Codemod represents a single code transformation that can be applied to workflow files
type Codemod struct {
ID string // Unique identifier for the codemod
Expand All @@ -17,7 +21,7 @@ type CodemodResult struct {

// GetAllCodemods returns all available codemods in the registry
func GetAllCodemods() []Codemod {
return []Codemod{
codemods := []Codemod{
getTimeoutMinutesCodemod(),
getNetworkFirewallCodemod(),
getCommandToSlashCommandCodemod(),
Expand Down Expand Up @@ -45,4 +49,6 @@ func GetAllCodemods() []Codemod {
getSerenaLocalModeCodemod(), // Replace tools.serena mode: local with mode: docker
getGitHubAppCodemod(), // Rename deprecated 'app' to 'github-app'
}
fixCodemodsLog.Printf("Loaded codemod registry: %d codemods available", len(codemods))
return codemods
}
11 changes: 10 additions & 1 deletion pkg/console/spinner.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,13 @@ import (

"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/github/gh-aw/pkg/logger"
"github.com/github/gh-aw/pkg/styles"
"github.com/github/gh-aw/pkg/tty"
)

var spinnerLog = logger.New("console:spinner")

// updateMessageMsg is a custom message for updating the spinner message
type updateMessageMsg string

Expand Down Expand Up @@ -101,7 +104,10 @@ type SpinnerWrapper struct {
// NewSpinner creates a new spinner with the given message using MiniDot style.
// Automatically disabled when not running in a TTY or when ACCESSIBLE env var is set.
func NewSpinner(message string) *SpinnerWrapper {
enabled := tty.IsStderrTerminal() && os.Getenv("ACCESSIBLE") == ""
isTTY := tty.IsStderrTerminal()
isAccessible := os.Getenv("ACCESSIBLE") != ""
enabled := isTTY && !isAccessible
spinnerLog.Printf("Creating spinner: message=%q, tty=%t, accessible=%t, enabled=%t", message, isTTY, isAccessible, enabled)
s := &SpinnerWrapper{enabled: enabled}

if enabled {
Expand All @@ -120,11 +126,13 @@ func (s *SpinnerWrapper) Start() {
s.mu.Lock()
if s.running {
s.mu.Unlock()
spinnerLog.Print("Spinner already running, skipping Start")
return
}
s.running = true
s.wg.Add(1)
s.mu.Unlock()
spinnerLog.Print("Starting spinner")
go func() {
defer s.wg.Done()
_, _ = s.program.Run()
Expand All @@ -138,6 +146,7 @@ func (s *SpinnerWrapper) Stop() {
if s.running {
s.running = false
s.mu.Unlock()
spinnerLog.Print("Stopping spinner")
s.program.Quit()
s.wg.Wait() // Wait for the goroutine to complete
fmt.Fprintf(os.Stderr, "%s%s", ansiCarriageReturn, ansiClearLine)
Expand Down
11 changes: 10 additions & 1 deletion pkg/parser/import_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,14 @@ type ImportSpec struct {
// ProcessImportsFromFrontmatterWithSource processes imports field from frontmatter with source tracking
// This version includes the workflow file path and YAML content for better error reporting
func ProcessImportsFromFrontmatterWithSource(frontmatter map[string]any, baseDir string, cache *ImportCache, workflowFilePath string, yamlContent string) (*ImportsResult, error) {
return processImportsFromFrontmatterWithManifestAndSource(frontmatter, baseDir, cache, workflowFilePath, yamlContent)
importLog.Printf("Processing imports: workflowFile=%s, baseDir=%s", workflowFilePath, baseDir)
result, err := processImportsFromFrontmatterWithManifestAndSource(frontmatter, baseDir, cache, workflowFilePath, yamlContent)
if err != nil {
importLog.Printf("Import processing failed for %s: %v", workflowFilePath, err)
return result, err
}
if result != nil {
importLog.Printf("Import processing complete: importedFiles=%d, mergedTools=%d bytes", len(result.ImportedFiles), len(result.MergedTools))
}
return result, nil
}
12 changes: 10 additions & 2 deletions pkg/stringutil/identifiers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package stringutil
import (
"path/filepath"
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var identifiersLog = logger.New("stringutil:identifiers")

// NormalizeWorkflowName removes .md and .lock.yml extensions from workflow names.
// This is used to standardize workflow identifiers regardless of the file format.
//
Expand Down Expand Up @@ -75,7 +79,9 @@ func MarkdownToLockFile(mdPath string) string {
}

cleaned := filepath.Clean(mdPath)
return strings.TrimSuffix(cleaned, ".md") + ".lock.yml"
lockPath := strings.TrimSuffix(cleaned, ".md") + ".lock.yml"
identifiersLog.Printf("MarkdownToLockFile: %s -> %s", mdPath, lockPath)
return lockPath
}

// LockFileToMarkdown converts a compiled lock file path back to its markdown source path.
Expand All @@ -97,5 +103,7 @@ func LockFileToMarkdown(lockPath string) string {
}

cleaned := filepath.Clean(lockPath)
return strings.TrimSuffix(cleaned, ".lock.yml") + ".md"
mdPath := strings.TrimSuffix(cleaned, ".lock.yml") + ".md"
identifiersLog.Printf("LockFileToMarkdown: %s -> %s", lockPath, mdPath)
return mdPath
}
6 changes: 6 additions & 0 deletions pkg/stringutil/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package stringutil
import (
"net/url"
"strings"

"github.com/github/gh-aw/pkg/logger"
)

var urlsLog = logger.New("stringutil:urls")

// NormalizeGitHubHostURL ensures the host URL has a scheme (defaulting to https://) and no trailing slashes.
// It is safe to call with URLs that already have an http:// or https:// scheme.
func NormalizeGitHubHostURL(rawHostURL string) string {
Expand Down Expand Up @@ -35,12 +39,14 @@ func NormalizeGitHubHostURL(rawHostURL string) string {
// ExtractDomainFromURL("http://sub.domain.com:8080/path") // returns "sub.domain.com"
// ExtractDomainFromURL("localhost:8080") // returns "localhost"
func ExtractDomainFromURL(urlStr string) string {
urlsLog.Printf("Extracting domain from URL: %s", urlStr)
// Handle full URLs with protocols (http://, https://)
if strings.HasPrefix(urlStr, "http://") || strings.HasPrefix(urlStr, "https://") {
// Parse full URL
parsedURL, err := url.Parse(urlStr)
if err != nil {
// Fall back to string manipulation if parsing fails
urlsLog.Printf("URL parse failed, using fallback: %v", err)
Comment on lines +42 to +49
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ExtractDomainFromURL logs the full input URL. This helper is used on access log entries and workflow tool URLs (e.g., Squid logs), which may include sensitive data in query strings, fragments, or userinfo. Consider logging only the extracted hostname (or a redacted form that strips query/fragment/userinfo) to avoid leaking secrets when DEBUG is enabled; similarly avoid printing the raw parse error if it may echo the original URL.

Suggested change
urlsLog.Printf("Extracting domain from URL: %s", urlStr)
// Handle full URLs with protocols (http://, https://)
if strings.HasPrefix(urlStr, "http://") || strings.HasPrefix(urlStr, "https://") {
// Parse full URL
parsedURL, err := url.Parse(urlStr)
if err != nil {
// Fall back to string manipulation if parsing fails
urlsLog.Printf("URL parse failed, using fallback: %v", err)
urlsLog.Printf("Extracting domain from URL")
// Handle full URLs with protocols (http://, https://)
if strings.HasPrefix(urlStr, "http://") || strings.HasPrefix(urlStr, "https://") {
// Parse full URL
parsedURL, err := url.Parse(urlStr)
if err != nil {
// Fall back to string manipulation if parsing fails
urlsLog.Printf("URL parse failed, using fallback")

Copilot uses AI. Check for mistakes.
return extractDomainFallback(urlStr)
}
return parsedURL.Hostname()
Expand Down
Loading