Skip to content

Add meta-data set-batch command#3791

Open
pda wants to merge 1 commit intomainfrom
add-meta-data-set-batch
Open

Add meta-data set-batch command#3791
pda wants to merge 1 commit intomainfrom
add-meta-data-set-batch

Conversation

@pda
Copy link
Copy Markdown
Member

@pda pda commented Apr 1, 2026

Description

Add a buildkite-agent meta-data set-batch command for setting multiple meta-data key/value pairs in a single API request.

buildkite-agent meta-data set-batch "foo=bar" "baz=qux"

The batch operation is transactional — all items succeed or none do.

Context

Companion to a new POST /v3/jobs/:job_id/data/set-batch API route, which is not yet generally available.

Changes

  • API client: MetaDataBatch type and SetMetaDataBatch method (POST /jobs/{id}/data/set-batch)
  • CLI command: meta-data set-batch subcommand accepting key=value arguments (no stdin support)
  • Tests: table-driven argument parsing tests and HTTP-level tests covering success, error, and no-retry on 401/404
  • Docs: minor correction to import organization note in AGENT.md

Testing

  • Tests have run locally (with go test ./...). Buildkite employees may check this if the pipeline has run automatically.
  • Code is formatted (with go tool gofumpt -extra -w .)

Disclosures / Credits

Amp (Claude Opus 4.6) wrote the implementation and tests with human direction and review.

Add a `buildkite-agent meta-data set-batch` command for setting
multiple meta-data key/value pairs in a single transactional API
request. All items succeed or none do.

Usage:
  buildkite-agent meta-data set-batch "foo=bar" "baz=qux"

Unlike `meta-data set`, values cannot be read from stdin — all
key/value pairs are provided as key=value positional arguments.

API: POST /jobs/{id}/data/set-batch with {"items": [{"key": ...,
"value": ...}, ...]}. Response is 204 No Content on success.

Changes:
- api/meta_data.go: MetaDataBatch type and SetMetaDataBatch method
- clicommand/meta_data_set_batch.go: CLI command with argument
  parsing, secret redaction, and retry logic matching `set`
- clicommand/meta_data_set_batch_test.go: table-driven parsing
  tests and HTTP-level tests (success, server error, 401/404
  no-retry, validation error)
- AGENT.md: correct import organization docs to match gofumpt
  behavior (stdlib, then everything else in one group)

Amp-Thread-ID: https://ampcode.com/threads/T-019d48e9-8854-7158-8dd7-16a883e56b84
Co-authored-by: Amp <amp@ampcode.com>
@pda pda requested review from a team as code owners April 1, 2026 13:10
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a11a13a911

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +116 to +117
if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404) {
r.Break()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Stop retrying unrecoverable 4xx batch validation errors

In setMetaDataBatch, retries are only disabled for 401/404, so other deterministic client-side failures (for example a 422 validation error from POST /jobs/:id/data/set-batch) are retried up to 10 times with exponential backoff before returning. That turns immediate user/input errors into long waits and makes this command appear hung for cases that can never succeed on retry; this path should break retries for unrecoverable 4xx responses (at least 400/422, while preserving retry for transient statuses like 429 if desired).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🤖 Valid observation, but this intentionally matches the existing meta-data set command, which has the same retry behaviour (only breaks on 401/404). Broadening the no-retry set for 4xx could be a good improvement, but it should be done consistently across both commands.


Set multiple meta-data key/value pairs on a build in a single request.

Each argument must be in key=value format.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we support JSON input (over stdin)?

Copy link
Copy Markdown
Member Author

@pda pda Apr 1, 2026

Choose a reason for hiding this comment

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

Maybe!
Do you think that would change the CLI design? 🤔

Would it look like one/some of these…

buildkite-agent meta-data set-batch < meta-data.json

buildkite-agent meta-data set-batch --json < meta-data.json

buildkite-agent meta-data set-batch --from-file meta-data.json

I mostly didn't add it because it contained more decisions 😅

If we think the current argv approach needs to change to make room for JSON/stdin input, I'll revise it. But if we think there's room at add it later, I'd rather defer it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

(In my initial use-case, I have a bash script coordinating some build concerns, and it's rounding up lots of information and then setting ~8 meta-data key=values. I could push that into JSON structure, perhaps using jq as a builder, but it's a much better fit to just build an array of key=value strings and put them on argv)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I foresee it being useful if something other than Bash is orchestrating. We have JSON input in some other commands. But I agree it can be done later.

Comment on lines +98 to +100
if strings.TrimSpace(value) == "" {
return nil, fmt.Errorf("invalid argument %q: value cannot be empty, or composed of only whitespace characters", arg)
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we offer a way to "clear" a particular key? key= (nothing following) seems like a reasonable syntax for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants