fix: multiple platform handler bug fixes
- secrets.go: Log RowsAffected errors instead of silently discarding them - a2a_proxy.go: Add 60s safety timeout to a2aClient HTTP client - terminal.go: Fix defer ordering - always close WebSocket conn on error, only defer resp.Close() after successful exec attach - webhooks.go: Add shortSHA() helper to safely handle empty HeadSHA Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
14c36e1bbd
commit
87778c5c1b
@ -87,7 +87,9 @@ const maxProxyResponseBody = 10 << 20
|
||||
// a2aClient is a shared HTTP client for proxying A2A requests to workspace agents.
|
||||
// No client-level timeout — timeouts are enforced per-request via context deadlines:
|
||||
// canvas = 5 min (Rule 3), agent-to-agent = 30 min (DoS cap).
|
||||
var a2aClient = &http.Client{}
|
||||
var a2aClient = &http.Client{
|
||||
Timeout: 60 * time.Second, // Safety net for when context deadlines are missing
|
||||
}
|
||||
|
||||
type proxyA2AError struct {
|
||||
Status int
|
||||
|
||||
@ -276,7 +276,10 @@ func (h *SecretsHandler) Delete(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rows, _ := result.RowsAffected()
|
||||
rows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
log.Printf("DeleteWorkspace: RowsAffected error: %v", err)
|
||||
}
|
||||
if rows == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "secret not found"})
|
||||
return
|
||||
@ -418,7 +421,10 @@ func (h *SecretsHandler) DeleteGlobal(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
rows, _ := result.RowsAffected()
|
||||
rows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
log.Printf("DeleteGlobal: RowsAffected error: %v", err)
|
||||
}
|
||||
if rows == 0 {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "secret not found"})
|
||||
return
|
||||
|
||||
@ -97,7 +97,6 @@ func (h *TerminalHandler) HandleConnect(c *gin.Context) {
|
||||
log.Printf("Terminal WebSocket upgrade error: %v", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// No hard session deadline — terminal stays open as long as there is activity.
|
||||
// The idle timeout (terminalSessionTimeout) resets on each keystroke in the
|
||||
@ -108,6 +107,7 @@ func (h *TerminalHandler) HandleConnect(c *gin.Context) {
|
||||
// ContainerExecCreate succeeds even if the binary doesn't exist — the error
|
||||
// only surfaces at attach/start time, so we must retry at the attach level.
|
||||
var resp types.HijackedResponse
|
||||
var execErr error
|
||||
for _, shell := range []string{"/bin/bash", "/bin/sh"} {
|
||||
execCfg := container.ExecOptions{
|
||||
Cmd: []string{shell},
|
||||
@ -118,20 +118,21 @@ func (h *TerminalHandler) HandleConnect(c *gin.Context) {
|
||||
}
|
||||
execID, createErr := h.docker.ContainerExecCreate(ctx, containerName, execCfg)
|
||||
if createErr != nil {
|
||||
err = createErr
|
||||
execErr = createErr
|
||||
continue
|
||||
}
|
||||
resp, err = h.docker.ContainerExecAttach(ctx, execID.ID, container.ExecAttachOptions{Tty: true})
|
||||
if err == nil {
|
||||
resp, execErr = h.docker.ContainerExecAttach(ctx, execID.ID, container.ExecAttachOptions{Tty: true})
|
||||
if execErr == nil {
|
||||
defer resp.Close()
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Terminal exec error: %v", err)
|
||||
if execErr != nil {
|
||||
log.Printf("Terminal exec error: %v", execErr)
|
||||
conn.WriteMessage(websocket.TextMessage, []byte("Error: failed to create shell session\r\n"))
|
||||
conn.Close()
|
||||
return
|
||||
}
|
||||
defer resp.Close()
|
||||
|
||||
// Bridge: container stdout → WebSocket
|
||||
done := make(chan struct{})
|
||||
|
||||
@ -33,6 +33,15 @@ func NewWebhookHandlerWithWorkspace(workspaces *WorkspaceHandler) *WebhookHandle
|
||||
}
|
||||
}
|
||||
|
||||
// shortSHA returns the first n characters of a commit SHA, or the
|
||||
// full value if it's shorter than n. Safe for empty strings.
|
||||
func shortSHA(sha string) string {
|
||||
if len(sha) < 7 {
|
||||
return sha
|
||||
}
|
||||
return sha[:7]
|
||||
}
|
||||
|
||||
// GitHub handles POST /webhooks/github/:id
|
||||
// It verifies X-Hub-Signature-256, maps supported events to A2A message/send,
|
||||
// then forwards through the same proxy flow used by /workspaces/:id/a2a.
|
||||
@ -266,7 +275,7 @@ func buildGitHubA2APayload(eventType, deliveryID string, rawBody []byte) (string
|
||||
payload.WorkflowRun.RunNumber,
|
||||
payload.WorkflowRun.Conclusion,
|
||||
payload.WorkflowRun.HeadBranch,
|
||||
payload.WorkflowRun.HeadSHA[:min(7, len(payload.WorkflowRun.HeadSHA))],
|
||||
shortSHA(payload.WorkflowRun.HeadSHA),
|
||||
payload.Sender.Login,
|
||||
payload.WorkflowRun.Event,
|
||||
payload.Repository.FullName,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user