diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index b84879b3..5c92c651 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -29,7 +29,7 @@ jobs: - name: Set up Go uses: useblacksmith/setup-go@v6 with: - go-version: '1.24' + go-version: '1.25' - name: Generate Error Codes run: go generate ./... diff --git a/.github/workflows/upgrade-test.yml b/.github/workflows/upgrade-test.yml index d0506fb9..505bb8d3 100644 --- a/.github/workflows/upgrade-test.yml +++ b/.github/workflows/upgrade-test.yml @@ -33,14 +33,14 @@ jobs: uses: actions/setup-go@v5 if: ${{ matrix.os != 'blacksmith-4vcpu-ubuntu-2204' }} with: - go-version: '1.24' + go-version: '1.25' cache: true - name: Set up Go uses: useblacksmith/setup-go@v6 if: ${{ matrix.os == 'blacksmith-4vcpu-ubuntu-2204' }} with: - go-version: '1.24' + go-version: '1.25' cache: true - name: Build current version diff --git a/go.mod b/go.mod index 5678d410..ef3b25e6 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,10 @@ module github.com/agentuity/cli -go 1.24.4 +go 1.25 require ( github.com/Masterminds/semver v1.5.0 - github.com/agentuity/go-common v1.0.67 + github.com/agentuity/go-common v1.0.71 github.com/agentuity/mcp-golang/v2 v2.0.2 github.com/bmatcuk/doublestar/v4 v4.8.1 github.com/charmbracelet/bubbles v0.20.0 @@ -29,6 +29,7 @@ require ( require ( dario.cat/mergo v1.0.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.1.5 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect diff --git a/go.sum b/go.sum index d3b11180..8fe187fd 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= @@ -9,8 +11,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4= github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= -github.com/agentuity/go-common v1.0.67 h1:Pw6Lv/2eJ+F4kZZgnZhYy3JyTzA3VEa64h/BPSfayxw= -github.com/agentuity/go-common v1.0.67/go.mod h1:cy1EPYpZUkp3JSMgTb+Sa3sLnS7vQQupj/RwO4An6L4= +github.com/agentuity/go-common v1.0.71 h1:W8ynuxcXKfrDNcCWNAoAzqhfMt8oTBR4ALVJJelE0Yw= +github.com/agentuity/go-common v1.0.71/go.mod h1:qMuSKhvnSAyje6MB1XLSp6xC4d17Hy6FiE3NDYFr9pk= github.com/agentuity/mcp-golang/v2 v2.0.2 h1:wZqS/aHWZsQoU/nd1E1/iMsVY2dywWT9+PFlf+3YJxo= github.com/agentuity/mcp-golang/v2 v2.0.2/go.mod h1:U105tZXyTatxxOBlcObRgLb/ULvGgT2DJ1nq/8++P6Q= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= diff --git a/internal/templates/steps.go b/internal/templates/steps.go index 30ce6472..24db036d 100644 --- a/internal/templates/steps.go +++ b/internal/templates/steps.go @@ -40,26 +40,47 @@ type CommandStep struct { var _ Step = (*CommandStep)(nil) +const commandExecTimeout = time.Minute * 2 + func (s *CommandStep) Run(ctx TemplateContext) error { ctx.Logger.Debug("Running command: %s with args: %s", s.Command, strings.Join(s.Args, " ")) - timeoutCtx, cancel := context.WithTimeout(ctx.Context, 1*time.Minute) + started := time.Now() + timeoutCtx, cancel := context.WithTimeout(ctx.Context, commandExecTimeout) defer cancel() cmd := exec.CommandContext(timeoutCtx, s.Command, s.Args...) cmd.Dir = ctx.ProjectDir cmd.Stdin = nil out, err := cmd.CombinedOutput() + + buf := strings.TrimSpace(string(out)) + if buf != "" { + ctx.Logger.Debug("Command output: %s", buf) + } + + if cmd.ProcessState != nil { + ctx.Logger.Debug("command exit code %d (took %v)", cmd.ProcessState.ExitCode(), time.Since(started)) + } + + if timeoutCtx.Err() == context.DeadlineExceeded { + ctx.Logger.Error("command: %s %s timed out after %v", s.Command, strings.Join(s.Args, " "), time.Since(started)) + } + if err != nil { + ctx.Logger.Debug("command failed with error: %s (%T)", err, err) if s.Command == "uv" && len(s.Args) >= 3 && s.Args[0] == "add" { exitErr, ok := err.(*exec.ExitError) if ok && exitErr.ExitCode() == 130 { packages := s.Args[2:] ctx.Logger.Debug("Command interrupted with SIGINT (130), trying alternative installation methods for: %v", packages) - altCmd := exec.CommandContext(ctx.Context, "uv", "pip", "install") + fallbackCtx1, fallbackCancel1 := context.WithTimeout(ctx.Context, commandExecTimeout) + defer fallbackCancel1() + altCmd := exec.CommandContext(fallbackCtx1, "uv", "pip", "install") altCmd.Args = append(altCmd.Args, packages...) altCmd.Dir = ctx.ProjectDir + altCmd.Stdin = nil altOut, altErr := altCmd.CombinedOutput() if altErr == nil { @@ -68,9 +89,12 @@ func (s *CommandStep) Run(ctx TemplateContext) error { } ctx.Logger.Debug("Failed to install with uv pip, trying with pip: %v", altErr) - pipCmd := exec.CommandContext(ctx.Context, "pip", "install") + fallbackCtx2, fallbackCancel2 := context.WithTimeout(ctx.Context, commandExecTimeout) + defer fallbackCancel2() + pipCmd := exec.CommandContext(fallbackCtx2, "pip", "install") pipCmd.Args = append(pipCmd.Args, packages...) pipCmd.Dir = ctx.ProjectDir + pipCmd.Stdin = nil pipOut, pipErr := pipCmd.CombinedOutput() if pipErr == nil { @@ -83,13 +107,9 @@ func (s *CommandStep) Run(ctx TemplateContext) error { } } - return fmt.Errorf("failed to run command: %s with args: %s: %w (%s)", s.Command, strings.Join(s.Args, " "), err, string(out)) + return fmt.Errorf("failed to run command: %s with args: %s: %w (%s)", s.Command, strings.Join(s.Args, " "), err, buf) } - buf := strings.TrimSpace(string(out)) - if buf != "" { - ctx.Logger.Debug("Command output: %s", buf) - } return nil }