feat: add shared platform buildkite/githubactions BuildRunner clients#423
feat: add shared platform buildkite/githubactions BuildRunner clients#423roychying wants to merge 7 commits into
Conversation
| // Already terminal — no-op per BuildRunner.Cancel contract. | ||
| return nil | ||
| default: | ||
| return fmt.Errorf("unexpected status %d from cancel", resp.StatusCode) |
There was a problem hiding this comment.
would be nice to also include the message into the error, typically in a body of a response; can be truncated if needed.
| } | ||
| defer resp.Body.Close() | ||
|
|
||
| respBody, err := io.ReadAll(resp.Body) |
There was a problem hiding this comment.
this may not properly respond to context cancellation. AI analysis:
Behavior: Vulnerable to blocking/hanging.
Why: io.ReadAll reads from resp.Body until it hits io.EOF. However, once httpClient.Do() successfully receives response headers, the HTTP transport hands the raw stream body to you. Standard response bodies (net/http.bodyEOFSignal or TCP socket readers) do not automatically monitor the request ctx for subsequent reads.
If the server stalls, sends data infinitely slowly, or hangs while streaming the payload after headers have been sent, calling io.ReadAll(resp.Body) will block the goroutine until the connection times out at the network level—even if your ctx was canceled long ago.
The poor man's alternative is buffered read with cancellation checks:
https://github.com/uber/tango/blob/1ed2b86888fc4afc59494d9d97fdd6dc23c2638e/core/storage/ctxreader.go#L25
At least it cancels somewhere in between for long transfers.
| } | ||
|
|
||
| if resp.StatusCode == http.StatusNotFound { | ||
| return fmt.Errorf("build not found") |
There was a problem hiding this comment.
http helper function do() is not necessarily about build. You may want to define sentinel errors to transform http codes into.
| if !ok || raw == "" { | ||
| return meta | ||
| } | ||
| _ = json.Unmarshal([]byte(raw), &meta) |
There was a problem hiding this comment.
let's not swallow errors without proper visibility
because this is an exported function, probably better design is to expose an error and let caller handle it as they see fit
| } | ||
|
|
||
| func buildJSONWithEnv(number int, state, webURL string, env map[string]string) []byte { | ||
| b, _ := json.Marshal(BuildResponse{Number: number, State: state, WebURL: webURL, Env: env}) |
There was a problem hiding this comment.
func buildJSONWithEnv(t *testing.T, number int, state, webURL string, env map[string]string) []byte {
t.Helper()
b, err := json.Marshal(BuildResponse{Number: number, State: state, WebURL: webURL, Env: env})
require.NoError(t, err)
return b
}
| capturedMethod = req.Method | ||
| capturedBody, _ = io.ReadAll(req.Body) | ||
| w.Header().Set("Content-Type", "application/json") | ||
| _, _ = w.Write(buildJSON(42, "scheduled", "https://buildkite.com/test-org/my-pipeline/builds/42")) |
| ) | ||
| } | ||
|
|
||
| func (c *Client) do(ctx context.Context, method, rawURL string, body []byte, out any) error { |
There was a problem hiding this comment.
duplicated code with buildkite impl, can deduce?
| } | ||
| if params.Logger == nil { | ||
| return nil, fmt.Errorf("logger is required") | ||
| } |
There was a problem hiding this comment.
Submitqueue design assumes all wiring to be non-nil, so there is no need to explicitly check it. Panic will do just fine.
| EnvKeyQueue: r.cfg.QueueName, | ||
| } | ||
| if len(metadata) > 0 { | ||
| metaJSON, _ := json.Marshal(metadata) |
There was a problem hiding this comment.
plz do not swallow errors
|
|
||
| _, err := r.Trigger(context.Background(), "", "github://repo/head/aaa", nil) | ||
| require.Error(t, err) | ||
| assert.Contains(t, err.Error(), "response missing workflow_run_id") |
There was a problem hiding this comment.
Do not assume on error messages - messages are not part of application logic and it makes test unnecessary fragile. AGENTS.md has an instruction to avoid it, surprising it was not picked up.
Summary
platform/extension/buildrunner/and refactor the existing submitqueue adapters to use them.BuildRunneradapters on top of the shared clients.Test plan
go build ./...go test ./platform/extension/buildrunner/... ./submitqueue/extension/buildrunner/... ./stovepipe/extension/buildrunner/...make gazelle(no drift)