Showing preview only (1,483K chars total). Download the full file or copy to clipboard to get everything.
Repository: buildkite/cli
Branch: main
Commit: 02d27513e1cd
Files: 272
Total size: 1.4 MB
Directory structure:
gitextract_4e0fgwb8/
├── .buildkite/
│ ├── hooks/
│ │ └── pre-command
│ ├── pipeline.release.yml
│ ├── pipeline.yml
│ ├── release.sh
│ ├── tag.sh
│ └── upload-packages.sh
├── .dockerignore
├── .github/
│ ├── CODEOWNERS
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ └── pull_request_template.md
├── .gitignore
├── .golangci.yaml
├── .goreleaser.yaml
├── .graphqlrc.yml
├── AGENT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE.md
├── README.md
├── cmd/
│ ├── agent/
│ │ ├── agent_test.go
│ │ ├── install.go
│ │ ├── list.go
│ │ ├── list_test.go
│ │ ├── pause.go
│ │ ├── pause_test.go
│ │ ├── resume.go
│ │ ├── resume_test.go
│ │ ├── run.go
│ │ ├── stop.go
│ │ ├── stop_test.go
│ │ ├── util.go
│ │ ├── view.go
│ │ └── view_test.go
│ ├── api/
│ │ ├── api.go
│ │ └── api_test.go
│ ├── artifacts/
│ │ ├── download.go
│ │ └── list.go
│ ├── auth/
│ │ ├── login.go
│ │ ├── login_test.go
│ │ ├── logout.go
│ │ ├── status.go
│ │ ├── switch.go
│ │ ├── switch_test.go
│ │ └── token.go
│ ├── build/
│ │ ├── cancel.go
│ │ ├── create.go
│ │ ├── download.go
│ │ ├── list.go
│ │ ├── list_test.go
│ │ ├── rebuild.go
│ │ ├── view.go
│ │ ├── view_test.go
│ │ └── watch.go
│ ├── cluster/
│ │ ├── cluster_test.go
│ │ ├── create.go
│ │ ├── delete.go
│ │ ├── list.go
│ │ ├── update.go
│ │ └── view.go
│ ├── config/
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── get.go
│ │ ├── list.go
│ │ ├── set.go
│ │ └── unset.go
│ ├── configure/
│ │ ├── configure.go
│ │ ├── configure_case_test.go
│ │ └── configure_test.go
│ ├── generate/
│ │ └── generate.go
│ ├── init/
│ │ ├── init.go
│ │ └── init_test.go
│ ├── job/
│ │ ├── cancel.go
│ │ ├── cancel_test.go
│ │ ├── graphql/
│ │ │ ├── cancel.graphql
│ │ │ ├── jobs.graphql
│ │ │ ├── retry.graphql
│ │ │ └── unblock.graphql
│ │ ├── list.go
│ │ ├── list_test.go
│ │ ├── log.go
│ │ ├── reprioritize.go
│ │ ├── retry.go
│ │ ├── unblock.go
│ │ └── unblock_test.go
│ ├── maintainer/
│ │ ├── create.go
│ │ ├── delete.go
│ │ ├── list.go
│ │ └── maintainer_test.go
│ ├── organization/
│ │ └── list.go
│ ├── pipeline/
│ │ ├── convert.go
│ │ ├── convert_test.go
│ │ ├── copy.go
│ │ ├── create.go
│ │ ├── create_test.go
│ │ ├── graphql/
│ │ │ └── create_webhook.graphql
│ │ ├── list.go
│ │ ├── validate.go
│ │ ├── validate_test.go
│ │ └── view.go
│ ├── pkg/
│ │ ├── push.go
│ │ └── push_test.go
│ ├── preflight/
│ │ ├── cleanup_cmd.go
│ │ ├── cleanup_cmd_test.go
│ │ ├── event.go
│ │ ├── event_test.go
│ │ ├── job_presenter.go
│ │ ├── job_presenter_test.go
│ │ ├── preflight.go
│ │ ├── preflight_test.go
│ │ ├── render.go
│ │ ├── render_test.go
│ │ ├── result.go
│ │ ├── result_test.go
│ │ ├── test_presenter.go
│ │ ├── test_presenter_test.go
│ │ ├── tty.go
│ │ └── tty_test.go
│ ├── queue/
│ │ ├── create.go
│ │ ├── delete.go
│ │ ├── list.go
│ │ ├── pause.go
│ │ ├── queue_test.go
│ │ ├── resume.go
│ │ ├── update.go
│ │ └── view.go
│ ├── secret/
│ │ ├── create.go
│ │ ├── delete.go
│ │ ├── get.go
│ │ ├── list.go
│ │ ├── secret_test.go
│ │ └── update.go
│ ├── skill/
│ │ ├── skill.go
│ │ └── skill_test.go
│ ├── use/
│ │ └── use.go
│ ├── user/
│ │ └── invite.go
│ ├── version/
│ │ ├── update_check.go
│ │ ├── update_check_test.go
│ │ └── version.go
│ └── whoami/
│ └── whoami.go
├── docs/
│ └── shell-prompt-integration.md
├── fixtures/
│ ├── build.json
│ └── config/
│ ├── local.basic.yaml
│ └── user.basic.yaml
├── genqlient.yaml
├── go.mod
├── go.sum
├── internal/
│ ├── agent/
│ │ ├── download.go
│ │ ├── download_test.go
│ │ ├── platform.go
│ │ ├── platform_test.go
│ │ ├── token.go
│ │ └── token_test.go
│ ├── annotation/
│ │ ├── annotation.go
│ │ └── list.go
│ ├── artifact/
│ │ ├── artifact.go
│ │ └── view.go
│ ├── build/
│ │ ├── build.go
│ │ ├── resolver/
│ │ │ ├── cli.go
│ │ │ ├── cli_test.go
│ │ │ ├── options/
│ │ │ │ ├── options.go
│ │ │ │ └── options_test.go
│ │ │ ├── resolver.go
│ │ │ ├── url.go
│ │ │ └── with_options.go
│ │ ├── state/
│ │ │ ├── state.go
│ │ │ └── state_test.go
│ │ ├── view/
│ │ │ ├── shared/
│ │ │ │ └── summary.go
│ │ │ ├── view.go
│ │ │ └── view_test.go
│ │ └── watch/
│ │ ├── job.go
│ │ ├── test_tracker.go
│ │ ├── test_tracker_test.go
│ │ ├── tracker.go
│ │ ├── tracker_test.go
│ │ ├── watch.go
│ │ └── watch_test.go
│ ├── cli/
│ │ └── context.go
│ ├── cluster/
│ │ ├── list_queues.graphql
│ │ ├── query.go
│ │ └── view.go
│ ├── config/
│ │ ├── config.go
│ │ └── config_test.go
│ ├── emoji/
│ │ ├── emoji.go
│ │ └── emoji_test.go
│ ├── errors/
│ │ ├── README.md
│ │ ├── api.go
│ │ ├── api_test.go
│ │ ├── errors.go
│ │ ├── errors_test.go
│ │ ├── handler.go
│ │ └── handler_test.go
│ ├── graphql/
│ │ └── generated.go
│ ├── http/
│ │ ├── README.md
│ │ ├── client.go
│ │ ├── client_test.go
│ │ ├── ratelimit.go
│ │ ├── ratelimit_test.go
│ │ ├── refresh_transport.go
│ │ └── refresh_transport_test.go
│ ├── io/
│ │ ├── confirm.go
│ │ ├── input.go
│ │ ├── pager.go
│ │ ├── pager_test.go
│ │ ├── progress.go
│ │ ├── progress_test.go
│ │ ├── prompt.go
│ │ ├── prompt_test.go
│ │ ├── readline.go
│ │ ├── spinner.go
│ │ ├── spinner_test.go
│ │ └── terminal.go
│ ├── job/
│ │ └── view.go
│ ├── organization/
│ │ └── organization.graphql
│ ├── pipeline/
│ │ ├── pipeline.go
│ │ └── resolver/
│ │ ├── cli.go
│ │ ├── cli_test.go
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── flag.go
│ │ ├── flag_test.go
│ │ ├── picker.go
│ │ ├── picker_test.go
│ │ ├── repository.go
│ │ ├── repository_test.go
│ │ ├── resolver.go
│ │ └── resolver_test.go
│ ├── preflight/
│ │ ├── branch_build.go
│ │ ├── branch_build_test.go
│ │ ├── cleanup.go
│ │ ├── cleanup_test.go
│ │ ├── exit_policy.go
│ │ ├── git.go
│ │ ├── run_summary.go
│ │ ├── run_summary_test.go
│ │ ├── snapshot.go
│ │ └── snapshot_test.go
│ ├── secret/
│ │ └── view.go
│ ├── user/
│ │ └── user.graphql
│ ├── util/
│ │ └── util.go
│ └── validation/
│ ├── errors.go
│ ├── rule.go
│ ├── validator.go
│ └── validator_test.go
├── lefthook.yml
├── main.go
├── main_test.go
├── mise.toml
├── pkg/
│ ├── analytics/
│ │ ├── analytics.go
│ │ └── logger.go
│ ├── cmd/
│ │ ├── factory/
│ │ │ ├── factory.go
│ │ │ └── factory_test.go
│ │ └── validation/
│ │ ├── config.go
│ │ └── config_test.go
│ ├── keyring/
│ │ ├── keyring.go
│ │ └── keyring_test.go
│ ├── oauth/
│ │ ├── oauth.go
│ │ ├── oauth_test.go
│ │ └── refresh_test.go
│ └── output/
│ ├── color.go
│ ├── flags.go
│ ├── flags_test.go
│ ├── output.go
│ ├── output_test.go
│ ├── table.go
│ ├── table_test.go
│ ├── value.go
│ ├── viewable.go
│ └── viewable_test.go
├── renovate.json
└── schema.graphql
================================================
FILE CONTENTS
================================================
================================================
FILE: .buildkite/hooks/pre-command
================================================
#!/usr/bin/env bash
set -euo pipefail
checkout_path="${BUILDKITE_BUILD_CHECKOUT_PATH:-$(pwd)}"
cache_root="${checkout_path}/.buildkite/cache-volume"
mkdir -p \
"${cache_root}/go/build" \
"${cache_root}/go/pkg/mod" \
"${cache_root}/golangci-lint"
export GOCACHE="${cache_root}/go/build"
export GOMODCACHE="${cache_root}/go/pkg/mod"
export GOLANGCI_LINT_CACHE="${cache_root}/golangci-lint"
================================================
FILE: .buildkite/pipeline.release.yml
================================================
agents:
queue: hosted
cache: ".buildkite/cache-volume"
steps:
- label: ":terminal: build ({{matrix}})"
key: build
matrix:
- "darwin"
- "linux"
- "windows"
artifact_paths:
- dist/**/*
secrets:
- MISE_GITHUB_TOKEN
- POSTHOG_API_KEY
- OAUTH_CLIENT_ID
command: 'GOOS="{{matrix}}" .buildkite/release.sh release --clean --split'
plugins:
- mise#v1.1.2: ~
- label: ":rocket: :package: upload packages ({{matrix}})"
key: upload_packages
depends_on: build
matrix:
- "deb"
- "rpm"
command: '.buildkite/upload-packages.sh "{{matrix}}"'
plugins:
- artifacts#v1.9.4:
download:
- dist/linux/*
- label: ":rocket: :github: release"
key: release
depends_on: ["build", "upload_packages"]
artifact_paths:
- dist/**/*
env:
AWS_REGION: us-east-1
secrets:
- MISE_GITHUB_TOKEN
- POSTHOG_API_KEY
- OAUTH_CLIENT_ID
plugins:
- aws-assume-role-with-web-identity#v1.6.0:
role-arn: arn:aws:iam::445615400570:role/pipeline-buildkite-buildkite-cli-release
session-tags:
- organization_slug
- organization_id
- pipeline_slug
- aws-ssm#v1.1.0:
parameters:
GITHUB_TOKEN: /pipelines/buildkite/buildkite-cli-release/github-token
DOCKERHUB_USER: /pipelines/buildkite/buildkite-cli-release/dockerhub-user
DOCKERHUB_PASSWORD: /pipelines/buildkite/buildkite-cli-release/dockerhub-password
- artifacts#v1.9.4:
download:
- dist/**/*
- mise#v1.1.2: ~
command: '.buildkite/release.sh continue --merge'
================================================
FILE: .buildkite/pipeline.yml
================================================
agents:
queue: hosted
cache: ".buildkite/cache-volume"
steps:
- name: ":golangci-lint: lint"
key: lint
command: 'golangci-lint run --verbose --timeout 3m'
secrets:
- MISE_GITHUB_TOKEN
plugins:
- mise#v1.1.2: ~
- name: ":go: test"
key: test
artifact_paths:
- cover-tree.svg
secrets:
- MISE_GITHUB_TOKEN
commands:
# Hosted agents inject org/token env that breaks config-precedence tests,
# so clear those variables in the command shell right before go test.
- unset BUILDKITE_ORGANIZATION_SLUG BUILDKITE_API_TOKEN
- go test -coverprofile cover.out ./...
- go-cover-treemap -coverprofile cover.out > cover-tree.svg
- echo '<details><summary>Coverage tree map</summary><img src="artifact://cover-tree.svg" alt="Test coverage tree map" width="70%"></details>' | buildkite-agent annotate --style "info"
plugins:
- mise#v1.1.2: ~
- label: ":terminal: build ({{matrix}})"
key: build
depends_on: ["lint", "test"]
branches:
- main
matrix:
- "darwin"
- "linux"
- "windows"
artifact_paths:
- dist/**/*
secrets:
- MISE_GITHUB_TOKEN
- POSTHOG_API_KEY
- OAUTH_CLIENT_ID
command: 'GOOS="{{matrix}}" .buildkite/release.sh release --clean --snapshot --split'
plugins:
- mise#v1.1.2: ~
- input: ":package: Create a release?"
key: release_unblock
depends_on: ["lint", "test", "build"]
prompt: "Select the release type"
branches:
- main
allowed_teams:
- "support"
- "deploy"
blocked_state: "passed"
fields:
- key: release-type
select: "Release Type"
required: true
options:
- label: "Patch (v3.x.X)"
value: "patch"
- label: "Minor (v3.X.0)"
value: "minor"
- label: "Major (vX.0.0) - Manual only"
value: "major"
# this tags the commit with the input from the previous block step and pushes it to github
# that will trigger the buildkite-cli-release pipeline off the tag which will create a release in github
- label: ":rocket: Pushing a tag to release"
command: ".buildkite/tag.sh"
depends_on: release_unblock
branches:
- main
env:
AWS_REGION: us-east-1
plugins:
- aws-assume-role-with-web-identity#v1.6.0:
role-arn: arn:aws:iam::445615400570:role/pipeline-buildkite-buildkite-cli
session-tags:
- organization_slug
- organization_id
- pipeline_slug
- aws-ssm#v1.1.0:
parameters:
GITHUB_TOKEN: /pipelines/buildkite/buildkite-cli/github-token
GITHUB_USER: /pipelines/buildkite/buildkite-cli/github-user
================================================
FILE: .buildkite/release.sh
================================================
#!/usr/bin/env bash
#
# This script is used to build a release of the CLI and publish it to multiple registries on Buildkite
#
# NOTE: do not exit on non-zero returns codes
set -uo pipefail
export GORELEASER_KEY=$(buildkite-agent secret get goreleaser_key)
if [[ $? -ne 0 ]]; then
echo "Failed to retrieve GoReleaser Pro key"
exit 1
fi
# check if DOCKERHUB_USER and DOCKERHUB_PASSWORD are set if not skip docker login
if [[ -z "${DOCKERHUB_USER:-}" || -z "${DOCKERHUB_PASSWORD:-}" ]]; then
echo "Skipping Docker login as DOCKERHUB_USER or DOCKERHUB_PASSWORD is not set"
else
echo "--- :key: :docker: Login to Docker Hub using ko"
echo "${DOCKERHUB_PASSWORD}" | ko login index.docker.io --username "${DOCKERHUB_USER}" --password-stdin
if [[ $? -ne 0 ]]; then
echo "Docker login failed"
exit 1
fi
fi
if ! goreleaser "$@"; then
echo "Failed to build a release"
exit 1
fi
================================================
FILE: .buildkite/tag.sh
================================================
#!/usr/bin/env bash
#
# This script calculates the next semantic version and pushes a tag
#
set -euo pipefail
RELEASE_TYPE="$(buildkite-agent meta-data get "release-type")"
if [[ "${RELEASE_TYPE}" == "major" ]]; then
echo "🚨 Major releases require manual tagging to prevent accidents."
echo "Please run: git tag vX.0.0 && git push origin vX.0.0"
exit 1
fi
# Get latest tag matching v*.*.* pattern
LATEST_TAG=$(git describe --tags --match "v[0-9]*" --abbrev=0 2>/dev/null) || {
echo "Error: No existing version tags found. Cannot calculate next version."
exit 1
}
echo "Latest tag: ${LATEST_TAG}"
# Parse version (strip 'v' prefix and any pre-release suffix)
VERSION="${LATEST_TAG#v}"
IFS='.' read -r MAJOR MINOR PATCH <<< "${VERSION%%-*}"
# Calculate new version
case "${RELEASE_TYPE}" in
minor)
TAG="v${MAJOR}.$((MINOR + 1)).0"
;;
patch)
TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
;;
*)
echo "Error: Unknown release type: ${RELEASE_TYPE}"
exit 1
;;
esac
echo "New tag: ${TAG}"
if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "Error: Tag ${TAG} already exists at origin"
exit 1
fi
echo "${TAG} does not exist at origin. Proceeding... 🚀"
echo "--- Downloading gh"
curl -sL https://github.com/cli/cli/releases/download/v2.57.0/gh_2.57.0_linux_amd64.tar.gz | tar xz
echo "--- Logging in to gh"
gh_2.57.0_linux_amd64/bin/gh auth setup-git
echo "+++ Tagging ${BUILDKITE_COMMIT} with ${TAG}"
git tag "${TAG}"
git push origin "${TAG}"
================================================
FILE: .buildkite/upload-packages.sh
================================================
#!/bin/env bash
#
# This script is used to upload packages to Buildkite registries
#
set -uo pipefail
if [[ -z "${1}" ]]; then
echo "Must pass in the package type: deb, rpm"
exit 1
fi
PACKAGE=${1}
ORGANIZATION=${2:-buildkite}
REGISTRY=${3:-cli-$PACKAGE}
audience() {
ORG=$1
REGISTRY=$2
echo "https://packages.buildkite.com/${ORG}/${REGISTRY}"
}
upload_url() {
ORG=$1
REGISTRY=$2
echo "https://api.buildkite.com/v2/packages/organizations/${ORG}/registries/${REGISTRY}/packages"
}
AUDIENCE=$(audience $ORGANIZATION $REGISTRY)
# grab a token for pushing packages to buildkite with an expiry of 3 mins
echo "--- Fetching OIDC token for $AUDIENCE"
TOKEN=$(buildkite-agent oidc request-token --audience "$AUDIENCE" --lifetime 180)
if [[ $? -ne 0 ]]; then
echo "Failed to retrieve OIDC token"
exit 1
fi
for FILE in dist/linux/*.${PACKAGE}; do
echo "--- Pushing $FILE"
if [[ $PACKAGE = "apk" ]]; then
curl -s -X POST $(upload_url $ORGANIZATION $REGISTRY) \
-H "Authorization: Bearer ${TOKEN}" \
-F "package[distro_version_id]=alpine/v3" \
-F "package[package_file]=@${FILE}" \
--fail-with-body
else
curl -s -X POST $(upload_url $ORGANIZATION $REGISTRY) \
-H "Authorization: Bearer ${TOKEN}" \
-F "file=@${FILE}" \
--fail-with-body
fi
if [[ $? -ne 0 ]]; then
echo "Failed to push package $FILE"
exit 1
fi
done
================================================
FILE: .dockerignore
================================================
# Git files
.git
.github
.gitignore
# Documentation
*.md
docs/
images/
LICENSE.md
CHANGELOG.md
CONTRIBUTING.md
AGENT.md
README.md
# Build artifacts
dist/
build-logs-*
# Test files
*_test.go
fixtures/
internal/*/resolver/*_test.go
# IDE and editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# CI/CD files
.buildkite/
buildkite.yaml
.bk.yaml
# Config files not needed for build
.golangci.yaml
.graphqlrc.yml
genqlient.yaml
# Dependencies (these will be downloaded during build)
vendor/
================================================
FILE: .github/CODEOWNERS
================================================
* @buildkite/support @buildkite/engineering
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
name: 🐛 Bug Report
description: File a bug report for the Buildkite CLI
title: "[Bug]: "
labels: ["bug", "triage"]
projects: ["buildkite/cli"]
assignees:
- buildkite/technical-services
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: input
id: contact
attributes:
label: Contact Details
description: How can we get in touch with you if we need more info?
placeholder: ex. email@example.com
validations:
required: false
- type: textarea
id: what-happened
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
value: "A bug happened!"
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: What version of our software are you running?
validations:
required: true
- type: dropdown
id: browsers
attributes:
label: What environment are you seeing the problem on?
multiple: true
options:
- CI
- Local Development
- type: textarea
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: Buildkite Community Forum
url: https://forum.buildkite.community/
about: Discuss issues and requests in the forum.
- name: Contact Buildkite Support
url: https://buildkite.com/about/contact/
about: Get in contact with Buildkite's support team.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
name: 💡 Feature Request
description: Suggest an idea for this project.
title: "💡 feat: <title>"
labels: [Enhancement]
body:
- type: textarea
attributes:
label: Is your feature request related to a problem?
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...].
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like.
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Describe alternatives you've considered.
description: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
validations:
required: false
================================================
FILE: .github/pull_request_template.md
================================================
### Description
<!--
- What problem are you trying to solve, and how are you solving it?
- What alternatives did you consider?
-->
### Changes
<!--
List of what the PR changes. If the PR changes the CLI arguments, consider adding the output of the various levels of `bk <subcomand> --help`.
Can skip if changes are simple or clear from the commit messages.
-->
### Testing
- [ ] Tests have run locally (with `go test ./...`)
- [ ] Code is formatted (with `go fmt ./...`)
### Disclosures / Credits
<!--
If you used AI in any way to produce this PR (beyond typo fixes or small amounts of tab-autocompletion), please describe the extent of the contribution here, and the tools used.
Feel free to claim credit for work _not_ done by an AI here too, or to give credit to others who helped in any meaningful way.
Examples:
- "Claude Code wrote the unit tests, then I implemented the rest of the change"
- "I consulted ChatGPT on potential approaches, then wrote the implementation myself"
- "I used Gemini to write the code and Midjourney to produce the diagrams"
- "Special thanks to the Wikipedia page on ANSI escape codes"
- "I did not use AI tools at all"
-->
================================================
FILE: .gitignore
================================================
*.DS_STORE
dist/
buildkite.yaml
.bk.yaml
build-logs-*
mise.local.toml
.mise.local.toml
================================================
FILE: .golangci.yaml
================================================
version: "2"
linters:
enable:
- nolintlint
- tparallel
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- linters:
- errcheck
path: _test.go
paths:
- third_party$
- builtin$
- examples$
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
enable:
- gofmt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
================================================
FILE: .goreleaser.yaml
================================================
project_name: bk
version: 2
release:
name_template: Buildkite CLI {{.Version}}
draft: true
replace_existing_draft: true
prerelease: auto
make_latest: false
mode: replace
changelog:
use: github
brews:
- name: bk@3
ids:
- macos-archive
- linux-archive
directory: Formula
homepage: https://github.com/buildkite/cli
description: Work with Buildkite from the command-line
license: MIT
skip_upload: false
test: system "#{bin}/bk version"
repository:
owner: buildkite
name: homebrew-buildkite
branch: master
builds:
- id: macos
goos: [darwin]
goarch: [amd64, arm64]
binary: bk
main: .
ldflags:
- -s -w -X github.com/buildkite/cli/v3/cmd/version.Version={{.Version}} -X github.com/buildkite/cli/v3/pkg/cmd/pipeline.MigrationEndpoint=https://m4vrh5pvtd.execute-api.us-east-1.amazonaws.com/production/migrate -X github.com/buildkite/cli/v3/pkg/analytics.apiKey={{.Env.POSTHOG_API_KEY}} -X github.com/buildkite/cli/v3/pkg/oauth.DefaultClientID={{.Env.OAUTH_CLIENT_ID}}
- id: linux
goos: [linux]
goarch: [amd64, arm64]
env:
- CGO_ENABLED=0
binary: bk
main: .
ldflags:
- -s -w -X github.com/buildkite/cli/v3/cmd/version.Version={{.Version}} -X github.com/buildkite/cli/v3/pkg/cmd/pipeline.MigrationEndpoint=https://m4vrh5pvtd.execute-api.us-east-1.amazonaws.com/production/migrate -X github.com/buildkite/cli/v3/pkg/analytics.apiKey={{.Env.POSTHOG_API_KEY}} -X github.com/buildkite/cli/v3/pkg/oauth.DefaultClientID={{.Env.OAUTH_CLIENT_ID}}
- id: windows
goos: [windows]
goarch: [amd64, arm64]
binary: bk
main: .
ldflags:
- -s -w -X github.com/buildkite/cli/v3/cmd/version.Version={{.Version}} -X github.com/buildkite/cli/v3/pkg/cmd/pipeline.MigrationEndpoint=https://m4vrh5pvtd.execute-api.us-east-1.amazonaws.com/production/migrate -X github.com/buildkite/cli/v3/pkg/analytics.apiKey={{.Env.POSTHOG_API_KEY}} -X github.com/buildkite/cli/v3/pkg/oauth.DefaultClientID={{.Env.OAUTH_CLIENT_ID}}
kos:
- repositories:
- docker.io/buildkite/cli
build: linux
main: .
creation_time: "{{.CommitTimestamp}}"
base_image: 'cgr.dev/chainguard/static:latest'
tags:
- '{{.Version}}'
- latest
labels:
org.opencontainers.image.authors: Buildkite Inc. https://buildkite.com
org.opencontainers.image.source: https://github.com/buildkite/cli
org.opencontainers.image.created: "{{.Date}}"
org.opencontainers.image.title: "{{.ProjectName}}"
org.opencontainers.image.revision: "{{.FullCommit}}"
org.opencontainers.image.version: "{{.Version}}"
bare: true
preserve_import_paths: false
disable: '{{ and (isEnvSet "GOOS") (ne .Env.GOOS "linux") }}'
platforms:
- linux/amd64
- linux/arm64
archives:
- id: macos-archive
builds: [macos]
name_template: "bk_{{ .Version }}_macOS_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
wrap_in_directory: true
format: zip
files:
- LICENSE.md
- README.md
- id: linux-archive
builds: [linux]
name_template: "bk_{{ .Version }}_linux_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
wrap_in_directory: true
format: tar.gz
files:
- LICENSE.md
- README.md
- id: windows-archive
builds: [windows]
name_template: "bk_{{ .Version }}_windows_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
wrap_in_directory: false
format: zip
files:
- LICENSE.md
- README.md
nfpms:
- builds:
- linux
vendor: Buildkite
homepage: https://buildkite.com
maintainer: Buildkite <support@buildkite.com>
description: A command line interface for Buildkite.
license: MIT
formats:
- apk
- deb
- rpm
provides:
- bk
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
================================================
FILE: .graphqlrc.yml
================================================
schema: schema.graphql
================================================
FILE: AGENT.md
================================================
This project is the Buildkite CLI (`bk`)
## Commands
- Bootstrap: `mise install`
- Hooks: `mise run hooks`
- Format: `mise run format`
- Test: `mise run test`
- Lint: `mise run lint`
- Generate: `mise run generate` (required after GraphQL changes)
- Run: `go run main.go`
## Environment
- `BUILDKITE_GRAPHQL_TOKEN` required for development
## Project Structure
- Main binary: `main.go`
- GraphQL schema: `schema.graphql`
- CLI commands: `pkg/cmd/`
## Notes
- `mise.toml` pins the local Go/tool versions
- CI: https://buildkite.com/buildkite/buildkite-cli
- Always format after changing code
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
We welcome contributions from the community to make Buildkite CLI, `bk`, project even better.
## Getting Started
To get started with contributing, please follow these steps:
1. Fork the repository.
2. Create a feature branch with a nice name (`git checkout -b cli-new-feature`) for your changes.
3. Install [mise](https://mise.jdx.dev/) and run `mise install`.
4. Install the local git hooks with `mise run hooks`.
5. Write your code.
6. Run the local checks before opening a pull request.
* Format the code with `mise run format`.
* Lint with `mise run lint`.
* Make sure the tests pass with `mise run test`.
* Run `mise run generate` after GraphQL changes. If you need to refresh `schema.graphql`, set `BUILDKITE_GRAPHQL_TOKEN` first.
7. Commit your changes and push them to your forked repository.
8. Submit a pull request with a detailed description of your changes and links to any relevant issues.
The team maintaining this codebase will review your PR and start a CI build for it. For security reasons, we don't automatically run CI against forked repos, and a human will review your PR prior to its CI running.
## Testing
There is a continuous integration pipeline on Buildkite:
https://buildkite.com/buildkite/buildkite-cli
## Releasing
Builds on `main` include a block step to "Create a release". The step takes a tag name, then takes care of tagging the built commit.
New tags trigger the release pipeline:
https://buildkite.com/buildkite/buildkite-cli-release
This will prepare a new draft release on GitHub:
https://github.com/buildkite/cli/releases
To release, edit the draft and _Publish release_.
## Reporting Issues
If you encounter any issues or have suggestions for improvements, please open an issue on the GitHub repository. Provide as much detail as possible, including steps to reproduce the issue.
## Contact
If we're really dragging our feet on reviewing a PR, please feel free to ping us through GitHub or Slack, or get in touch with [support@buildkite.com](mailto:support@buildkite.com), and they can bug us to get things done :)
Happy contributing!
================================================
FILE: Dockerfile
================================================
FROM golang:1.26-alpine AS base
RUN apk add --no-cache git ca-certificates
WORKDIR /base
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o bk .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /cli
COPY --from=base /base/bk .
ENV PATH="/cli:${PATH}"
ENTRYPOINT ["bk"]
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2014-2023 Buildkite Pty Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# bk - The Buildkite CLI
[](https://github.com/buildkite/cli/releases)
A command line interface for [Buildkite](https://buildkite.com/).
Full documentation is available at [buildkite.com/docs/platform/cli](https://buildkite.com/docs/platform/cli).
## Quick Start
### Install
```sh
brew tap buildkite/buildkite && brew install buildkite/buildkite/bk
```
Or download a binary from the [releases page](https://github.com/buildkite/cli/releases).
### Authenticate
```sh
bk auth login
```
## Feedback
We'd love to hear any feedback and questions you might have. Please [file an issue on GitHub](https://github.com/buildkite/cli/issues) and let us know!
## Development
This repository uses [mise](https://mise.jdx.dev/) to pin Go and the main
local development tools.
```bash
git clone git@github.com:buildkite/cli.git
cd cli/
mise install
mise run build
mise run install
mise run install:global
mise run hooks
mise run format
mise run lint
mise run test
mise run generate
go run main.go --help
```
`mise.toml` pins the shared toolchain, including the release helpers used in
CI. The module itself remains compatible with Go `1.25.0` as declared in
`go.mod`.
================================================
FILE: cmd/agent/agent_test.go
================================================
package agent
import (
"testing"
"github.com/buildkite/cli/v3/internal/config"
"github.com/spf13/afero"
)
func TestParseAgentArg(t *testing.T) {
t.Parallel()
testcases := map[string]struct {
url, org, agent string
}{
"slug": {
url: "buildkite/abcd",
org: "buildkite",
agent: "abcd",
},
"id": {
url: "abcd",
org: "testing",
agent: "abcd",
},
"url": {
url: "https://buildkite.com/organizations/buildkite/agents/018a4a65-bfdb-4841-831a-ff7c1ddbad99",
org: "buildkite",
agent: "018a4a65-bfdb-4841-831a-ff7c1ddbad99",
},
"clustered url": {
url: "https://buildkite.com/organizations/buildkite/clusters/0b7c9944-10ba-434d-9dbb-b332431252de/queues/3d039cf8-9862-4cb0-82cd-fc5c497a265a/agents/018c3d31-1b4a-454a-87f6-190b206e3759",
org: "buildkite",
agent: "018c3d31-1b4a-454a-87f6-190b206e3759",
},
}
for name, testcase := range testcases {
testcase := testcase
t.Run(name, func(t *testing.T) {
t.Parallel()
conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing", true)
org, agent := parseAgentArg(testcase.url, conf)
if org != testcase.org {
t.Error("parsed organization slug did not match expected")
}
if agent != testcase.agent {
t.Error("parsed agent ID did not match expected")
}
})
}
}
================================================
FILE: cmd/agent/install.go
================================================
package agent
import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
bkAgent "github.com/buildkite/cli/v3/internal/agent"
)
var (
userArch = runtime.GOARCH
userOS = runtime.GOOS
)
// InstallCmd allows users to define which agent version they want to install
// We will take care of OS/arch in the command itself
type InstallCmd struct {
Version string `help:"Specify an agent version to install" default:"latest"`
Dest string `help:"Destination directory for the binary" type:"path"`
ClusterUUID string `help:"Cluster UUID to create the agent token on (default: the \"Default\" cluster)" name:"cluster-uuid" optional:""`
NoToken bool `help:"Skip creating an agent token and config file" name:"no-token"`
ConfigPath string `help:"Path to write the agent config file" type:"path"`
}
func (i *InstallCmd) Help() string {
return `Install the buildkite-agent binary locally.
By default, this also creates an agent token on the Default cluster and writes
a minimal config file so the agent is ready to start.
Examples:
# Install the latest version of the agent
$ bk agent install
# Install a specific version
$ bk agent install --version "3.112.0"
# Install to a custom location
$ bk agent install --dest ~/.local/bin
# Install without creating a token/config
$ bk agent install --no-token
`
}
func (i *InstallCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
dest := i.Dest
if dest == "" {
dest = bkAgent.DefaultBinDir(userOS)
}
// Check for existing installations in PATH
if existing := bkAgent.FindExisting(userOS); existing != nil {
destBinary := filepath.Join(dest, bkAgent.BinaryName(userOS))
if existing.Path != destBinary {
fmt.Printf("Warning: existing buildkite-agent found at %s", existing.Path)
if existing.Version != "" {
fmt.Printf(" (%s)", existing.Version)
}
fmt.Println()
fmt.Printf(" The new install at %s may be shadowed in your PATH.\n", destBinary)
fmt.Println()
}
}
if err := os.MkdirAll(dest, 0o755); err != nil {
return fmt.Errorf("creating destination directory: %w", err)
}
version := i.Version
if version == "latest" {
resolved, err := bkAgent.ResolveLatestVersion()
if err != nil {
return fmt.Errorf("resolving latest version: %w", err)
}
version = resolved
}
version = strings.TrimPrefix(version, "v")
downloadURL := bkAgent.BuildDownloadURL(version, userOS, userArch)
fmt.Printf("Downloading buildkite-agent v%s for %s/%s...\n", version, userOS, userArch)
tmpFile, err := bkAgent.DownloadToTemp(downloadURL)
if err != nil {
return fmt.Errorf("downloading agent: %w", err)
}
defer os.Remove(tmpFile)
// Verify the download checksum
fmt.Println("Verifying checksum...")
sumsURL := bkAgent.BuildSHA256SumsURL(version)
archiveFilename := filepath.Base(downloadURL)
expectedHash, err := bkAgent.FetchExpectedSHA256(sumsURL, archiveFilename)
if err != nil {
return fmt.Errorf("fetching checksum: %w", err)
}
if err := bkAgent.VerifySHA256(tmpFile, expectedHash); err != nil {
return fmt.Errorf("checksum verification failed: %w", err)
}
if err := bkAgent.ExtractBinary(tmpFile, dest, userOS); err != nil {
return fmt.Errorf("extracting agent: %w", err)
}
binaryName := bkAgent.BinaryName(userOS)
fmt.Printf("Installed buildkite-agent to %s\n", filepath.Join(dest, binaryName))
if !i.NoToken {
if err := i.createTokenAndConfig(globals); err != nil {
return err
}
}
return nil
}
func (i *InstallCmd) createTokenAndConfig(globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return fmt.Errorf("initializing API client: %w", err)
}
ctx := context.Background()
org := f.Config.OrganizationSlug()
clusterID, err := bkAgent.FindCluster(ctx, f, org, i.ClusterUUID)
if err != nil {
return fmt.Errorf("finding default cluster: %w", err)
}
fmt.Println("Creating agent token...")
token, err := bkAgent.CreateAgentToken(ctx, f, org, clusterID, "Token created by bk agent install")
if err != nil {
return fmt.Errorf("creating agent token: %w", err)
}
configPath := i.ConfigPath
if configPath == "" {
configPath = bkAgent.DefaultConfigPath(userOS)
}
buildPath := bkAgent.DefaultBuildPath(userOS)
if err := bkAgent.WriteAgentConfig(configPath, token, buildPath, nil); err != nil {
return fmt.Errorf("writing agent config: %w", err)
}
fmt.Printf("Agent config written to %s\n", configPath)
return nil
}
================================================
FILE: cmd/agent/list.go
================================================
package agent
import (
"context"
"fmt"
"os"
"slices"
"strings"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
const (
stateRunning = "running"
stateIdle = "idle"
statePaused = "paused"
)
var validStates = []string{stateRunning, stateIdle, statePaused}
type ListCmd struct {
Name string `help:"Filter agents by their name"`
Version string `help:"Filter agents by their version"`
Hostname string `help:"Filter agents by their hostname"`
State string `help:"Filter agents by state (running, idle, paused)"`
Tags []string `help:"Filter agents by tags"`
PerPage int `help:"Number of agents per page" default:"30"`
Limit int `help:"Maximum number of agents to return" default:"100"`
output.OutputFlags
}
func (c *ListCmd) Help() string {
return `By default, shows up to 100 agents. Use filters to narrow results, or increase the number of agents displayed with --limit.
Examples:
# List all agents
$ bk agent list
# List agents with JSON output
$ bk agent list --output json
# List only running agents (currently executing jobs)
$ bk agent list --state running
# List only idle agents (connected but not running jobs)
$ bk agent list --state idle
# List only paused agents
$ bk agent list --state paused
# Filter agents by hostname
$ bk agent list --hostname my-server-01
# Combine state and hostname filters
$ bk agent list --state idle --hostname my-server-01
# Filter agents by tags
$ bk agent list --tags queue=default
# Filter agents by multiple tags (all must match)
$ bk agent list --tags queue=default --tags os=linux
# Multiple filters with output format
$ bk agent list --state running --version 3.107.2 --output json`
}
func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
if err := validateState(c.State); err != nil {
return err
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
agents := []buildkite.Agent{}
page := 1
hasMore := false
var previousFirstAgentID string
for len(agents) < c.Limit {
opts := buildkite.AgentListOptions{
Name: c.Name,
Hostname: c.Hostname,
Version: c.Version,
ListOptions: buildkite.ListOptions{
Page: page,
PerPage: c.PerPage,
},
}
pageAgents, _, err := f.RestAPIClient.Agents.List(ctx, f.Config.OrganizationSlug(), &opts)
if err != nil {
return err
}
if len(pageAgents) == 0 {
break
}
if page > 1 && len(pageAgents) > 0 && pageAgents[0].ID == previousFirstAgentID {
return fmt.Errorf("API returned duplicate page content at page %d, stopping pagination to prevent infinite loop", page)
}
if len(pageAgents) > 0 {
previousFirstAgentID = pageAgents[0].ID
}
filtered := filterAgents(pageAgents, c.State, c.Tags)
agents = append(agents, filtered...)
// If this was a full page, there might be more results
// We'll check after breaking from the loop if we hit the limit with a full page
if len(pageAgents) < c.PerPage {
break
}
// Check if we've hit the limit before fetching more
if len(agents) >= c.Limit {
// We hit the limit with a full page, so there are likely more results
hasMore = true
break
}
page++
}
totalFetched := len(agents)
if len(agents) > c.Limit {
agents = agents[:c.Limit]
}
if format != output.FormatText {
return output.Write(os.Stdout, agents, format)
}
if len(agents) == 0 {
fmt.Println("No agents found")
return nil
}
headers := []string{"State", "Name", "Version", "Queue", "Hostname"}
rows := make([][]string, len(agents))
for i, agent := range agents {
queue := extractQueue(agent.Metadata)
state := displayState(agent)
rows[i] = []string{
state,
agent.Name,
agent.Version,
queue,
agent.Hostname,
}
}
columnStyles := map[string]string{
"state": "bold",
"name": "bold",
"hostname": "dim",
"version": "italic",
"queue": "italic",
}
table := output.Table(headers, rows, columnStyles)
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() {
_ = cleanup()
}()
totalDisplay := fmt.Sprintf("%d", totalFetched)
if hasMore {
totalDisplay = fmt.Sprintf("%d+", totalFetched)
}
fmt.Fprintf(writer, "Showing %d of %s agents in %s\n\n", len(agents), totalDisplay, f.Config.OrganizationSlug())
fmt.Fprint(writer, table)
return nil
}
func validateState(state string) error {
if state == "" {
return nil
}
normalized := strings.ToLower(state)
if slices.Contains(validStates, normalized) {
return nil
}
return fmt.Errorf("invalid state %q: must be one of %s, %s, or %s", state, stateRunning, stateIdle, statePaused)
}
func filterAgents(agents []buildkite.Agent, state string, tags []string) []buildkite.Agent {
filtered := make([]buildkite.Agent, 0, len(agents))
for _, a := range agents {
if matchesState(a, state) && matchesTags(a, tags) {
filtered = append(filtered, a)
}
}
return filtered
}
func matchesState(a buildkite.Agent, state string) bool {
if state == "" {
return true
}
normalized := strings.ToLower(state)
switch normalized {
case stateRunning:
return a.Job != nil
case stateIdle:
return a.Job == nil && (a.Paused == nil || !*a.Paused)
case statePaused:
return a.Paused != nil && *a.Paused
default:
return false
}
}
func matchesTags(a buildkite.Agent, tags []string) bool {
if len(tags) == 0 {
return true
}
for _, tag := range tags {
if !hasTag(a.Metadata, tag) {
return false
}
}
return true
}
func hasTag(metadata []string, tag string) bool {
return slices.Contains(metadata, tag)
}
func extractQueue(metadata []string) string {
for _, m := range metadata {
if after, ok := strings.CutPrefix(m, "queue="); ok {
return after
}
}
return "default"
}
func displayState(a buildkite.Agent) string {
if a.Job != nil {
return stateRunning
}
if a.Paused != nil && *a.Paused {
return statePaused
}
return stateIdle
}
================================================
FILE: cmd/agent/list_test.go
================================================
package agent
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
func testFilterAgents(agents []buildkite.Agent, state string, tags []string) []buildkite.Agent {
return filterAgents(agents, state, tags)
}
func TestCmdAgentList(t *testing.T) {
t.Parallel()
t.Run("fetches agents through API", func(t *testing.T) {
t.Parallel()
paused := false
agents := []buildkite.Agent{
{
ID: "123",
Name: "my-agent",
ConnectedState: "connected",
Version: "3.50.0",
Hostname: "host1",
Metadata: []string{"queue=default"},
Paused: &paused,
},
{
ID: "456",
Name: "another-agent",
ConnectedState: "idle",
Version: "3.51.0",
Hostname: "host2",
Metadata: []string{"queue=deploy", "os=linux"},
Paused: &paused,
},
}
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
page := r.URL.Query().Get("page")
if page == "" || page == "1" {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(agents)
} else {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode([]buildkite.Agent{})
}
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
ctx := context.Background()
fetchedAgents, _, err := client.Agents.List(ctx, "test-org", &buildkite.AgentListOptions{
ListOptions: buildkite.ListOptions{Page: 1, PerPage: 30},
})
if err != nil {
t.Fatal(err)
}
if len(fetchedAgents) != 2 {
t.Fatalf("expected 2 agents, got %d", len(fetchedAgents))
}
if fetchedAgents[0].Name != "my-agent" {
t.Errorf("expected first agent name 'my-agent', got %q", fetchedAgents[0].Name)
}
if fetchedAgents[1].Hostname != "host2" {
t.Errorf("expected second agent hostname 'host2', got %q", fetchedAgents[1].Hostname)
}
queue := extractQueue(fetchedAgents[0].Metadata)
if queue != "default" {
t.Errorf("expected queue 'default', got %q", queue)
}
deployQueue := extractQueue(fetchedAgents[1].Metadata)
if deployQueue != "deploy" {
t.Errorf("expected queue 'deploy', got %q", deployQueue)
}
})
t.Run("renders table output", func(t *testing.T) {
t.Parallel()
paused := false
agents := []buildkite.Agent{
{
ID: "agent-1",
Name: "test-agent",
ConnectedState: "connected",
Job: &buildkite.Job{ID: "job-1"},
Version: "3.50.0",
Hostname: "test-host",
Metadata: []string{"queue=default"},
Paused: &paused,
},
}
headers := []string{"State", "Name", "Version", "Queue", "Hostname"}
rows := make([][]string, len(agents))
for i, agent := range agents {
queue := extractQueue(agent.Metadata)
state := displayState(agent)
rows[i] = []string{
state,
agent.Name,
agent.Version,
queue,
agent.Hostname,
}
}
columnStyles := map[string]string{
"state": "bold",
"name": "bold",
"hostname": "dim",
"version": "italic",
"queue": "italic",
}
table := output.Table(headers, rows, columnStyles)
if !strings.Contains(table, "STATE") {
t.Error("expected table to contain header 'STATE'")
}
if !strings.Contains(table, "test-agent") {
t.Error("expected table to contain agent name")
}
if !strings.Contains(table, "running") {
t.Error("expected table to contain semantic state 'running'")
}
if !strings.Contains(table, "3.50.0") {
t.Error("expected table to contain version")
}
if !strings.Contains(table, "default") {
t.Error("expected table to contain queue")
}
if !strings.Contains(table, "test-host") {
t.Error("expected table to contain hostname")
}
})
t.Run("empty result returns empty array", func(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode([]buildkite.Agent{})
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
ctx := context.Background()
agents, _, err := client.Agents.List(ctx, "test-org", &buildkite.AgentListOptions{
ListOptions: buildkite.ListOptions{Page: 1, PerPage: 30},
})
if err != nil {
t.Fatal(err)
}
if len(agents) != 0 {
t.Errorf("expected 0 agents, got %d", len(agents))
}
})
}
func TestAgentListStateFilter(t *testing.T) {
t.Parallel()
paused := true
notPaused := false
agents := []buildkite.Agent{
{ID: "1", Name: "running-agent", Job: &buildkite.Job{ID: "job-1"}},
{ID: "2", Name: "idle-agent"},
{ID: "3", Name: "paused-agent", Paused: &paused},
{ID: "4", Name: "idle-not-paused", Paused: ¬Paused},
}
tests := []struct {
state string
want []string // agent IDs
}{
{"running", []string{"1"}},
{"RUNNING", []string{"1"}},
{"idle", []string{"2", "4"}},
{"paused", []string{"3"}},
{"", []string{"1", "2", "3", "4"}},
}
for _, tt := range tests {
t.Run(tt.state, func(t *testing.T) {
t.Parallel()
result := testFilterAgents(agents, tt.state, nil)
if len(result) != len(tt.want) {
t.Errorf("got %d agents, want %d", len(result), len(tt.want))
}
for i, id := range tt.want {
if i >= len(result) || result[i].ID != id {
t.Errorf("agent %d: got ID %q, want %q", i, result[i].ID, id)
}
}
})
}
}
func TestAgentListInvalidState(t *testing.T) {
t.Parallel()
err := validateState("invalid")
if err == nil {
t.Fatal("expected error for invalid state, got nil")
}
if !strings.Contains(err.Error(), "invalid state") {
t.Errorf("expected error to mention 'invalid state', got: %v", err)
}
}
func TestDisplayState(t *testing.T) {
t.Parallel()
paused := true
notPaused := false
tests := []struct {
name string
agent buildkite.Agent
want string
}{
{
name: "running when job present",
agent: buildkite.Agent{Job: &buildkite.Job{ID: "job-1"}},
want: stateRunning,
},
{
name: "paused when paused flag",
agent: buildkite.Agent{Paused: &paused},
want: statePaused,
},
{
name: "idle default",
agent: buildkite.Agent{Paused: ¬Paused},
want: stateIdle,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := displayState(tt.agent)
if got != tt.want {
t.Fatalf("displayState() = %q, want %q", got, tt.want)
}
})
}
}
func TestAgentListTagsFilter(t *testing.T) {
t.Parallel()
agents := []buildkite.Agent{
{ID: "1", Name: "default-linux", Metadata: []string{"queue=default", "os=linux"}},
{ID: "2", Name: "deploy-macos", Metadata: []string{"queue=deploy", "os=macos"}},
{ID: "3", Name: "default-macos", Metadata: []string{"queue=default", "os=macos"}},
{ID: "4", Name: "no-metadata"},
}
tests := []struct {
name string
tags []string
want []string
}{
{"single tag", []string{"queue=default"}, []string{"1", "3"}},
{"multiple tags AND", []string{"queue=default", "os=linux"}, []string{"1"}},
{"no match", []string{"queue=nonexistent"}, []string{}},
{"no tags filter", []string{}, []string{"1", "2", "3", "4"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
result := testFilterAgents(agents, "", tt.tags)
if len(result) != len(tt.want) {
t.Errorf("got %d agents, want %d", len(result), len(tt.want))
}
for i, id := range tt.want {
if i >= len(result) || result[i].ID != id {
t.Errorf("agent %d: got ID %q, want %q", i, result[i].ID, id)
}
}
})
}
}
func TestAgentListPagination(t *testing.T) {
t.Parallel()
t.Run("stops on partial page", func(t *testing.T) {
t.Parallel()
// Mock server that returns 30 agents on page 1, 15 on page 2
callCount := 0
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
callCount++
page := r.URL.Query().Get("page")
w.Header().Set("Content-Type", "application/json")
switch page {
case "", "1":
agents := make([]buildkite.Agent, 30)
for i := range agents {
agents[i] = buildkite.Agent{ID: fmt.Sprintf("page1-agent-%d", i), Name: "agent"}
}
json.NewEncoder(w).Encode(agents)
case "2":
agents := make([]buildkite.Agent, 15)
for i := range agents {
agents[i] = buildkite.Agent{ID: fmt.Sprintf("page2-agent-%d", i), Name: "agent"}
}
json.NewEncoder(w).Encode(agents)
default:
json.NewEncoder(w).Encode([]buildkite.Agent{})
}
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
// Simulate pagination loop
var agents []buildkite.Agent
page := 1
limit := 100
perPage := 30
var previousFirstAgentID string
for len(agents) < limit {
opts := &buildkite.AgentListOptions{
ListOptions: buildkite.ListOptions{
Page: page,
PerPage: perPage,
},
}
pageAgents, _, err := client.Agents.List(context.Background(), "test-org", opts)
if err != nil {
t.Fatal(err)
}
if len(pageAgents) == 0 {
break
}
if page > 1 && len(pageAgents) > 0 && pageAgents[0].ID == previousFirstAgentID {
t.Fatal("detected duplicate page")
}
if len(pageAgents) > 0 {
previousFirstAgentID = pageAgents[0].ID
}
agents = append(agents, pageAgents...)
// Natural pagination end
if len(pageAgents) < perPage {
break
}
page++
}
// Should have fetched 45 agents total (30 + 15)
if len(agents) != 45 {
t.Errorf("expected 45 agents, got %d", len(agents))
}
// Should have made exactly 2 API calls (page 1 and page 2)
if callCount != 2 {
t.Errorf("expected 2 API calls, got %d", callCount)
}
})
t.Run("detects duplicate pages", func(t *testing.T) {
t.Parallel()
// Mock server that returns same page twice
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Always return same agents regardless of page
agents := []buildkite.Agent{
{ID: "agent-1", Name: "test"},
{ID: "agent-2", Name: "test"},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(agents)
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
// Simulate pagination loop
var agents []buildkite.Agent
page := 1
limit := 100
perPage := 30
var previousFirstAgentID string
duplicateDetected := false
for len(agents) < limit && page < 5 {
opts := &buildkite.AgentListOptions{
ListOptions: buildkite.ListOptions{
Page: page,
PerPage: perPage,
},
}
pageAgents, _, err := client.Agents.List(context.Background(), "test-org", opts)
if err != nil {
t.Fatal(err)
}
if len(pageAgents) == 0 {
break
}
// Detect duplicate
if page > 1 && len(pageAgents) > 0 && pageAgents[0].ID == previousFirstAgentID {
duplicateDetected = true
break
}
if len(pageAgents) > 0 {
previousFirstAgentID = pageAgents[0].ID
}
agents = append(agents, pageAgents...)
page++
}
if !duplicateDetected {
t.Error("expected duplicate page detection to trigger")
}
})
t.Run("continues on full pages with different content", func(t *testing.T) {
t.Parallel()
// Mock server that returns different full pages
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
page := r.URL.Query().Get("page")
w.Header().Set("Content-Type", "application/json")
agents := make([]buildkite.Agent, 30)
prefix := "a"
switch page {
case "2":
prefix = "b"
case "3":
prefix = "c"
}
for i := range agents {
agents[i] = buildkite.Agent{
ID: fmt.Sprintf("%s-agent-%d", prefix, i),
Name: "agent",
}
}
if page == "3" {
// Make page 3 partial to end pagination
agents = agents[:10]
}
json.NewEncoder(w).Encode(agents)
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
// Simulate pagination loop
var agents []buildkite.Agent
page := 1
limit := 100
perPage := 30
var previousFirstAgentID string
for len(agents) < limit {
opts := &buildkite.AgentListOptions{
ListOptions: buildkite.ListOptions{
Page: page,
PerPage: perPage,
},
}
pageAgents, _, err := client.Agents.List(context.Background(), "test-org", opts)
if err != nil {
t.Fatal(err)
}
if len(pageAgents) == 0 {
break
}
if page > 1 && len(pageAgents) > 0 && pageAgents[0].ID == previousFirstAgentID {
t.Fatal("unexpected duplicate page")
}
if len(pageAgents) > 0 {
previousFirstAgentID = pageAgents[0].ID
}
agents = append(agents, pageAgents...)
if len(pageAgents) < perPage {
break
}
page++
}
// Should have fetched 70 agents (30 + 30 + 10)
if len(agents) != 70 {
t.Errorf("expected 70 agents, got %d", len(agents))
}
})
}
================================================
FILE: cmd/agent/pause.go
================================================
package agent
import (
"context"
"fmt"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type PauseCmd struct {
AgentID string `arg:"" help:"Agent ID to pause"`
Note string `help:"A descriptive note to record why the agent is paused"`
TimeoutInMinutes int `help:"Timeout after which the agent is automatically resumed, in minutes" default:"5"`
}
func (c *PauseCmd) Help() string {
return `When an agent is paused, it will stop accepting new jobs but will continue
running any jobs it has already started. You can optionally provide a note
explaining why the agent is being paused and set a timeout for automatic resumption.
The timeout must be between 1 and 1440 minutes (24 hours). If no timeout is
specified, the agent will pause for 5 minutes by default.
Examples:
# Pause an agent for 5 minutes (default)
$ bk agent pause 0198d108-a532-4a62-9bd7-b2e744bf5c45
# Pause an agent with a note
$ bk agent pause 0198d108-a532-4a62-9bd7-b2e744bf5c45 --note "Maintenance scheduled"
# Pause an agent with a note and 60 minute timeout
$ bk agent pause 0198d108-a532-4a62-9bd7-b2e744bf5c45 --note "too many llamas" --timeout-in-minutes 60
# Pause for a short time (15 minutes) during deployment
$ bk agent pause 0198d108-a532-4a62-9bd7-b2e744bf5c45 --note "Deploy in progress" --timeout-in-minutes 15`
}
func (c *PauseCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
if c.TimeoutInMinutes <= 0 {
return fmt.Errorf("timeout-in-minutes must be 1 or more")
}
if c.TimeoutInMinutes > 1440 {
return fmt.Errorf("timeout-in-minutes cannot exceed 1440 minutes (1 day)")
}
var pauseOpts *buildkite.AgentPauseOptions
if c.Note != "" || c.TimeoutInMinutes > 0 {
pauseOpts = &buildkite.AgentPauseOptions{
Note: c.Note,
TimeoutInMinutes: c.TimeoutInMinutes,
}
}
_, err = f.RestAPIClient.Agents.Pause(ctx, f.Config.OrganizationSlug(), c.AgentID, pauseOpts)
if err != nil {
return fmt.Errorf("failed to pause agent: %w", err)
}
message := fmt.Sprintf("Agent %s paused successfully", c.AgentID)
if c.Note != "" {
message += fmt.Sprintf(" with note: %s", c.Note)
}
if c.TimeoutInMinutes > 0 {
message += fmt.Sprintf(" (auto-resume in %d minutes)", c.TimeoutInMinutes)
}
fmt.Printf("%s\n", message)
return nil
}
================================================
FILE: cmd/agent/pause_test.go
================================================
package agent
import (
"testing"
)
func TestPauseCmdValidation(t *testing.T) {
t.Parallel()
tests := []struct {
name string
timeout int
wantErr bool
errMsg string
}{
{"valid timeout", 60, false, ""},
{"minimum valid timeout", 1, false, ""},
{"maximum valid timeout", 1440, false, ""},
{"zero timeout invalid", 0, true, "timeout-in-minutes must be 1 or more"},
{"negative timeout invalid", -1, true, "timeout-in-minutes must be 1 or more"},
{"excessive timeout invalid", 1441, true, "timeout-in-minutes cannot exceed 1440 minutes (1 day)"},
{"very large timeout invalid", 10000, true, "timeout-in-minutes cannot exceed 1440 minutes (1 day)"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
cmd := &PauseCmd{
TimeoutInMinutes: tt.timeout,
}
var err error
if cmd.TimeoutInMinutes <= 0 {
err = errValidation("timeout-in-minutes must be 1 or more")
} else if cmd.TimeoutInMinutes > 1440 {
err = errValidation("timeout-in-minutes cannot exceed 1440 minutes (1 day)")
}
if tt.wantErr {
if err == nil {
t.Errorf("expected error but got none")
} else if err.Error() != tt.errMsg {
t.Errorf("expected error %q, got %q", tt.errMsg, err.Error())
}
} else {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
}
})
}
}
type validationError string
func (e validationError) Error() string { return string(e) }
func errValidation(msg string) error { return validationError(msg) }
================================================
FILE: cmd/agent/resume.go
================================================
package agent
import (
"context"
"fmt"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
)
type ResumeCmd struct {
AgentID string `arg:"" help:"Agent ID to resume"`
}
func (c *ResumeCmd) Help() string {
return `Resume a paused Buildkite agent.
When an agent is resumed, it will start accepting new jobs again.
Examples:
# Resume an agent
$ bk agent resume 0198d108-a532-4a62-9bd7-b2e744bf5c45`
}
func (c *ResumeCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
_, err = f.RestAPIClient.Agents.Resume(ctx, f.Config.OrganizationSlug(), c.AgentID)
if err != nil {
return fmt.Errorf("failed to resume agent: %w", err)
}
fmt.Printf("Agent %s resumed successfully\n", c.AgentID)
return nil
}
================================================
FILE: cmd/agent/resume_test.go
================================================
package agent
import (
"testing"
)
func TestResumeCmdStructure(t *testing.T) {
t.Parallel()
cmd := &ResumeCmd{
AgentID: "test-agent-123",
}
if cmd.AgentID != "test-agent-123" {
t.Errorf("expected AgentID to be %q, got %q", "test-agent-123", cmd.AgentID)
}
}
func TestResumeCmdHelp(t *testing.T) {
t.Parallel()
cmd := &ResumeCmd{}
help := cmd.Help()
if help == "" {
t.Error("Help() should return non-empty string")
}
if len(help) < 10 {
t.Errorf("Help text seems too short: %q", help)
}
}
================================================
FILE: cmd/agent/run.go
================================================
package agent
import (
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"path/filepath"
"runtime"
"strings"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
bkAgent "github.com/buildkite/cli/v3/internal/agent"
)
// RunCmd spins up an ephemeral buildkite-agent attached to a cluster.
type RunCmd struct {
Version string `help:"Specify an agent version to run" default:"latest"`
ClusterUUID string `help:"Cluster UUID to create the agent token on (default: the \"Default\" cluster)" name:"cluster-uuid" optional:""`
Queue string `help:"Queue for the agent to listen on" default:"default"`
}
func (r *RunCmd) Help() string {
return `Run an ephemeral buildkite-agent locally.
Downloads the agent binary, creates a cluster token, and starts the agent.
All temporary files are cleaned up when the agent is stopped with Ctrl+C.
Examples:
# Run the latest agent on the Default cluster
$ bk agent run
# Run a specific version
$ bk agent run --version "3.112.0"
# Run on a specific cluster
$ bk agent run --cluster-uuid "01234567-89ab-cdef-0123-456789abcdef"
# Run on a specific queue
$ bk agent run --queue "deploy"
`
}
func (r *RunCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
// Track temp directory for cleanup
tmpDir, err := os.MkdirTemp("", "bk-agent-run-*")
if err != nil {
return fmt.Errorf("creating temp directory: %w", err)
}
defer func() {
fmt.Println("Cleaning up temporary files...")
os.RemoveAll(tmpDir)
}()
targetOS := runtime.GOOS
targetArch := runtime.GOARCH
version := r.Version
if version == "latest" {
resolved, err := bkAgent.ResolveLatestVersion()
if err != nil {
return fmt.Errorf("resolving latest version: %w", err)
}
version = resolved
}
version = strings.TrimPrefix(version, "v")
downloadURL := bkAgent.BuildDownloadURL(version, targetOS, targetArch)
fmt.Printf("Downloading buildkite-agent v%s for %s/%s...\n", version, targetOS, targetArch)
tmpFile, err := bkAgent.DownloadToTemp(downloadURL)
if err != nil {
return fmt.Errorf("downloading agent: %w", err)
}
defer os.Remove(tmpFile)
fmt.Println("Verifying checksum...")
sumsURL := bkAgent.BuildSHA256SumsURL(version)
archiveFilename := filepath.Base(downloadURL)
expectedHash, err := bkAgent.FetchExpectedSHA256(sumsURL, archiveFilename)
if err != nil {
return fmt.Errorf("fetching checksum: %w", err)
}
if err := bkAgent.VerifySHA256(tmpFile, expectedHash); err != nil {
return fmt.Errorf("checksum verification failed: %w", err)
}
if err := bkAgent.ExtractBinary(tmpFile, tmpDir, targetOS); err != nil {
return fmt.Errorf("extracting agent: %w", err)
}
binaryPath := filepath.Join(tmpDir, bkAgent.BinaryName(targetOS))
// Create API client and provision a cluster token
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return fmt.Errorf("initializing API client: %w", err)
}
ctx := context.Background()
org := f.Config.OrganizationSlug()
clusterID, err := bkAgent.FindCluster(ctx, f, org, r.ClusterUUID)
if err != nil {
return fmt.Errorf("finding cluster: %w", err)
}
fmt.Println("Creating agent token...")
token, err := bkAgent.CreateAgentToken(ctx, f, org, clusterID, "Ephemeral token created by bk agent run")
if err != nil {
return fmt.Errorf("creating agent token: %w", err)
}
// Write a temporary config file
configPath := filepath.Join(tmpDir, "buildkite-agent.cfg")
buildPath := filepath.Join(tmpDir, "builds")
var tags []string
if r.Queue != "" {
tags = append(tags, "queue="+r.Queue)
}
if err := bkAgent.WriteAgentConfig(configPath, token, buildPath, tags); err != nil {
return fmt.Errorf("writing agent config: %w", err)
}
// Catch signals so we wait for the agent to shut down gracefully
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
fmt.Printf("Starting buildkite-agent v%s...\n", version)
cmd := exec.Command(binaryPath, "start", "--config", configPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
if err := cmd.Start(); err != nil {
return fmt.Errorf("starting agent: %w", err)
}
// Wait for the agent to exit in the background
errCh := make(chan error, 1)
go func() {
errCh <- cmd.Wait()
}()
select {
case <-sigCh:
fmt.Println("\nShutting down agent...")
// The agent already received the signal (same process group)
// and will finish any running job before exiting.
<-errCh
fmt.Println("Agent stopped.")
return nil
case err := <-errCh:
if err != nil {
return fmt.Errorf("agent exited with error: %w", err)
}
return nil
}
}
================================================
FILE: cmd/agent/stop.go
================================================
package agent
import (
"bufio"
"context"
"errors"
"fmt"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/mattn/go-isatty"
)
type StopCmd struct {
Agents []string `arg:"" optional:"" help:"Agent IDs to stop"`
Force bool `help:"Force stop the agent. Terminating any jobs in progress"`
Limit int64 `help:"Limit parallel API requests" short:"l" default:"5"`
}
func (c *StopCmd) Help() string {
return `Instruct one or more agents to stop accepting new build jobs and shut itself down.
Agents can be supplied as positional arguments or from STDIN, one per line.
If the "ORGANIZATION_SLUG/" portion of the "ORGANIZATION_SLUG/UUID" agent argument
is omitted, it uses the currently selected organization.
The --force flag applies to all agents that are stopped.
Examples:
# Stop a single agent
$ bk agent stop 0198d108-a532-4a62-9bd7-b2e744bf5c45
# Stop multiple agents
$ bk agent stop agent-1 agent-2 agent-3
# Force stop an agent
$ bk agent stop 0198d108-a532-4a62-9bd7-b2e744bf5c45 --force
# Stop agents from STDIN
$ cat agent-ids.txt | bk agent stop`
}
func (c *StopCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
defer signal.Stop(sigCh)
go func() {
select {
case <-sigCh:
cancel()
case <-ctx.Done():
return
}
}()
limit := max(c.Limit, 1)
var agentIDs []string
// this command accepts either input from stdin or positional arguments (not both) in that order
// so we need to check if stdin has data for us to read and read that, otherwise use positional args and if
// there are none, then we need to error
// if stdin has data available, use that
if bkIO.HasDataAvailable(os.Stdin) {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
id := scanner.Text()
if strings.TrimSpace(id) != "" {
agentIDs = append(agentIDs, id)
}
}
if scanner.Err() != nil {
return scanner.Err()
}
} else if len(c.Agents) > 0 {
for _, id := range c.Agents {
if strings.TrimSpace(id) != "" {
agentIDs = append(agentIDs, id)
}
}
} else {
return errors.New("must supply agents to stop")
}
if len(agentIDs) == 0 {
return errors.New("must supply agents to stop")
}
writer := os.Stdout
isTTY := isatty.IsTerminal(writer.Fd())
total := len(agentIDs)
label := "Stopping agents"
if total == 1 {
label = "Stopping agent"
}
workerCount := int(min(limit, int64(total)))
work := make(chan string, workerCount)
updates := make(chan stopResult, workerCount)
var wg sync.WaitGroup
for i := 0; i < workerCount; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for agentID := range work {
if ctx.Err() != nil {
updates <- stopResult{id: agentID, err: ctx.Err()}
continue
}
updates <- stopAgent(ctx, agentID, f, c.Force)
}
}()
}
go func() {
for _, id := range agentIDs {
select {
case <-ctx.Done():
close(work)
return
case work <- id:
}
}
close(work)
}()
go func() {
wg.Wait()
close(updates)
}()
succeeded := 0
failed := 0
completed := 0
var errorDetails []string
if !f.Quiet {
line := bkIO.ProgressLine(label, completed, total, succeeded, failed, 24)
if isTTY {
fmt.Fprint(writer, line)
} else {
fmt.Fprintln(writer, line)
}
}
for update := range updates {
completed++
if update.err != nil {
failed++
errorDetails = append(errorDetails, fmt.Sprintf("FAILED %s: %v", update.id, update.err))
} else {
succeeded++
}
if !f.Quiet {
line := bkIO.ProgressLine(label, completed, total, succeeded, failed, 24)
if isTTY {
fmt.Fprintf(writer, "\r%s", line)
} else {
fmt.Fprintln(writer, line)
}
}
}
if !f.Quiet && isTTY {
fmt.Fprintln(writer)
}
summaryWriter := writer
if failed > 0 {
summaryWriter = os.Stderr
}
if len(errorDetails) > 0 {
fmt.Fprintln(summaryWriter)
for _, detail := range errorDetails {
fmt.Fprintln(summaryWriter, detail)
}
}
if !f.Quiet {
agentLabel := pluralize("agent", total)
failedLabel := pluralize("agent", failed)
if failed > 0 {
fmt.Fprintf(summaryWriter, "\nStopped %d of %d %s (%d %s failed)\n", succeeded, total, agentLabel, failed, failedLabel)
} else {
fmt.Fprintf(summaryWriter, "\nSuccessfully stopped %d of %d %s\n", succeeded, total, agentLabel)
}
}
if failed > 0 {
return fmt.Errorf("failed to stop %d of %d %s (see above for details)", failed, total, pluralize("agent", total))
}
return nil
}
type stopResult struct {
id string
err error
}
func pluralize(word string, count int) string {
if count == 1 {
return word
}
return word + "s"
}
func stopAgent(ctx context.Context, id string, f *factory.Factory, force bool) stopResult {
org, agentID := parseAgentArg(id, f.Config)
_, err := f.RestAPIClient.Agents.Stop(ctx, org, agentID, force)
return stopResult{id: id, err: err}
}
================================================
FILE: cmd/agent/stop_test.go
================================================
package agent
import (
"fmt"
"strings"
"testing"
"github.com/buildkite/cli/v3/internal/config"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/spf13/afero"
)
func TestStopCmdStructure(t *testing.T) {
t.Parallel()
cmd := &StopCmd{
Agents: []string{"agent-1", "agent-2"},
Limit: 5,
Force: true,
}
if len(cmd.Agents) != 2 {
t.Errorf("expected 2 agents, got %d", len(cmd.Agents))
}
if cmd.Limit != 5 {
t.Errorf("expected Limit to be 5, got %d", cmd.Limit)
}
if !cmd.Force {
t.Error("expected Force to be true")
}
}
func TestStopCmdHelp(t *testing.T) {
t.Parallel()
cmd := &StopCmd{}
help := cmd.Help()
if help == "" {
t.Error("Help() should return non-empty string")
}
if !strings.Contains(strings.ToLower(help), "agent") {
t.Error("Help text should mention agents")
}
}
func TestStopAgentErrorCollection(t *testing.T) {
t.Parallel()
t.Run("parses agent arg correctly", func(t *testing.T) {
t.Parallel()
conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("default-org", false)
tests := []struct {
name string
input string
expectedOrg string
expectedID string
}{
{
name: "agent ID only",
input: "agent-123",
expectedOrg: "default-org",
expectedID: "agent-123",
},
{
name: "org/agent format",
input: "custom-org/agent-456",
expectedOrg: "custom-org",
expectedID: "agent-456",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
org, id := parseAgentArg(tt.input, conf)
if org != tt.expectedOrg {
t.Errorf("expected org %q, got %q", tt.expectedOrg, org)
}
if id != tt.expectedID {
t.Errorf("expected id %q, got %q", tt.expectedID, id)
}
})
}
})
}
func TestStopAgentBulkOperationErrorHandling(t *testing.T) {
t.Parallel()
// This test verifies the error collection logic without running the full command
t.Run("error details format", func(t *testing.T) {
t.Parallel()
errorDetails := []string{}
// Simulate collecting errors
updates := []stopResult{
{id: "agent-1", err: nil},
{id: "agent-2", err: fmt.Errorf("connection timeout")},
{id: "agent-3", err: nil},
{id: "agent-4", err: fmt.Errorf("not found")},
}
for _, update := range updates {
if update.err != nil {
errorDetails = append(errorDetails, fmt.Sprintf("FAILED %s: %v", update.id, update.err))
}
}
if len(errorDetails) != 2 {
t.Errorf("expected 2 error details, got %d", len(errorDetails))
}
if !strings.Contains(errorDetails[0], "agent-2") {
t.Error("expected first error to mention agent-2")
}
if !strings.Contains(errorDetails[1], "agent-4") {
t.Error("expected second error to mention agent-4")
}
if !strings.Contains(errorDetails[0], "connection timeout") {
t.Error("expected first error to include 'connection timeout'")
}
if !strings.Contains(errorDetails[1], "not found") {
t.Error("expected second error to include 'not found'")
}
})
t.Run("progress tracking", func(t *testing.T) {
t.Parallel()
total := 10
succeeded := 0
failed := 0
completed := 0
updates := []stopResult{
{id: "agent-1", err: nil},
{id: "agent-2", err: nil},
{id: "agent-3", err: fmt.Errorf("timeout")},
{id: "agent-4", err: nil},
{id: "agent-5", err: fmt.Errorf("not found")},
}
for _, update := range updates {
completed++
if update.err != nil {
failed++
} else {
succeeded++
}
}
if completed != 5 {
t.Errorf("expected completed=5, got %d", completed)
}
if succeeded != 3 {
t.Errorf("expected succeeded=3, got %d", succeeded)
}
if failed != 2 {
t.Errorf("expected failed=2, got %d", failed)
}
expectedPercent := (completed * 100) / total
if expectedPercent != 50 {
t.Errorf("expected 50%% progress, got %d%%", expectedPercent)
}
})
}
func TestStopProgressOutput(t *testing.T) {
t.Parallel()
t.Run("progress line format", func(t *testing.T) {
t.Parallel()
line := bkIO.ProgressLine("Stopping agents", 5, 10, 3, 2, 6)
if !strings.Contains(line, "Stopping agents") {
t.Error("expected line to contain 'Stopping agents'")
}
if !strings.Contains(line, "50%") {
t.Error("expected line to contain percentage")
}
if !strings.Contains(line, "5/10") {
t.Error("expected line to contain completed/total")
}
if !strings.Contains(line, "succeeded:3") {
t.Error("expected line to contain success count")
}
if !strings.Contains(line, "failed:2") {
t.Error("expected line to contain fail count")
}
if !strings.Contains(line, "[") || !strings.Contains(line, "]") {
t.Error("expected line to contain progress bar brackets")
}
})
}
func TestPluralize(t *testing.T) {
t.Parallel()
tests := []struct {
count int
want string
}{
{count: 1, want: "agent"},
{count: 0, want: "agents"},
{count: 2, want: "agents"},
}
for _, tt := range tests {
tt := tt
t.Run(fmt.Sprintf("count_%d", tt.count), func(t *testing.T) {
t.Parallel()
if got := pluralize("agent", tt.count); got != tt.want {
t.Fatalf("pluralize() = %q, want %q", got, tt.want)
}
})
}
}
================================================
FILE: cmd/agent/util.go
================================================
package agent
import (
"net/url"
"strings"
"github.com/buildkite/cli/v3/internal/config"
)
func parseAgentArg(agent string, conf *config.Config) (string, string) {
var org, id string
agentIsURL := strings.Contains(agent, ":")
agentIsSlug := !agentIsURL && strings.Contains(agent, "/")
if agentIsURL {
url, err := url.Parse(agent)
if err != nil {
return "", ""
}
part := strings.Split(url.Path, "/")
if part[3] == "agents" {
org, id = part[2], part[4]
} else {
org, id = part[2], part[len(part)-1]
}
} else {
if agentIsSlug {
part := strings.Split(agent, "/")
org, id = part[0], part[1]
} else {
org = conf.OrganizationSlug()
id = agent
}
}
return org, id
}
================================================
FILE: cmd/agent/view.go
================================================
package agent
import (
"context"
"fmt"
"os"
"strings"
"time"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
"github.com/pkg/browser"
)
type ViewCmd struct {
Agent string `arg:"" help:"Agent ID to view"`
Web bool `help:"Open agent in a browser" short:"w"`
output.OutputFlags
}
func (c *ViewCmd) Help() string {
return `If the "ORGANIZATION_SLUG/" portion of the "ORGANIZATION_SLUG/UUID" agent argument
is omitted, it uses the currently selected organization.
Examples:
# View an agent
$ bk agent view 0198d108-a532-4a62-9bd7-b2e744bf5c45
# View an agent with organization slug
$ bk agent view my-org/0198d108-a532-4a62-9bd7-b2e744bf5c45
# Open agent in browser
$ bk agent view 0198d108-a532-4a62-9bd7-b2e744bf5c45 --web
# View agent as JSON
$ bk agent view 0198d108-a532-4a62-9bd7-b2e744bf5c45 --output json`
}
func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
org, id := parseAgentArg(c.Agent, f.Config)
if c.Web {
url := fmt.Sprintf("https://buildkite.com/organizations/%s/agents/%s", org, id)
fmt.Printf("Opening %s in your browser\n", url)
return browser.OpenURL(url)
}
var agentData buildkite.Agent
if err = bkIO.SpinWhile(f, "Loading agent", func() error {
var apiErr error
agentData, _, apiErr = f.RestAPIClient.Agents.Get(ctx, org, id)
return apiErr
}); err != nil {
return err
}
if format != output.FormatText {
return output.Write(os.Stdout, agentData, format)
}
metadata, queue := parseMetadata(agentData.Metadata)
if metadata == "" {
metadata = "~"
}
connected := "-"
if agentData.CreatedAt != nil {
connected = agentData.CreatedAt.Format(time.RFC3339)
}
headers := []string{"Property", "Value"}
rows := [][]string{
{"ID", agentData.ID},
{"Name", agentData.Name},
{"State", agentData.ConnectedState},
{"Queue", queue},
{"Version", agentData.Version},
{"Hostname", agentData.Hostname},
{"User Agent", agentData.UserAgent},
{"IP Address", agentData.IPAddress},
{"Connected", connected},
{"Metadata", metadata},
}
table := output.Table(headers, rows, map[string]string{
"property": "bold",
"value": "dim",
})
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() { _ = cleanup() }()
fmt.Fprintf(writer, "Agent %s (%s)\n\n", agentData.Name, agentData.ID)
fmt.Fprint(writer, table)
return nil
}
func parseMetadata(metadataList []string) (string, string) {
var metadataTags []string
var queue string
if len(metadataList) == 1 {
if queueValue := parseQueue(metadataList[0]); queueValue != "" {
return "~", queueValue
}
return metadataList[0], "default"
}
for _, v := range metadataList {
if queueValue := parseQueue(v); queueValue != "" {
queue = queueValue
} else {
metadataTags = append(metadataTags, v)
}
}
if queue == "" {
queue = "default"
}
metadata := strings.Join(metadataTags, ", ")
return metadata, queue
}
func parseQueue(metadata string) string {
parts := strings.Split(metadata, "=")
if len(parts) > 1 && parts[0] == "queue" {
return parts[1]
}
return ""
}
================================================
FILE: cmd/agent/view_test.go
================================================
package agent
import "testing"
func TestParseMetadata(t *testing.T) {
cases := []struct {
name string
input []string
metadata string
queue string
}{
{
name: "single queue entry",
input: []string{"queue=production"},
metadata: "~",
queue: "production",
},
{
name: "single non-queue entry",
input: []string{"os=linux"},
metadata: "os=linux",
queue: "default",
},
{
name: "multiple entries with queue",
input: []string{"queue=deploy", "os=linux", "region=us"},
metadata: "os=linux, region=us",
queue: "deploy",
},
{
name: "no entries",
input: nil,
metadata: "",
queue: "default",
},
{
name: "multiple entries without queue",
input: []string{"os=linux", "region=us"},
metadata: "os=linux, region=us",
queue: "default",
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
metadata, queue := parseMetadata(tc.input)
if metadata != tc.metadata {
t.Fatalf("metadata mismatch: got %q want %q", metadata, tc.metadata)
}
if queue != tc.queue {
t.Fatalf("queue mismatch: got %q want %q", queue, tc.queue)
}
})
}
}
================================================
FILE: cmd/api/api.go
================================================
package api
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"time"
"github.com/Khan/genqlient/graphql"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
httpClient "github.com/buildkite/cli/v3/internal/http"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/vektah/gqlparser/v2/ast"
"github.com/vektah/gqlparser/v2/parser"
)
type ApiCmd struct {
Endpoint string `arg:"" optional:"" help:"API endpoint to call"`
Method string `help:"HTTP method to use" short:"X"`
Headers []string `help:"Headers to include in the request" short:"H"`
Data string `help:"Data to send in the request body" short:"d"`
Analytics bool `help:"Use the Test Analytics endpoint"`
File string `help:"File containing GraphQL query" short:"f"`
Verbose bool `help:"Enable verbose output (currently only provides information about rate limit exceeded retries)"`
}
func (c *ApiCmd) Help() string {
return `
Interact with either the REST or GraphQL Buildkite APIs.
Examples:
# To get a build
$ bk api /pipelines/example-pipeline/builds/420
# To create a pipeline
$ bk api --method POST /pipelines --data '
{
"name": "My Cool Pipeline",
"repository": "git@github.com:acme-inc/my-pipeline.git",
"configuration": "steps:\n - command: env"
}
'
# To update a cluster
$ bk api --method PUT /clusters/CLUSTER_UUID --data '
{
"name": "My Updated Cluster",
}
'
# To get all test suites
$ bk api --analytics /suites
# Run GraphQL query from file
$ bk api --file get_build.graphql
`
}
// buildFullEndpoint constructs the full API endpoint path with organization prefix
func buildFullEndpoint(endpoint, orgSlug string, isAnalytics bool) string {
// Default to root if empty
if endpoint == "" {
endpoint = "/"
}
// Ensure endpoint starts with a leading slash
if !strings.HasPrefix(endpoint, "/") {
endpoint = "/" + endpoint
}
var endpointPrefix string
if isAnalytics {
endpointPrefix = fmt.Sprintf("v2/analytics/organizations/%s", orgSlug)
} else {
endpointPrefix = fmt.Sprintf("v2/organizations/%s", orgSlug)
}
return endpointPrefix + endpoint
}
func (c *ApiCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
// Determine HTTP method: default to GET, but use POST if data is provided and method not explicitly set
method := c.Method
if method == "" {
if c.Data != "" {
method = "POST"
} else {
method = "GET"
}
}
// Handle GraphQL file queries
if c.File != "" {
return c.handleGraphQLQuery(context.Background(), f)
}
fullEndpoint := buildFullEndpoint(c.Endpoint, f.Config.OrganizationSlug(), c.Analytics)
// Create an HTTP client with rate-limit retry via the shared transport.
rl := httpClient.NewRateLimitTransport(nil)
rl.MaxRetryDelay = 60 * time.Second
rl.OnRateLimit = func(attempt int, delay time.Duration) {
if c.Verbose {
fmt.Fprintf(os.Stderr, "WARNING: Rate limit exceeded, retrying in %v @ %q (attempt %d)\n", delay, time.Now().Add(delay).Format(time.RFC3339), attempt)
}
}
client := httpClient.NewClient(
f.Config.APIToken(),
httpClient.WithBaseURL(f.RestAPIClient.BaseURL.String()),
httpClient.WithHTTPClient(&http.Client{Transport: rl}),
)
// Process custom headers
customHeaders := make(map[string]string)
for _, header := range c.Headers {
parts := strings.SplitN(header, ":", 2)
if len(parts) == 2 {
customHeaders[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}
}
var requestData any
if c.Data != "" {
// Try to parse as JSON first
if err := json.Unmarshal([]byte(c.Data), &requestData); err != nil {
// If not JSON, use raw string
requestData = c.Data
}
}
var response any
switch method {
case "GET":
err = client.Get(context.Background(), fullEndpoint, &response)
case "POST":
err = client.Post(context.Background(), fullEndpoint, requestData, &response)
case "PUT":
err = client.Put(context.Background(), fullEndpoint, requestData, &response)
default:
// For other methods, use the Do method directly
err = client.Do(context.Background(), method, fullEndpoint, requestData, &response)
}
if err != nil {
return fmt.Errorf("error making request: %w", err)
}
// Format and print the response
var prettyJSON bytes.Buffer
responseBytes, err := json.Marshal(response)
if err != nil {
return fmt.Errorf("error marshaling response: %w", err)
}
err = json.Indent(&prettyJSON, responseBytes, "", " ")
if err != nil {
return fmt.Errorf("error formatting JSON response: %w", err)
}
fmt.Println(prettyJSON.String())
return nil
}
func (c *ApiCmd) handleGraphQLQuery(ctx context.Context, f *factory.Factory) error {
// Read the GraphQL query from file
queryBytes, err := os.ReadFile(c.File)
if err != nil {
return fmt.Errorf("error reading GraphQL query file %s: %w", c.File, err)
}
// Validate and parse GraphQL query
query := strings.TrimSpace(string(queryBytes))
if query == "" {
return fmt.Errorf("GraphQL query file %s is empty", c.File)
}
doc, err := parser.ParseQuery(&ast.Source{Input: query})
if err != nil {
return fmt.Errorf("invalid GraphQL query: %w", err)
}
// Validate that we have at least one operation
if len(doc.Operations) == 0 {
return fmt.Errorf("GraphQL query must contain at least one operation (query, mutation, or subscription)")
}
// Extract and validate operation name (Buildkite GraphQL API requires named operations)
opName := doc.Operations[0].Name
if opName == "" {
return fmt.Errorf("GraphQL operation must have a name when using file input. Please add a name after the operation type, e.g., 'query MyQuery { ... }'")
}
// Create GraphQL request using the existing client infrastructure
req := &graphql.Request{
OpName: opName,
Query: query,
}
// Use a generic response type for raw queries
resp := &graphql.Response{Data: new(interface{})}
// Use the existing GraphQL client
if err = f.GraphQLClient.MakeRequest(ctx, req, resp); err != nil {
return fmt.Errorf("error making GraphQL request: %w", err)
}
// Format and print the response
responseBytes, err := json.Marshal(resp)
if err != nil {
return fmt.Errorf("error marshaling response: %w", err)
}
var prettyJSON bytes.Buffer
if err = json.Indent(&prettyJSON, responseBytes, "", " "); err != nil {
return fmt.Errorf("error formatting JSON response: %w", err)
}
fmt.Println(prettyJSON.String())
return nil
}
================================================
FILE: cmd/api/api_test.go
================================================
package api
import (
"testing"
)
func TestBuildFullEndpoint(t *testing.T) {
t.Parallel()
testcases := map[string]struct {
endpoint string
orgSlug string
isAnalytics bool
wantEndpoint string
}{
"endpoint with leading slash": {
endpoint: "/pipelines/dummy/builds/5085",
orgSlug: "test-org",
isAnalytics: false,
wantEndpoint: "v2/organizations/test-org/pipelines/dummy/builds/5085",
},
"endpoint without leading slash": {
endpoint: "pipelines/dummy/builds/5085",
orgSlug: "test-org",
isAnalytics: false,
wantEndpoint: "v2/organizations/test-org/pipelines/dummy/builds/5085",
},
"empty endpoint": {
endpoint: "",
orgSlug: "test-org",
isAnalytics: false,
wantEndpoint: "v2/organizations/test-org/",
},
"root endpoint": {
endpoint: "/",
orgSlug: "test-org",
isAnalytics: false,
wantEndpoint: "v2/organizations/test-org/",
},
"analytics endpoint with leading slash": {
endpoint: "/suites",
orgSlug: "test-org",
isAnalytics: true,
wantEndpoint: "v2/analytics/organizations/test-org/suites",
},
"analytics endpoint without leading slash": {
endpoint: "suites",
orgSlug: "test-org",
isAnalytics: true,
wantEndpoint: "v2/analytics/organizations/test-org/suites",
},
"pipeline endpoint without leading slash": {
endpoint: "pipelines",
orgSlug: "acme-inc",
isAnalytics: false,
wantEndpoint: "v2/organizations/acme-inc/pipelines",
},
}
for name, tc := range testcases {
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
got := buildFullEndpoint(tc.endpoint, tc.orgSlug, tc.isAnalytics)
if got != tc.wantEndpoint {
t.Errorf("buildFullEndpoint(%q, %q, %v) = %q, want %q",
tc.endpoint, tc.orgSlug, tc.isAnalytics, got, tc.wantEndpoint)
}
})
}
}
================================================
FILE: cmd/artifacts/download.go
================================================
package artifacts
import (
"context"
"fmt"
"os"
"path/filepath"
"strconv"
"github.com/alecthomas/kong"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/build/resolver/options"
"github.com/buildkite/cli/v3/internal/cli"
bkErrors "github.com/buildkite/cli/v3/internal/errors"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type DownloadCmd struct {
ArtifactID string `arg:"" optional:"" help:"Artifact ID to download. If omitted, all artifacts are downloaded. Use 'bk artifacts list' to find IDs."`
BuildNumber string `help:"Build number containing the artifact. If omitted, the most recent build on the current branch will be used." short:"b" name:"build"`
Pipeline string `help:"The pipeline containing the artifact. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}. If omitted, it will be resolved using the current directory." short:"p"`
JobUUID string `help:"The job UUID containing the artifact." short:"j" name:"job-uuid"`
}
func (c *DownloadCmd) Help() string {
return `
Use this command to download artifacts from a build.
If no artifact ID is provided, all artifacts for the build (or job) will be downloaded.
Artifact IDs can be found using "bk artifacts list".
Examples:
# Download all artifacts from the most recent build on the current branch
$ bk artifacts download
# Download all artifacts from a specific build
$ bk artifacts download --build 429
# Download all artifacts from a specific job
$ bk artifacts download --build 429 --job-uuid 0193903e-ecd9-4c51-9156-0738da987e87
# Download a specific artifact
$ bk artifacts download 0191727d-b5ce-4576-b37d-477ae0ca830c --build 429
# Specify the pipeline explicitly
$ bk artifacts download --build 429 -p monolith
`
}
func (c *DownloadCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
optionsResolver := options.AggregateResolver{
options.ResolveBranchFromFlag(""),
options.ResolveBranchFromRepository(f.GitRepository),
}
var buildResolvers []buildResolver.BuildResolverFn
if c.BuildNumber != "" {
buildResolvers = append(buildResolvers, buildResolver.ResolveFromPositionalArgument([]string{c.BuildNumber}, 0, pipelineRes.Resolve, f.Config))
}
buildResolvers = append(buildResolvers, buildResolver.ResolveBuildWithOpts(f, pipelineRes.Resolve, optionsResolver...))
buildRes := buildResolver.NewAggregateResolver(buildResolvers...)
ctx := context.Background()
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
if bld == nil {
return bkErrors.NewResourceNotFoundError(nil, "no build found")
}
build := strconv.Itoa(bld.BuildNumber)
if c.ArtifactID != "" {
return c.downloadOne(ctx, f, bld.Organization, bld.Pipeline, build)
}
return c.downloadAll(ctx, f, bld.Organization, bld.Pipeline, build)
}
func (c *DownloadCmd) downloadOne(ctx context.Context, f *factory.Factory, org, pipeline, build string) error {
var filename string
if err := bkIO.SpinWhile(f, "Downloading artifact", func() error {
artifact, findErr := findArtifact(ctx, f, org, pipeline, build, c.ArtifactID, c.JobUUID)
if findErr != nil {
return findErr
}
var dlErr error
filename, dlErr = downloadArtifact(ctx, f, artifact)
return dlErr
}); err != nil {
return err
}
fmt.Printf("Downloaded: %s\n", filename)
return nil
}
func (c *DownloadCmd) downloadAll(ctx context.Context, f *factory.Factory, org, pipeline, build string) error {
var artifacts []buildkite.Artifact
if err := bkIO.SpinWhile(f, "Loading artifacts", func() error {
var err error
artifacts, err = listArtifacts(ctx, f, org, pipeline, build, c.JobUUID)
return err
}); err != nil {
return err
}
if len(artifacts) == 0 {
fmt.Println("No artifacts found.")
return nil
}
directory := fmt.Sprintf("artifacts-build-%s", build)
if err := os.MkdirAll(directory, os.ModePerm); err != nil {
return err
}
for i := range artifacts {
a := &artifacts[i]
destPath := filepath.Join(directory, filepath.FromSlash(a.Path))
if err := downloadToFile(ctx, f, a.DownloadURL, destPath); err != nil {
return err
}
fmt.Printf("Downloaded: %s\n", a.Path)
}
fmt.Printf("Downloaded %d artifacts to: %s\n", len(artifacts), directory)
return nil
}
func findArtifact(ctx context.Context, f *factory.Factory, org, pipeline, build, artifactID, jobUUID string) (*buildkite.Artifact, error) {
if jobUUID != "" {
artifact, _, err := f.RestAPIClient.Artifacts.Get(ctx, org, pipeline, build, jobUUID, artifactID)
if err != nil {
return nil, err
}
return &artifact, nil
}
artifacts, err := listArtifacts(ctx, f, org, pipeline, build, "")
if err != nil {
return nil, err
}
for i := range artifacts {
if artifacts[i].ID == artifactID {
return &artifacts[i], nil
}
}
return nil, bkErrors.NewResourceNotFoundError(nil, fmt.Sprintf("no artifact found with ID %s in build #%s", artifactID, build))
}
// listArtifacts fetches all artifacts for a build or job, paginating through all results.
func listArtifacts(ctx context.Context, f *factory.Factory, org, pipeline, build, jobUUID string) ([]buildkite.Artifact, error) {
var all []buildkite.Artifact
opts := &buildkite.ArtifactListOptions{
ListOptions: buildkite.ListOptions{PerPage: 100},
}
for {
var artifacts []buildkite.Artifact
var resp *buildkite.Response
var err error
if jobUUID != "" {
artifacts, resp, err = f.RestAPIClient.Artifacts.ListByJob(ctx, org, pipeline, build, jobUUID, opts)
} else {
artifacts, resp, err = f.RestAPIClient.Artifacts.ListByBuild(ctx, org, pipeline, build, opts)
}
if err != nil {
return nil, err
}
all = append(all, artifacts...)
if resp.NextPage == 0 {
break
}
opts.Page = resp.NextPage
}
return all, nil
}
func downloadArtifact(ctx context.Context, f *factory.Factory, artifact *buildkite.Artifact) (string, error) {
destPath := filepath.FromSlash(artifact.Path)
if err := downloadToFile(ctx, f, artifact.DownloadURL, destPath); err != nil {
return "", err
}
return destPath, nil
}
func downloadToFile(ctx context.Context, f *factory.Factory, url, destPath string) error {
if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil {
return err
}
out, err := os.Create(destPath)
if err != nil {
return err
}
defer out.Close()
_, err = f.RestAPIClient.Artifacts.DownloadArtifactByURL(ctx, url, out)
return err
}
================================================
FILE: cmd/artifacts/list.go
================================================
package artifacts
import (
"context"
"fmt"
"io"
"os"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/artifact"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/build/resolver/options"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type ListCmd struct {
BuildNumber string `arg:"" optional:"" help:"Build number to list artifacts for"`
Pipeline string `help:"The pipeline to view. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}. If omitted, it will be resolved using the current directory." short:"p"`
JobUUID string `help:"List artifacts for a specific job on the given build." short:"j" name:"job-uuid"`
output.OutputFlags
}
func (c *ListCmd) Help() string {
return `
List artifacts for a build or a job in a build.
You can pass an optional build number. If omitted, the most recent build on the current branch will be resolved.
Examples:
# By default, artifacts of the most recent build for the current branch is shown
$ bk artifacts list
# To list artifacts of a specific build
$ bk artifacts list 429
# To list artifacts of a specific job in a build
$ bk artifacts list 429 --job-uuid 0193903e-ecd9-4c51-9156-0738da987e87
# If not inside a repository or to use a specific pipeline, pass -p
$ bk artifacts list 429 -p monolith
`
}
func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
var args []string
if c.BuildNumber != "" {
args = []string{c.BuildNumber}
}
// Resolve a pipeline based on how bk build resolves the pipeline
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
// We resolve a build an optional argument or positional argument
optionsResolver := options.AggregateResolver{
options.ResolveBranchFromFlag(""),
options.ResolveBranchFromRepository(f.GitRepository),
}
buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
buildResolver.ResolveBuildWithOpts(f, pipelineRes.Resolve, optionsResolver...),
)
ctx := context.Background()
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
if bld == nil {
return output.WriteTextOrStructured(os.Stdout, format, []buildkite.Artifact{}, "No build found.")
}
var buildArtifacts []buildkite.Artifact
if err = bkIO.SpinWhile(f, "Loading artifacts information", func() error {
buildArtifacts, err = listArtifacts(ctx, f, bld.Organization, bld.Pipeline, fmt.Sprint(bld.BuildNumber), c.JobUUID)
return err
}); err != nil {
return err
}
if format != output.FormatText {
return output.Write(os.Stdout, buildArtifacts, format)
}
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() { _ = cleanup() }()
if len(buildArtifacts) == 0 {
fmt.Fprintln(writer, "No artifacts found.")
return nil
}
buildURL := fmt.Sprintf("https://buildkite.com/organizations/%s/pipelines/%s/builds/%d", bld.Organization, bld.Pipeline, bld.BuildNumber)
if c.JobUUID != "" {
jobURL := fmt.Sprintf("%s/jobs/%s", buildURL, c.JobUUID)
fmt.Fprintf(writer, "Showing %d artifacts for %s/%s build #%d (job %s): %s\n\n", len(buildArtifacts), bld.Organization, bld.Pipeline, bld.BuildNumber, c.JobUUID, jobURL)
} else {
fmt.Fprintf(writer, "Showing %d artifacts for %s/%s build #%d: %s\n\n", len(buildArtifacts), bld.Organization, bld.Pipeline, bld.BuildNumber, buildURL)
}
return displayArtifacts(buildArtifacts, writer, buildURL)
}
func displayArtifacts(artifacts []buildkite.Artifact, writer io.Writer, baseBuildURL string) error {
headers := []string{"ID", "Path", "Size", "URL"}
var rows [][]string
for _, a := range artifacts {
url := "-"
if a.JobID != "" {
url = fmt.Sprintf("%s/jobs/%s/artifacts/%s", baseBuildURL, a.JobID, a.ID)
} else if a.URL != "" {
url = a.URL
}
rows = append(rows, []string{
a.ID,
a.Path,
artifact.FormatBytes(a.FileSize),
url,
})
}
table := output.Table(headers, rows, map[string]string{
"id": "dim",
"path": "bold",
"size": "dim",
"url": "dim",
})
fmt.Fprint(writer, table)
return nil
}
================================================
FILE: cmd/auth/login.go
================================================
package auth
import (
"context"
"errors"
"fmt"
"os"
"strings"
"time"
"github.com/alecthomas/kong"
buildkite "github.com/buildkite/go-buildkite/v4"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/keyring"
"github.com/buildkite/cli/v3/pkg/oauth"
"github.com/google/uuid"
"github.com/pkg/browser"
)
type LoginCmd struct {
Scopes string `help:"OAuth scopes to request" default:""`
Org string `help:"Organization slug or UUID to request access for" optional:""`
Token string `help:"API token to store (non-OAuth login, requires --org)" optional:""`
}
func organizationIdentifier(org string) (orgSlug, orgUUID string) {
parsedUUID, err := uuid.Parse(org)
if err == nil && strings.EqualFold(parsedUUID.String(), org) {
return "", org
}
return org, ""
}
func (c *LoginCmd) Help() string {
return `
Authenticate with Buildkite using OAuth instead of manually creating an API token.
By default, the CLI requests all available scopes and Buildkite grants only those
your account has permission for. Use --scopes to request a specific subset instead.
Scope groups can be used as shorthand for common permission sets:
read_only All read_* scopes (read-only access)
Groups can be mixed with individual scopes:
--scopes "read_only write_builds"
Examples:
# Login with full permissions (inherits your account's scopes)
$ bk auth login
# Login to a specific organization
$ bk auth login --org my-org
# Login non-interactively with an API token
$ bk auth login --org my-org --token my-token
# Login with read-only access
$ bk auth login --scopes read_only
# Login with read-only plus write access to builds
$ bk auth login --scopes "read_only write_builds"
# Login with specific scopes
$ bk auth login --scopes "read_user read_organizations read_clusters write_clusters"
`
}
// LoginWithToken stores a token for an organization in the system keychain.
// When the keychain is unavailable (e.g. BUILDKITE_NO_KEYRING=1 is set), it
// still registers the org and selects it in config so that commands resolve the
// org correctly; the caller is expected to supply the token via BUILDKITE_API_TOKEN.
func LoginWithToken(f *factory.Factory, org, token string) error {
if org == "" {
return errors.New("--org is required when --token is provided")
}
if token == "" {
return errors.New("--token cannot be empty")
}
kr := keyring.New()
if kr.IsAvailable() {
if err := kr.Set(org, token); err != nil {
return fmt.Errorf("failed to store token in keychain: %w", err)
}
fmt.Println("Token stored securely in system keychain.")
} else {
fmt.Println("Keychain unavailable; token not stored. Use BUILDKITE_API_TOKEN to supply your token at runtime.")
}
if err := f.Config.EnsureOrganization(org); err != nil {
return fmt.Errorf("failed to register organization in config: %w", err)
}
if err := f.Config.SelectOrganization(org, f.GitRepository != nil); err != nil {
return fmt.Errorf("failed to select organization: %w", err)
}
return nil
}
func (c *LoginCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
if c.Token != "" {
if err := LoginWithToken(f, c.Org, c.Token); err != nil {
return err
}
fmt.Printf("\nSuccessfully authenticated with organization %q\n", c.Org)
return nil
}
// Resolve scope groups (e.g., "read_only" → individual read_* scopes).
// When --scopes is empty, no scope parameter is sent and the token
// inherits the user's full Buildkite permissions.
resolvedScopes := oauth.ResolveScopes(c.Scopes)
orgSlug, orgUUID := organizationIdentifier(c.Org)
// Create OAuth flow
cfg := &oauth.Config{
// Host default handled via NewFlow, omitted to allow usage of BUILDKITE_HOST
ClientID: oauth.DefaultClientID,
OrgSlug: orgSlug,
OrgUUID: orgUUID,
Scopes: resolvedScopes,
}
flow, err := oauth.NewFlow(cfg)
if err != nil {
return fmt.Errorf("failed to initialize OAuth flow: %w", err)
}
defer flow.Close()
// Get authorization URL
authURL := flow.AuthorizationURL()
fmt.Println("Opening browser for authentication...")
fmt.Printf("If the browser doesn't open, visit:\n %s\n\n", authURL)
// Open browser
if err := browser.OpenURL(authURL); err != nil {
fmt.Printf("Could not open browser automatically: %v\n", err)
}
// Wait for callback with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
fmt.Println("Waiting for authentication...")
result, err := flow.WaitForCallback(ctx)
if err != nil {
return fmt.Errorf("authentication failed: %w", err)
}
// Exchange code for token
fmt.Println("Exchanging authorization code for token...")
tokenResp, err := flow.ExchangeCode(ctx, result.Code)
if err != nil {
return fmt.Errorf("token exchange failed: %w", err)
}
// Resolve org from the API using the new token
client, err := buildkite.NewOpts(
buildkite.WithTokenAuth(tokenResp.AccessToken),
buildkite.WithBaseURL(f.Config.RESTAPIEndpoint()),
)
if err != nil {
return fmt.Errorf("failed to create API client: %w", err)
}
orgs, _, err := client.Organizations.List(ctx, nil)
if err != nil {
return fmt.Errorf("failed to list organizations: %w", err)
}
if len(orgs) == 0 {
return fmt.Errorf("no organizations found for this token")
}
org := orgs[0]
if err := LoginWithToken(f, org.Slug, tokenResp.AccessToken); err != nil {
return err
}
// Store refresh token if the server issued one
if tokenResp.RefreshToken != "" {
kr := keyring.New()
if kr.IsAvailable() {
if err := kr.SetRefreshToken(org.Slug, tokenResp.RefreshToken); err != nil {
fmt.Fprintf(os.Stderr, "Warning: failed to store refresh token: %v\n", err)
}
}
}
fmt.Printf("\n✅ Successfully authenticated with organization %q\n", org.Slug)
fmt.Printf(" Scopes: %s\n", tokenResp.Scope)
if tokenResp.RefreshToken != "" {
fmt.Printf(" Token expires in: %s (will refresh automatically)\n", formatDuration(tokenResp.ExpiresIn))
}
return nil
}
func formatDuration(seconds int) string {
if seconds <= 0 {
return "unknown"
}
d := time.Duration(seconds) * time.Second
if d >= time.Hour {
hours := int(d.Hours())
if hours == 1 {
return "1 hour"
}
return fmt.Sprintf("%d hours", hours)
}
return fmt.Sprintf("%d minutes", int(d.Minutes()))
}
================================================
FILE: cmd/auth/login_test.go
================================================
package auth
import "testing"
func TestOrganizationIdentifier(t *testing.T) {
t.Parallel()
tests := []struct {
name string
org string
wantSlug string
wantUUID string
}{
{
name: "slug",
org: "buildkite",
wantSlug: "buildkite",
wantUUID: "",
},
{
name: "uuid",
org: "018f2f7e-7e99-7d77-b4d3-a95cb01805f4",
wantSlug: "",
wantUUID: "018f2f7e-7e99-7d77-b4d3-a95cb01805f4",
},
{
name: "uppercase uuid",
org: "018F2F7E-7E99-7D77-B4D3-A95CB01805F4",
wantSlug: "",
wantUUID: "018F2F7E-7E99-7D77-B4D3-A95CB01805F4",
},
{
name: "uuid-like slug without hyphens",
org: "018f2f7e7e997d77b4d3a95cb01805f4",
wantSlug: "018f2f7e7e997d77b4d3a95cb01805f4",
wantUUID: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
gotSlug, gotUUID := organizationIdentifier(tt.org)
if gotSlug != tt.wantSlug || gotUUID != tt.wantUUID {
t.Fatalf("organizationIdentifier(%q) = (%q, %q), want (%q, %q)", tt.org, gotSlug, gotUUID, tt.wantSlug, tt.wantUUID)
}
})
}
}
================================================
FILE: cmd/auth/logout.go
================================================
package auth
import (
"fmt"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/keyring"
)
type LogoutCmd struct {
All bool `help:"Log out of all organizations" xor:"target"`
Org string `help:"Organization slug (defaults to currently selected organization)" optional:"" xor:"target"`
}
func (c *LogoutCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
if c.All {
return c.logoutAll(f)
}
return c.logoutOrg(f)
}
func (c *LogoutCmd) logoutAll(f *factory.Factory) error {
orgs := f.Config.ConfiguredOrganizations()
kr := keyring.New()
if kr.IsAvailable() {
for _, org := range orgs {
if err := kr.Delete(org); err != nil {
fmt.Printf("Warning: could not remove token from keychain for %q: %v\n", org, err)
}
_ = kr.DeleteRefreshToken(org)
}
}
if err := f.Config.ClearAllOrganizations(); err != nil {
return fmt.Errorf("failed to clear organizations from config: %w", err)
}
fmt.Printf("Logged out of all %d organizations\n", len(orgs))
return nil
}
func (c *LogoutCmd) logoutOrg(f *factory.Factory) error {
org := c.Org
if org == "" {
org = f.Config.OrganizationSlug()
}
if org == "" {
return fmt.Errorf("no organization specified and none currently selected")
}
kr := keyring.New()
if kr.IsAvailable() {
if err := kr.Delete(org); err != nil {
fmt.Printf("Warning: could not remove token from keychain: %v\n", err)
} else {
fmt.Println("Token removed from system keychain.")
}
_ = kr.DeleteRefreshToken(org)
}
fmt.Printf("Logged out of organization %q\n", org)
return nil
}
================================================
FILE: cmd/auth/status.go
================================================
// Package auth handles commands related to authentication via the CLI
package auth
import (
"context"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
"github.com/buildkite/go-buildkite/v4"
)
type StatusOutput struct {
OrganizationSlug string `json:"organization_slug"`
Token buildkite.AccessToken `json:"token"`
}
func (w StatusOutput) TextOutput() string {
b := strings.Builder{}
fmt.Fprintf(&b, "Current organization: %s\n", w.OrganizationSlug)
b.WriteRune('\n')
fmt.Fprintf(&b, "API Token UUID: %s\n", w.Token.UUID)
fmt.Fprintf(&b, "API Token Description: %s\n", w.Token.Description)
fmt.Fprintf(&b, "API Token Scopes: %v\n", w.Token.Scopes)
b.WriteRune('\n')
fmt.Fprintf(&b, "API Token user name: %s\n", w.Token.User.Name)
fmt.Fprintf(&b, "API Token user email: %s\n", w.Token.User.Email)
return b.String()
}
type StatusCmd struct {
output.OutputFlags
}
func (c *StatusCmd) Help() string {
return `
It returns information on the current session.
Examples:
# List the current token session
$ bk auth status
`
}
func (c *StatusCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
if validationErr := validation.ValidateConfiguration(f.Config, kongCtx.Command()); validationErr != nil {
return validationErr
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
orgSlug := f.Config.OrganizationSlug()
if orgSlug == "" {
orgSlug = "<None>"
}
token, _, err := f.RestAPIClient.AccessTokens.Get(ctx)
if err != nil {
return fmt.Errorf("failed to get access token: %w", err)
}
w := StatusOutput{
OrganizationSlug: orgSlug,
Token: token,
}
err = output.Write(os.Stdout, w, format)
if err != nil {
return fmt.Errorf("failed to write output: %w", err)
}
return nil
}
================================================
FILE: cmd/auth/switch.go
================================================
package auth
import (
"fmt"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/internal/config"
"github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
)
type SwitchCmd struct {
OrganizationSlug string `arg:"" optional:"" help:"Organization slug to switch"`
}
func (c *SwitchCmd) Help() string {
return `Select a configured organization.
Examples:
# Switch the 'my-cool-org' configuration
$ bk auth switch my-cool-org
# Interactively select an organization
$ bk auth switch
`
}
func (c *SwitchCmd) Run(globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.NoInput = globals.DisableInput()
var org *string
if c.OrganizationSlug != "" {
org = &c.OrganizationSlug
}
return switchRun(org, f.Config, f.GitRepository != nil, f.NoInput)
}
func switchRun(org *string, conf *config.Config, inGitRepo bool, noInput bool) error {
var selected string
// prompt to choose from configured orgs if one is not already selected
if org == nil {
var err error
selected, err = io.PromptForOne("organization", conf.ConfiguredOrganizations(), noInput)
if err != nil {
return err
}
} else {
selected = *org
}
// if already selected, do nothing
if conf.OrganizationSlug() == selected {
fmt.Printf("Using configuration for `%s`\n", selected)
return nil
}
// if the selected org exists, switch it
if conf.HasConfiguredOrganization(selected) {
fmt.Printf("Using configuration for `%s`\n", selected)
return conf.SelectOrganization(selected, inGitRepo)
}
// if the selected org doesnt exist, recommend configuring it and error out
return fmt.Errorf("no configuration found for `%s`. run `bk auth login` to add it", selected)
}
================================================
FILE: cmd/auth/switch_test.go
================================================
package auth
import (
"os"
"path/filepath"
"testing"
"github.com/buildkite/cli/v3/internal/config"
"github.com/spf13/afero"
)
func setEnv(t *testing.T, key, value string) {
original, had := os.LookupEnv(key)
if err := os.Setenv(key, value); err != nil {
t.Fatalf("failed to set env %s: %v", key, err)
}
t.Cleanup(func() {
var restoreErr error
if had {
restoreErr = os.Setenv(key, original)
} else {
restoreErr = os.Unsetenv(key)
}
if restoreErr != nil {
t.Fatalf("failed to restore env %s: %v", key, restoreErr)
}
})
}
func TestCmdSwitch(t *testing.T) {
t.Parallel()
t.Run("switches already selected org", func(t *testing.T) {
t.Parallel()
conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing", true)
selected := "testing"
err := switchRun(&selected, conf, true, false)
if err != nil {
t.Error("expected no error")
}
if conf.OrganizationSlug() != "testing" {
t.Error("expected no change in organization")
}
})
t.Run("switches existing org", func(t *testing.T) {
t.Parallel()
// add some configurations
fs := afero.NewMemMapFs()
conf := config.New(fs, nil)
conf.SelectOrganization("testing", true)
conf.EnsureOrganization("testing")
conf.EnsureOrganization("default")
// now get a new empty config
conf = config.New(fs, nil)
selected := "testing"
err := switchRun(&selected, conf, true, false)
if err != nil {
t.Errorf("expected no error: %s", err)
}
if conf.OrganizationSlug() != "testing" {
t.Error("expected no change in organization")
}
})
t.Run("errors if missing org", func(t *testing.T) {
t.Parallel()
selected := "testing"
conf := config.New(afero.NewMemMapFs(), nil)
err := switchRun(&selected, conf, true, false)
if err == nil {
t.Error("expected an error")
}
})
t.Run("reads organization from user's config file", func(t *testing.T) {
home := t.TempDir()
setEnv(t, "HOME", home)
xdgConfig := filepath.Join(home, ".config")
setEnv(t, "XDG_CONFIG_HOME", xdgConfig)
setEnv(t, "BUILDKITE_API_TOKEN", "")
setEnv(t, "BUILDKITE_ORGANIZATION_SLUG", "")
if err := os.MkdirAll(xdgConfig, 0o755); err != nil {
t.Fatalf("failed to create config dir: %v", err)
}
switchrConfigPath := filepath.Join(xdgConfig, "bk.yaml")
content := []byte("selected_org: testing\norganizations:\n testing:\n api_token: token-123\n")
if err := os.WriteFile(switchrConfigPath, content, 0o644); err != nil {
t.Fatalf("failed to write switchr config: %v", err)
}
conf := config.New(afero.NewOsFs(), nil)
if got := conf.OrganizationSlug(); got != "testing" {
t.Fatalf("expected organization from file, got %q", got)
}
if got := conf.APIToken(); got != "token-123" {
t.Fatalf("expected token from file, got %q", got)
}
selected := "testing"
if err := switchRun(&selected, conf, false, true); err != nil {
t.Fatalf("expected switchRun to succeed: %v", err)
}
})
t.Run("preserves organization name case", func(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
orgName string
}{
{"mixed case", "gridX"},
{"uppercase", "ACME"},
{"lowercase", "buildkite"},
{"camelCase", "myOrg"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
fs := afero.NewMemMapFs()
conf := config.New(fs, nil)
// Configure organization with specific case
if err := conf.EnsureOrganization(tc.orgName); err != nil {
t.Fatalf("EnsureOrganization failed: %v", err)
}
if err := conf.SelectOrganization(tc.orgName, false); err != nil {
t.Fatalf("SelectOrganization failed: %v", err)
}
// Switch the organization
if err := switchRun(&tc.orgName, conf, false, true); err != nil {
t.Fatalf("switchRun failed: %v", err)
}
// Verify case is preserved
gotOrg := conf.OrganizationSlug()
if gotOrg != tc.orgName {
t.Errorf("expected organization %q, got %q - case was not preserved", tc.orgName, gotOrg)
}
})
}
})
}
================================================
FILE: cmd/auth/token.go
================================================
package auth
import (
"fmt"
"os"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
)
type TokenCmd struct{}
func (c *TokenCmd) Help() string {
return `
Prints the stored API token for the currently selected organization to stdout.
The token is retrieved from the system keychain (or the BUILDKITE_API_TOKEN
environment variable if set). This is useful for passing the token to other
tools, for example:
Examples:
# Print the current token
$ bk auth token
# Use the token in a curl request
$ curl -H "Authorization: Bearer $(bk auth token)" https://api.buildkite.com/v2/user
`
}
func (c *TokenCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
token := f.Config.APIToken()
if token == "" {
return fmt.Errorf("no token found; run `bk auth login` to authenticate")
}
fmt.Fprintln(os.Stdout, token)
return nil
}
================================================
FILE: cmd/build/cancel.go
================================================
package build
import (
"context"
"fmt"
"github.com/alecthomas/kong"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/internal/util"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type CancelCmd struct {
BuildNumber string `arg:"" help:"Build number to cancel"`
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Web bool `help:"Open the build in a web browser after it has been cancelled." short:"w"`
}
func (c *CancelCmd) Help() string {
return `
Examples:
# Cancel a build by number
$ bk build cancel 123 --pipeline my-pipeline
# Cancel a build and open in browser
$ bk build cancel 123 -pipeline my-pipeline --web`
}
func (c *CancelCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
args := []string{c.BuildNumber}
buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
)
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
confirmed, err := bkIO.Confirm(f, fmt.Sprintf("Cancel build #%d on %s", bld.BuildNumber, bld.Pipeline))
if err != nil {
return err
}
if !confirmed {
return nil
}
return cancelBuild(ctx, bld.Organization, bld.Pipeline, fmt.Sprint(bld.BuildNumber), c.Web, f)
}
func cancelBuild(ctx context.Context, org string, pipeline string, buildId string, web bool, f *factory.Factory) error {
var build buildkite.Build
if err := bkIO.SpinWhile(f, fmt.Sprintf("Cancelling build #%s from pipeline %s", buildId, pipeline), func() error {
var apiErr error
build, apiErr = f.RestAPIClient.Builds.Cancel(ctx, org, pipeline, buildId)
return apiErr
}); err != nil {
return err
}
fmt.Printf("%s\n", renderResult(fmt.Sprintf("Build canceled: %s", build.WebURL)))
return util.OpenInWebBrowser(web, build.WebURL)
}
================================================
FILE: cmd/build/create.go
================================================
package build
import (
"bufio"
"context"
"fmt"
"os"
"strings"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkErrors "github.com/buildkite/cli/v3/internal/errors"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/internal/util"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type CreateCmd struct {
Message string `help:"Description of the build. If left blank, the commit message will be used once the build starts." short:"m"`
Commit string `help:"The commit to build." short:"c" default:"HEAD"`
Branch string `help:"The branch to build. Defaults to the default branch of the pipeline." short:"b"`
Author string `help:"Author of the build. Supports: \"Name <email>\", \"email@domain.com\", \"Full Name\", or \"username\"" short:"a"`
Web bool `help:"Open the build in a web browser after it has been created." short:"w"`
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Env []string `help:"Set environment variables for the build (KEY=VALUE)" short:"e" sep:"none"`
Metadata []string `help:"Set metadata for the build (KEY=VALUE)" short:"M" sep:"none"`
IgnoreBranchFilters bool `help:"Ignore branch filters for the pipeline" short:"i"`
EnvFile string `help:"Set the environment variables for the build via an environment file" short:"f"`
}
func (c *CreateCmd) Help() string {
return `The web URL to the build will be printed to stdout.
Examples:
# Create a new build
$ bk build create
# Create a new build with environment variables set
$ bk build create -e "FOO=BAR" -e "BAR=BAZ"
# Create a new build with metadata
$ bk build create -M "key=value" -M "foo=bar"`
}
func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
// Initialize factory
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return bkErrors.NewInternalError(err, "failed to initialize CLI", "This is likely a bug", "Report to Buildkite")
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
resolvers := resolver.NewAggregateResolver(
resolver.ResolveFromFlag(c.Pipeline, f.Config),
resolver.ResolveFromConfig(f.Config, resolver.PickOneWithFactory(f)),
resolver.ResolveFromRepository(f, resolver.CachedPicker(f.Config, resolver.PickOneWithFactory(f))),
)
resolvedPipeline, err := resolvers.Resolve(ctx)
if err != nil {
return err // Already wrapped by resolver
}
if resolvedPipeline == nil {
return bkErrors.NewResourceNotFoundError(
nil,
"could not resolve a pipeline",
"Specify a pipeline with --pipeline (-p)",
"Run 'bk pipeline list' to see available pipelines",
)
}
confirmed, err := bkIO.Confirm(f, fmt.Sprintf("Create new build on %s?", resolvedPipeline.Name))
if err != nil {
return bkErrors.NewUserAbortedError(err, "confirmation canceled")
}
if !confirmed {
fmt.Println("Build creation canceled")
return nil
}
// Process environment variables
envMap := make(map[string]string)
for _, e := range c.Env {
key, value, _ := strings.Cut(e, "=")
envMap[key] = value
}
// Process metadata variables
metaDataMap := make(map[string]string)
for _, m := range c.Metadata {
key, value, _ := strings.Cut(m, "=")
metaDataMap[key] = value
}
// Process environment file if specified
if c.EnvFile != "" {
file, err := os.Open(c.EnvFile)
if err != nil {
return bkErrors.NewValidationError(
err,
fmt.Sprintf("could not open environment file: %s", c.EnvFile),
"Check that the file exists and is readable",
)
}
defer file.Close()
content := bufio.NewScanner(file)
for content.Scan() {
key, value, _ := strings.Cut(content.Text(), "=")
envMap[key] = value
}
if err := content.Err(); err != nil {
return bkErrors.NewValidationError(
err,
"error reading environment file",
"Ensure the file contains valid environment variables in KEY=VALUE format",
)
}
}
return createBuild(ctx, resolvedPipeline.Org, resolvedPipeline.Name, f, c.Message, c.Commit, c.Branch, c.Web, envMap, metaDataMap, c.IgnoreBranchFilters, c.Author)
}
func parseAuthor(author string) buildkite.Author {
if author == "" {
return buildkite.Author{}
}
// Check for Git-style format: "Name <email@domain.com>"
if strings.Contains(author, "<") && strings.Contains(author, ">") {
parts := strings.Split(author, "<")
if len(parts) == 2 {
name := strings.TrimSpace(parts[0])
email := strings.TrimSpace(strings.Trim(parts[1], ">"))
if name != "" && email != "" {
return buildkite.Author{Name: name, Email: email}
}
}
}
// Check for email-only format
if strings.Contains(author, "@") && strings.Contains(author, ".") && !strings.Contains(author, " ") {
return buildkite.Author{Email: author}
}
// Check for name format (contains spaces but no email)
if strings.Contains(author, " ") {
return buildkite.Author{Name: author}
}
// Default to username
return buildkite.Author{Username: author}
}
func createBuild(ctx context.Context, org string, pipeline string, f *factory.Factory, message string, commit string, branch string, web bool, env map[string]string, metaData map[string]string, ignoreBranchFilters bool, author string) error {
var build buildkite.Build
if err := bkIO.SpinWhile(f, fmt.Sprintf("Starting new build for %s", pipeline), func() error {
branch = strings.TrimSpace(branch)
if len(branch) == 0 {
p, _, err := f.RestAPIClient.Pipelines.Get(ctx, org, pipeline)
if err != nil {
return bkErrors.WrapAPIError(err, "fetching pipeline information")
}
// Check if the pipeline has a default branch set
if p.DefaultBranch == "" {
return bkErrors.NewValidationError(
nil,
fmt.Sprintf("No default branch set for pipeline %s", pipeline),
"Please specify a branch using --branch (-b)",
"Set a default branch in your pipeline settings on Buildkite",
)
}
branch = p.DefaultBranch
}
newBuild := buildkite.CreateBuild{
Message: message,
Commit: commit,
Branch: branch,
Author: parseAuthor(author),
Env: env,
MetaData: metaData,
IgnorePipelineBranchFilters: ignoreBranchFilters,
}
var err error
build, _, err = f.RestAPIClient.Builds.Create(ctx, org, pipeline, newBuild)
if err != nil {
return bkErrors.WrapAPIError(err, "creating build")
}
return nil
}); err != nil {
return err
}
if build.WebURL == "" {
return bkErrors.NewAPIError(
nil,
"build was created but no URL was returned",
"This may be due to an API version mismatch",
)
}
fmt.Printf("%s\n", renderResult(fmt.Sprintf("Build created: %s", build.WebURL)))
if err := util.OpenInWebBrowser(web, build.WebURL); err != nil {
return bkErrors.NewInternalError(err, "failed to open web browser")
}
return nil
}
func renderResult(result string) string {
return result
}
================================================
FILE: cmd/build/download.go
================================================
package build
import (
"context"
"fmt"
"os"
"path/filepath"
"sync"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/build"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/build/resolver/options"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
)
type DownloadCmd struct {
BuildNumber string `arg:"" optional:"" help:"Build number to download (omit for most recent build)"`
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Branch string `help:"Filter builds to this branch." short:"b"`
User string `help:"Filter builds to this user. You can use name or email." short:"u" xor:"userfilter"`
Mine bool `help:"Filter builds to only my user." short:"m" xor:"userfilter"`
}
func (c *DownloadCmd) Help() string {
return `
Examples:
# Download build 123
$ bk build download 123 --pipeline my-pipeline
# Download most recent build
$ bk build download --pipeline my-pipeline
# Download most recent build on a branch
$ bk build download -b main --pipeline my-pipeline
# Download most recent build by a user
$ bk build download --pipeline my-pipeline -u alice@hello.com
# Download most recent build by yourself
$ bk build download --pipeline my-pipeline --mine`
}
func (c *DownloadCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
// we find the pipeline based on the following rules:
// 1. an explicit flag is passed
// 2. a configured pipeline for this directory
// 3. find pipelines matching the current repository from the API
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
// we resolve a build based on the following rules:
// 1. an optional argument
// 2. resolve from API using some context
// a. filter by branch if --branch or use current repo
// b. filter by user if --user or --mine given
optionsResolver := options.AggregateResolver{
options.ResolveBranchFromFlag(c.Branch),
options.ResolveBranchFromRepository(f.GitRepository),
}.WithResolverWhen(
c.User != "",
options.ResolveUserFromFlag(c.User),
).WithResolverWhen(
c.Mine || c.User == "",
options.ResolveCurrentUser(ctx, f),
)
args := []string{}
if c.BuildNumber != "" {
args = []string{c.BuildNumber}
}
buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
buildResolver.ResolveBuildWithOpts(f, pipelineRes.Resolve, optionsResolver...),
)
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
if bld == nil {
fmt.Println("No build found.")
return nil
}
var dir string
if err = bkIO.SpinWhile(f, "Downloading build resources", func() error {
dir, err = download(ctx, bld, f)
return err
}); err != nil {
return err
}
fmt.Printf("Downloaded build to: %s\n", dir)
return nil
}
func download(ctx context.Context, build *build.Build, f *factory.Factory) (string, error) {
var wg sync.WaitGroup
var mu sync.Mutex
b, _, err := f.RestAPIClient.Builds.Get(ctx, build.Organization, build.Pipeline, fmt.Sprint(build.BuildNumber), nil)
if err != nil {
return "", err
}
directory := fmt.Sprintf("build-%s", b.ID)
err = os.MkdirAll(directory, os.ModePerm)
if err != nil {
return "", err
}
for _, job := range b.Jobs {
// only script (command) jobs will have logs
if job.Type != "script" {
continue
}
go func() {
defer wg.Done()
wg.Add(1)
log, _, apiErr := f.RestAPIClient.Jobs.GetJobLog(ctx, build.Organization, build.Pipeline, b.ID, job.ID)
if err != nil {
mu.Lock()
err = apiErr
mu.Unlock()
return
}
fileErr := os.WriteFile(filepath.Join(directory, job.ID), []byte(log.Content), 0o644)
if fileErr != nil {
mu.Lock()
err = fileErr
mu.Unlock()
}
}()
}
artifacts, _, err := f.RestAPIClient.Artifacts.ListByBuild(ctx, build.Organization, build.Pipeline, fmt.Sprint(build.BuildNumber), nil)
if err != nil {
return "", err
}
for _, artifact := range artifacts {
go func() {
defer wg.Done()
wg.Add(1)
out, fileErr := os.Create(filepath.Join(directory, fmt.Sprintf("artifact-%s-%s", artifact.ID, artifact.Filename)))
if err != nil {
err = fileErr
}
_, apiErr := f.RestAPIClient.Artifacts.DownloadArtifactByURL(ctx, artifact.DownloadURL, out)
if err != nil {
err = apiErr
}
}()
}
wg.Wait()
if err != nil {
return "", err
}
return directory, nil
}
================================================
FILE: cmd/build/list.go
================================================
package build
import (
"context"
"encoding/base64"
"fmt"
"io"
"net/mail"
"os"
"strings"
"time"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/internal/graphql"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
const (
maxBuildLimit = 5000
pageSize = 100
)
type ListCmd struct {
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Since string `help:"Filter builds created since this time (e.g. 1h, 30m)"`
Until string `help:"Filter builds created before this time (e.g. 1h, 30m)"`
Duration string `help:"Filter by duration (e.g. >5m, <10m, 20m) - supports >, <, >=, <= operators"`
State []string `help:"Filter by build state"`
Branch []string `help:"Filter by branch name"`
Creator string `help:"Filter by creator (email address or user ID)"`
Commit string `help:"Filter by commit SHA"`
Message string `help:"Filter by message content"`
MetaData map[string]string `help:"Filter by build meta-data (key=value format, can be specified multiple times)"`
Limit int `help:"Maximum number of builds to return" default:"50"`
NoLimit bool `help:"Fetch all builds (overrides --limit)"`
output.OutputFlags
}
func (c *ListCmd) Help() string {
return `List builds with optional filtering.
This command supports both server-side filtering (fast) and client-side filtering.
Server-side filters are applied by the Buildkite API, while client-side filters
are applied after fetching results and may require loading more builds.
Client-side filters: --duration, --message
Server-side filters: --pipeline, --since, --until, --state, --branch, --creator, --commit, --meta-data
Builds can be filtered by their duration, message content, and other attributes.
When filtering by duration, you can use operators like >, <, >=, and <= to specify your criteria.
Supported duration units are seconds (s), minutes (m), and hours (h).
Examples:
# List recent builds (50 by default)
$ bk build list
# Get more builds (automatically paginates)
$ bk build list --limit 500
# List builds from the last hour
$ bk build list --since 1h
# List failed builds
$ bk build list --state failed
# List builds on main branch
$ bk build list --branch main
# List builds by alice
$ bk build list --creator alice@company.com
# List builds that took longer than 20 minutes
$ bk build list --duration ">20m"
# List builds that finished in under 5 minutes
$ bk build list --duration "<5m"
# Combine filters: failed builds on main branch in the last 24 hours
$ bk build list --state failed --branch main --since 24h
# Find builds containing "deploy" in the message
$ bk build list --message deploy
# Filter builds by meta-data
$ bk build list --meta-data env=production
# Filter by multiple meta-data keys
$ bk build list --meta-data env=production --meta-data deploy=true
# Complex filtering: slow builds (>30m) that failed on feature branches
$ bk build list --duration ">30m" --state failed --branch feature/`
}
func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
if !c.NoLimit {
if c.Limit > maxBuildLimit {
return fmt.Errorf("limit cannot exceed %d builds (requested: %d); if you need more, use --no-limit", maxBuildLimit, c.Limit)
}
}
if c.Creator != "" && isValidEmail(c.Creator) {
originalEmail := c.Creator
if err = bkIO.SpinWhile(f, "Looking up user", func() error {
c.Creator, err = resolveCreatorEmailToUserID(ctx, f, originalEmail)
return err
}); err != nil {
return fmt.Errorf("failed to resolve creator email: %w", err)
}
if c.Creator == "" {
return fmt.Errorf("failed to resolve creator email: no user found")
}
}
listOpts, err := c.buildListOptions()
if err != nil {
return err
}
org := f.Config.OrganizationSlug()
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
if format == output.FormatText {
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() { _ = cleanup() }()
target := org
if c.Pipeline != "" {
target = fmt.Sprintf("%s/%s", org, c.Pipeline)
}
fmt.Fprintf(writer, "Showing builds for %s\n\n", target)
builds, err := c.fetchBuilds(ctx, f, org, listOpts, format, writer)
if err != nil {
return fmt.Errorf("failed to list builds: %w", err)
}
if len(builds) == 0 {
fmt.Fprintln(writer, "No builds found matching the specified criteria.")
}
return nil
}
builds, err := c.fetchBuilds(ctx, f, org, listOpts, format, nil)
if err != nil {
return fmt.Errorf("failed to list builds: %w", err)
}
if len(builds) == 0 {
return output.Write(os.Stdout, []buildkite.Build{}, format)
}
return displayBuilds(builds, format, os.Stdout)
}
func (c *ListCmd) buildListOptions() (*buildkite.BuildsListOptions, error) {
listOpts := &buildkite.BuildsListOptions{
ListOptions: buildkite.ListOptions{
PerPage: pageSize,
},
}
now := time.Now()
if c.Since != "" {
d, err := time.ParseDuration(c.Since)
if err != nil {
return nil, fmt.Errorf("invalid since duration '%s': %w", c.Since, err)
}
listOpts.CreatedFrom = now.Add(-d)
}
if c.Until != "" {
d, err := time.ParseDuration(c.Until)
if err != nil {
return nil, fmt.Errorf("invalid until duration '%s': %w", c.Until, err)
}
listOpts.CreatedTo = now.Add(-d)
}
if len(c.State) > 0 {
listOpts.State = make([]string, len(c.State))
for i, state := range c.State {
listOpts.State[i] = strings.ToLower(state)
}
}
listOpts.Branch = c.Branch
listOpts.Creator = c.Creator
listOpts.Commit = c.Commit
if len(c.MetaData) > 0 {
listOpts.MetaData = buildkite.MetaDataFilters{
MetaData: c.MetaData,
}
}
return listOpts, nil
}
func (c *ListCmd) fetchBuilds(ctx context.Context, f *factory.Factory, org string, listOpts *buildkite.BuildsListOptions, format output.Format, writer io.Writer) ([]buildkite.Build, error) {
var allBuilds []buildkite.Build
// filtered builds added since last confirm (used when --no-limit)
filteredSinceConfirm := 0
// raw (unfiltered) build counters so progress messaging makes sense when client-side filters are active
rawTotalFetched := 0
rawSinceConfirm := 0
previousPageFirstBuildNumber := 0
printedAny := false
for page := 1; ; page++ {
if !c.NoLimit && len(allBuilds) >= c.Limit {
break
}
listOpts.Page = page
var builds []buildkite.Build
var err error
spinnerMsg := "Loading builds ("
if c.Pipeline != "" {
spinnerMsg += fmt.Sprintf("pipeline %s, ", c.Pipeline)
}
filtersActive := c.Duration != "" || c.Message != ""
// Show matching (filtered) counts and raw counts independently
if !c.NoLimit && c.Limit > 0 {
spinnerMsg += fmt.Sprintf("%d/%d matching, %d raw fetched", len(allBuilds), c.Limit, rawTotalFetched)
} else {
spinnerMsg += fmt.Sprintf("%d matching, %d raw fetched", len(allBuilds), rawTotalFetched)
}
spinnerMsg += ")"
if format == output.FormatText && rawSinceConfirm >= maxBuildLimit {
prompt := fmt.Sprintf("Fetched %d more builds (%d total). Continue?", rawSinceConfirm, rawTotalFetched)
if filtersActive {
prompt = fmt.Sprintf(
"Fetched %d raw builds (%d matching, %d matching total). Continue?",
rawSinceConfirm, filteredSinceConfirm, len(allBuilds),
)
}
confirmed, err := bkIO.Confirm(f, prompt)
if err != nil {
return nil, err
}
if !confirmed {
return allBuilds, nil
}
filteredSinceConfirm = 0
rawSinceConfirm = 0
}
if err = bkIO.SpinWhile(f, spinnerMsg, func() error {
if c.Pipeline != "" {
builds, err = c.getBuildsByPipeline(ctx, f, org, listOpts)
} else {
builds, _, err = f.RestAPIClient.Builds.ListByOrg(ctx, org, listOpts)
}
return err
}); err != nil {
return nil, err
}
if len(builds) == 0 {
break
}
// Track raw builds fetched before applying client-side filters
rawCountThisPage := len(builds)
rawTotalFetched += rawCountThisPage
rawSinceConfirm += rawCountThisPage
// Detect duplicate first build number between pages to prevent infinite loop
if page > 1 && len(builds) > 0 {
currentPageFirstBuildNumber := builds[0].Number
if currentPageFirstBuildNumber == previousPageFirstBuildNumber {
return nil, fmt.Errorf("API returned duplicate results, stopping to prevent infinite loop")
}
}
if len(builds) > 0 {
previousPageFirstBuildNumber = builds[0].Number
}
builds, err = c.applyClientSideFilters(builds)
if err != nil {
return nil, fmt.Errorf("failed to apply filters: %w", err)
}
// Decide which builds will actually be added (respect limit)
var buildsToAdd []buildkite.Build
addedThisPage := 0
if !c.NoLimit {
remaining := c.Limit - len(allBuilds)
if remaining <= 0 {
break
}
if len(builds) > remaining {
buildsToAdd = builds[:remaining]
addedThisPage = remaining
} else {
buildsToAdd = builds
addedThisPage = len(builds)
}
} else {
buildsToAdd = builds
addedThisPage = len(builds)
}
// Stream only the builds we are about to add; header only once we actually print something
if format == output.FormatText && len(buildsToAdd) > 0 && writer != nil {
_ = displayBuilds(buildsToAdd, format, writer)
if !printedAny {
fmt.Fprintln(writer)
}
printedAny = true
}
allBuilds = append(allBuilds, buildsToAdd...)
filteredSinceConfirm += addedThisPage
if rawCountThisPage < listOpts.PerPage {
break
}
}
return allBuilds, nil
}
func (c *ListCmd) getBuildsByPipeline(ctx context.Context, f *factory.Factory, org string, listOpts *buildkite.BuildsListOptions) ([]buildkite.Build, error) {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
)
pipeline, err := pipelineRes.Resolve(ctx)
if err != nil {
return nil, err
}
builds, _, err := f.RestAPIClient.Builds.ListByPipeline(ctx, org, pipeline.Name, listOpts)
return builds, err
}
func (c *ListCmd) applyClientSideFilters(builds []buildkite.Build) ([]buildkite.Build, error) {
if c.Duration == "" && c.Message == "" {
return builds, nil
}
var durationOp string
var durationThreshold time.Duration
if c.Duration != "" {
durationOp = ">="
durationStr := c.Duration
switch {
case strings.HasPrefix(c.Duration, "<"):
durationOp = "<"
durationStr = c.Duration[1:]
case strings.HasPrefix(c.Duration, ">"):
durationOp = ">"
durationStr = c.Duration[1:]
}
d, err := time.ParseDuration(durationStr)
if err != nil {
return nil, fmt.Errorf("invalid duration format: %w", err)
}
durationThreshold = d
}
var messageFilter string
if c.Message != "" {
messageFilter = strings.ToLower(c.Message)
}
var result []buildkite.Build
for _, build := range builds {
if c.Duration != "" {
if build.StartedAt == nil {
continue
}
var elapsed time.Duration
if build.FinishedAt != nil {
elapsed = build.FinishedAt.Sub(build.StartedAt.Time)
} else {
elapsed = time.Since(build.StartedAt.Time)
}
switch durationOp {
case "<":
if elapsed >= durationThreshold {
continue
}
case ">":
if elapsed <= durationThreshold {
continue
}
default:
if elapsed < durationThreshold {
continue
}
}
}
if messageFilter != "" {
if !strings.Contains(strings.ToLower(build.Message), messageFilter) {
continue
}
}
result = append(result, build)
}
return result, nil
}
func isValidEmail(s string) bool {
_, err := mail.ParseAddress(s)
return err == nil
}
func resolveCreatorEmailToUserID(ctx context.Context, f *factory.Factory, email string) (string, error) {
org := f.Config.OrganizationSlug()
resp, err := graphql.FindUserByEmail(ctx, f.GraphQLClient, org, email)
if err != nil {
return "", fmt.Errorf("failed to query user by email: %w", err)
}
if resp.Organization == nil || resp.Organization.Members == nil || len(resp.Organization.Members.Edges) == 0 {
return "", fmt.Errorf("no user found with email: %s", email)
}
member := resp.Organization.Members.Edges[0].Node
if member == nil {
return "", fmt.Errorf("invalid user data for email: %s", email)
}
// Decode GraphQL ID and extract UUID
decoded, err := base64.StdEncoding.DecodeString(member.User.Id)
if err != nil {
return "", fmt.Errorf("failed to decode user ID: %w", err)
}
if userUUID, found := strings.CutPrefix(string(decoded), "User---"); found {
return userUUID, nil
}
return "", fmt.Errorf("unexpected user ID format")
}
func displayBuilds(builds []buildkite.Build, format output.Format, writer io.Writer) error {
if format != output.FormatText {
return output.Write(writer, builds, format)
}
const (
maxMessageLength = 22
truncatedLength = 19
timeFormat = "2006-01-02T15:04:05Z"
)
var rows [][]string
for _, build := range builds {
message := build.Message
if len(message) > maxMessageLength {
message = message[:truncatedLength] + "..."
}
startedAt := "-"
if build.StartedAt != nil {
startedAt = build.StartedAt.Format(timeFormat)
}
finishedAt := "-"
duration := "-"
if build.FinishedAt != nil {
finishedAt = build.FinishedAt.Format(timeFormat)
if build.StartedAt != nil {
dur := build.FinishedAt.Sub(build.StartedAt.Time)
duration = formatDuration(dur)
}
} else if build.StartedAt != nil {
dur := time.Since(build.StartedAt.Time)
duration = formatDuration(dur) + " (running)"
}
rows = append(rows, []string{
fmt.Sprintf("%d", build.Number),
build.State,
message,
startedAt,
finishedAt,
duration,
build.WebURL,
})
}
headers := []string{"Number", "State", "Message", "Started (UTC)", "Finished (UTC)", "Duration", "URL"}
table := output.Table(headers, rows, map[string]string{
"number": "bold",
"state": "bold",
"message": "italic",
"started (utc)": "dim",
"finished (utc)": "dim",
"duration": "bold",
"url": "dim",
})
fmt.Fprint(writer, table)
return nil
}
func formatDuration(d time.Duration) string {
if d < time.Minute {
return fmt.Sprintf("%.0fs", d.Seconds())
}
if d < time.Hour {
minutes := d / time.Minute
seconds := (d % time.Minute) / time.Second
return fmt.Sprintf("%dm%ds", minutes, seconds)
}
hours := d / time.Hour
minutes := (d % time.Hour) / time.Minute
return fmt.Sprintf("%dh%dm", hours, minutes)
}
================================================
FILE: cmd/build/list_test.go
================================================
package build
import (
"bytes"
"strings"
"testing"
"time"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type buildListOptions struct {
duration string
message string
}
func applyClientSideFilters(builds []buildkite.Build, opts buildListOptions) ([]buildkite.Build, error) {
cmd := &ListCmd{
Duration: opts.duration,
Message: opts.message,
}
return cmd.applyClientSideFilters(builds)
}
func TestBuildListOptions_MetaData(t *testing.T) {
cmd := &ListCmd{
MetaData: map[string]string{
"env": "production",
"deploy": "true",
},
}
opts, err := cmd.buildListOptions()
if err != nil {
t.Fatalf("buildListOptions failed: %v", err)
}
if len(opts.MetaData.MetaData) != 2 {
t.Errorf("Expected 2 meta-data filters, got %d", len(opts.MetaData.MetaData))
}
if opts.MetaData.MetaData["env"] != "production" {
t.Errorf("Expected env=production, got env=%s", opts.MetaData.MetaData["env"])
}
if opts.MetaData.MetaData["deploy"] != "true" {
t.Errorf("Expected deploy=true, got deploy=%s", opts.MetaData.MetaData["deploy"])
}
}
func TestBuildListOptions_EmptyMetaData(t *testing.T) {
cmd := &ListCmd{}
opts, err := cmd.buildListOptions()
if err != nil {
t.Fatalf("buildListOptions failed: %v", err)
}
if len(opts.MetaData.MetaData) != 0 {
t.Errorf("Expected empty meta-data, got %d entries", len(opts.MetaData.MetaData))
}
}
func TestDisplayBuilds_EmptyJSON(t *testing.T) {
var buf bytes.Buffer
err := displayBuilds([]buildkite.Build{}, output.FormatJSON, &buf)
if err != nil {
t.Fatalf("displayBuilds failed: %v", err)
}
got := strings.TrimSpace(buf.String())
if got != "[]" {
t.Errorf("Expected empty JSON array '[]', got %q", got)
}
}
func TestDisplayBuilds_EmptyYAML(t *testing.T) {
var buf bytes.Buffer
err := displayBuilds([]buildkite.Build{}, output.FormatYAML, &buf)
if err != nil {
t.Fatalf("displayBuilds failed: %v", err)
}
got := strings.TrimSpace(buf.String())
if got != "[]" {
t.Errorf("Expected empty YAML array '[]', got %q", got)
}
}
func TestFilterBuilds(t *testing.T) {
now := time.Now()
builds := []buildkite.Build{
{
Number: 1,
Message: "Fast build",
StartedAt: &buildkite.Timestamp{Time: now.Add(-5 * time.Minute)},
FinishedAt: &buildkite.Timestamp{Time: now.Add(-4 * time.Minute)}, // 1 minute
},
{
Number: 2,
Message: "Long build",
StartedAt: &buildkite.Timestamp{Time: now.Add(-30 * time.Minute)},
FinishedAt: &buildkite.Timestamp{Time: now.Add(-10 * time.Minute)}, // 20 minutes
},
}
opts := buildListOptions{duration: "10m"}
filtered, err := applyClientSideFilters(builds, opts)
if err != nil {
t.Fatalf("applyClientSideFilters failed: %v", err)
}
if len(filtered) != 1 {
t.Errorf("Expected 1 build >= 10m, got %d", len(filtered))
}
opts = buildListOptions{message: "Fast"}
filtered, err = applyClientSideFilters(builds, opts)
if err != nil {
t.Fatalf("applyClientSideFilters failed: %v", err)
}
if len(filtered) != 1 {
t.Errorf("Expected 1 build with 'Fast', got %d", len(filtered))
}
}
================================================
FILE: cmd/build/rebuild.go
================================================
package build
import (
"context"
"fmt"
"github.com/alecthomas/kong"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/build/resolver/options"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/internal/util"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type RebuildCmd struct {
BuildNumber string `arg:"" optional:"" help:"Build number to rebuild (omit for most recent build)"`
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Branch string `help:"Filter builds to this branch." short:"b"`
User string `help:"Filter builds to this user. You can use name or email." short:"u" xor:"userfilter"`
Mine bool `help:"Filter builds to only my user." short:"m" xor:"userfilter"`
Web bool `help:"Open the build in a web browser after it has been created." short:"w"`
}
func (c *RebuildCmd) Help() string {
return `
Examples:
# Rebuild a specific build by number
$ bk build rebuild 123
# Rebuild most recent build
$ bk build rebuild
# Rebuild and open in browser
$ bk build rebuild 123 --web
# Rebuild most recent build on a branch
$ bk build rebuild -b main
# Rebuild most recent build by a user
$ bk build rebuild -u alice
# Rebuild most recent build by yourself
$ bk build rebuild --mine`
}
func (c *RebuildCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
// we find the pipeline based on the following rules:
// 1. an explicit flag is passed
// 2. a configured pipeline for this directory
// 3. find pipelines matching the current repository from the API
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
// we resolve a build based on the following rules:
// 1. an optional argument
// 2. resolve from API using some context
// a. filter by branch if --branch or use current repo
// b. filter by user if --user or --mine given
optionsResolver := options.AggregateResolver{
options.ResolveBranchFromFlag(c.Branch),
options.ResolveBranchFromRepository(f.GitRepository),
}.WithResolverWhen(
c.User != "",
options.ResolveUserFromFlag(c.User),
).WithResolverWhen(
c.Mine || c.User == "",
options.ResolveCurrentUser(ctx, f),
)
args := []string{}
if c.BuildNumber != "" {
args = []string{c.BuildNumber}
}
buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
buildResolver.ResolveBuildWithOpts(f, pipelineRes.Resolve, optionsResolver...),
)
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
if bld == nil {
fmt.Println("No build found.")
return nil
}
return rebuild(ctx, bld.Organization, bld.Pipeline, fmt.Sprint(bld.BuildNumber), c.Web, f)
}
func rebuild(ctx context.Context, org string, pipeline string, buildId string, web bool, f *factory.Factory) error {
var build buildkite.Build
if err := bkIO.SpinWhile(f, fmt.Sprintf("Rerunning build #%s for pipeline %s", buildId, pipeline), func() error {
var apiErr error
build, apiErr = f.RestAPIClient.Builds.Rebuild(ctx, org, pipeline, buildId)
return apiErr
}); err != nil {
return err
}
fmt.Printf("%s\n", renderResult(fmt.Sprintf("Build created: %s", build.WebURL)))
return util.OpenInWebBrowser(web, build.WebURL)
}
================================================
FILE: cmd/build/view.go
================================================
package build
import (
"context"
"fmt"
"os"
"sync"
"github.com/alecthomas/kong"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/build/resolver/options"
"github.com/buildkite/cli/v3/internal/build/view"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
"github.com/pkg/browser"
)
type ViewCmd struct {
BuildNumber string `arg:"" optional:"" help:"Build number to view (omit for most recent build)"`
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Branch string `help:"Filter builds to this branch." short:"b"`
User string `help:"Filter builds to this user. You can use name or email." short:"u" xor:"userfilter"`
Mine bool `help:"Filter builds to only my user." xor:"userfilter"`
JobStates []string `help:"Filter jobs by state. Valid states: running, scheduled, passed, failed, canceled, skipped, not_run, broken." short:"s" sep:","`
Web bool `help:"Open the build in a web browser." short:"w"`
output.OutputFlags
}
func (c *ViewCmd) Help() string {
return `You can pass an optional build number to view. If omitted, the most recent build on the current branch will be resolved.
Examples:
# By default, the most recent build for the current branch is shown
$ bk build view
# If not inside a repository or to use a specific pipeline, pass -p
$ bk build view -p monolith
# To view a specific build
$ bk build view 429
# Add -w to any command to open the build in your web browser instead
$ bk build view -w 429
# To view the most recent build on feature-x branch
$ bk build view -b feature-y
# You can filter by a user name or id
$ bk build view -u "alice"
# A shortcut to view your builds is --mine
$ bk build view --mine
# Filter to only show failed and broken jobs
$ bk build view -s failed,broken
# You can combine most of these flags
# To view most recent build by greg on the deploy-pipeline
$ bk build view -p deploy-pipeline -u "greg"`
}
func (c *ViewCmd) buildGetOptions() *buildkite.BuildGetOptions {
if len(c.JobStates) > 0 {
return &buildkite.BuildGetOptions{JobStates: c.JobStates}
}
return nil
}
func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx := context.Background()
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
var opts view.ViewOptions
opts.Pipeline = c.Pipeline
opts.Web = c.Web
// Resolve pipeline first
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(opts.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
// Resolve build options
optionsResolver := options.AggregateResolver{
options.ResolveBranchFromFlag(c.Branch),
options.ResolveBranchFromRepository(f.GitRepository),
}.WithResolverWhen(
c.User != "",
options.ResolveUserFromFlag(c.User),
).WithResolverWhen(
c.Mine || c.User == "",
options.ResolveCurrentUser(ctx, f),
)
// Resolve build
args := []string{}
if c.BuildNumber != "" {
args = []string{c.BuildNumber}
}
buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
buildResolver.ResolveBuildWithOpts(f, pipelineRes.Resolve, optionsResolver...),
)
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
if bld == nil {
return output.WriteTextOrStructured(os.Stdout, format, nil, "No build found.")
}
opts.Organization = bld.Organization
opts.Pipeline = bld.Pipeline
opts.BuildNumber = bld.BuildNumber
if err := opts.Validate(); err != nil {
return err
}
if opts.Web {
buildURL := fmt.Sprintf("https://buildkite.com/%s/%s/builds/%d",
opts.Organization, opts.Pipeline, opts.BuildNumber)
fmt.Printf("Opening %s in your browser\n", buildURL)
return browser.OpenURL(buildURL)
}
var build buildkite.Build
var artifacts []buildkite.Artifact
var annotations []buildkite.Annotation
var wg sync.WaitGroup
var mu sync.Mutex
if err = bkIO.SpinWhile(f, "Loading build information", func() error {
var fetchErr error
wg.Add(3)
go func() {
defer wg.Done()
var apiErr error
build, _, apiErr = f.RestAPIClient.Builds.Get(
ctx,
opts.Organization,
opts.Pipeline,
fmt.Sprint(opts.BuildNumber),
c.buildGetOptions(),
)
if apiErr != nil {
mu.Lock()
fetchErr = apiErr
mu.Unlock()
}
}()
go func() {
defer wg.Done()
var apiErr error
artifacts, _, apiErr = f.RestAPIClient.Artifacts.ListByBuild(
ctx,
opts.Organization,
opts.Pipeline,
fmt.Sprint(opts.BuildNumber),
nil,
)
if apiErr != nil {
mu.Lock()
fetchErr = apiErr
mu.Unlock()
}
}()
go func() {
defer wg.Done()
var apiErr error
annotations, _, apiErr = f.RestAPIClient.Annotations.ListByBuild(
ctx,
opts.Organization,
opts.Pipeline,
fmt.Sprint(opts.BuildNumber),
nil,
)
if apiErr != nil {
mu.Lock()
fetchErr = apiErr
mu.Unlock()
}
}()
wg.Wait()
return fetchErr
}); err != nil {
return err
}
// Create a combined view for JSON/YAML output
type BuildOutput struct {
buildkite.Build
Artifacts []buildkite.Artifact `json:"artifacts,omitempty"`
Annotations []buildkite.Annotation `json:"annotations,omitempty"`
}
buildOutput := output.Viewable[BuildOutput]{
Data: BuildOutput{
Build: build,
Artifacts: artifacts,
Annotations: annotations,
},
Render: func(b BuildOutput) string {
return view.NewBuildView(&b.Build, b.Artifacts, b.Annotations, opts.Organization, opts.Pipeline).Render()
},
}
if format == output.FormatText {
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() { _ = cleanup() }()
_, err := fmt.Fprint(writer, buildOutput.TextOutput())
return err
}
return output.Write(os.Stdout, buildOutput, format)
}
================================================
FILE: cmd/build/view_test.go
================================================
package build
import (
"testing"
)
func TestViewCmd_BuildGetOptions_WithJobStates(t *testing.T) {
cmd := &ViewCmd{
JobStates: []string{"failed", "broken"},
}
opts := cmd.buildGetOptions()
if opts == nil {
t.Fatal("Expected non-nil BuildGetOptions")
return
}
if len(opts.JobStates) != 2 {
t.Fatalf("Expected 2 job states, got %d", len(opts.JobStates))
}
if opts.JobStates[0] != "failed" {
t.Errorf("Expected first state to be 'failed', got %q", opts.JobStates[0])
}
if opts.JobStates[1] != "broken" {
t.Errorf("Expected second state to be 'broken', got %q", opts.JobStates[1])
}
}
func TestViewCmd_BuildGetOptions_Empty(t *testing.T) {
cmd := &ViewCmd{}
opts := cmd.buildGetOptions()
if opts != nil {
t.Errorf("Expected nil BuildGetOptions when no job states, got %+v", opts)
}
}
func TestViewCmd_BuildGetOptions_SingleState(t *testing.T) {
cmd := &ViewCmd{
JobStates: []string{"running"},
}
opts := cmd.buildGetOptions()
if opts == nil {
t.Fatal("Expected non-nil BuildGetOptions")
return
}
if len(opts.JobStates) != 1 {
t.Fatalf("Expected 1 job state, got %d", len(opts.JobStates))
}
if opts.JobStates[0] != "running" {
t.Errorf("Expected state to be 'running', got %q", opts.JobStates[0])
}
}
================================================
FILE: cmd/build/watch.go
================================================
package build
import (
"context"
"errors"
"fmt"
"os"
"time"
"github.com/alecthomas/kong"
buildResolver "github.com/buildkite/cli/v3/internal/build/resolver"
"github.com/buildkite/cli/v3/internal/build/resolver/options"
"github.com/buildkite/cli/v3/internal/build/view/shared"
"github.com/buildkite/cli/v3/internal/build/watch"
"github.com/buildkite/cli/v3/internal/cli"
pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver"
"github.com/buildkite/cli/v3/internal/validation"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
pkgValidation "github.com/buildkite/cli/v3/pkg/cmd/validation"
buildkite "github.com/buildkite/go-buildkite/v4"
"github.com/mattn/go-isatty"
)
type WatchCmd struct {
BuildNumber string `arg:"" optional:"" help:"Build number to watch (omit for most recent build)"`
Pipeline string `help:"The pipeline to use. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}." short:"p"`
Branch string `help:"The branch to watch builds for." short:"b"`
Interval int `help:"Polling interval in seconds" default:"1"`
}
func (c *WatchCmd) Help() string {
return `
Examples:
# Watch the most recent build for the current branch
$ bk build watch --pipeline my-pipeline
# Watch a specific build
$ bk build watch 429 --pipeline my-pipeline
# Watch the most recent build on a specific branch
$ bk build watch -b feature-x --pipeline my-pipeline
# Watch a build on a specific pipeline
$ bk build watch --pipeline my-pipeline
# Set a custom polling interval (in seconds)
$ bk build watch --interval 5 --pipeline my-pipeline`
}
func (c *WatchCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := pkgValidation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
tty := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
// Validate command options
v := validation.New()
v.AddRule("Interval", validation.MinValue(1))
if c.Pipeline != "" {
v.AddRule("Pipeline", validation.Slug)
}
if err := v.Validate(map[string]interface{}{
"Pipeline": c.Pipeline,
"Interval": c.Interval,
}); err != nil {
return err
}
ctx := context.Background()
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(c.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOneWithFactory(f)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOneWithFactory(f))),
)
optionsResolver := options.AggregateResolver{
options.ResolveBranchFromFlag(c.Branch),
options.ResolveBranchFromRepository(f.GitRepository),
}
args := []string{}
if c.BuildNumber != "" {
args = []string{c.BuildNumber}
}
buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
buildResolver.ResolveBuildWithOpts(f, pipelineRes.Resolve, optionsResolver...),
)
bld, err := buildRes.Resolve(ctx)
if err != nil {
return err
}
if bld == nil {
return fmt.Errorf("no running builds found")
}
fmt.Printf("Watching build %d on %s/%s\n", bld.BuildNumber, bld.Organization, bld.Pipeline)
interval := time.Duration(c.Interval) * time.Second
_, err = watch.WatchBuild(ctx, f.RestAPIClient, bld.Organization, bld.Pipeline, bld.BuildNumber, interval, func(b buildkite.Build) error {
summary := shared.BuildSummaryWithJobs(&b, bld.Organization, bld.Pipeline)
if tty {
fmt.Print("\033[H\033[2J")
fmt.Printf("%s\n", summary)
} else {
fmt.Printf("[%s] %s\n", time.Now().Format(time.RFC3339), summary)
}
return nil
})
if errors.Is(err, context.Canceled) {
return nil
}
return err
}
================================================
FILE: cmd/cluster/cluster_test.go
================================================
package cluster
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
buildkite "github.com/buildkite/go-buildkite/v4"
)
func TestListClusters(t *testing.T) {
t.Parallel()
t.Run("fetches clusters through API", func(t *testing.T) {
t.Parallel()
clusters := []buildkite.Cluster{
{
ID: "cluster-1",
Name: "Production",
Description: "Production cluster",
},
{
ID: "cluster-2",
Name: "Staging",
Description: "Staging cluster",
},
}
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("expected GET, got %s", r.Method)
}
if !strings.Contains(r.URL.Path, "/clusters") {
t.Errorf("unexpected path: %s", r.URL.Path)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(clusters)
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
result, _, err := client.Clusters.List(context.Background(), "test-org", nil)
if err != nil {
t.Fatal(err)
}
if len(result) != 2 {
t.Fatalf("expected 2 clusters, got %d", len(result))
}
if result[0].Name != "Production" {
t.Errorf("expected name 'Production', got %q", result[0].Name)
}
if result[1].ID != "cluster-2" {
t.Errorf("expected ID 'cluster-2', got %q", result[1].ID)
}
})
t.Run("empty result returns empty slice", func(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode([]buildkite.Cluster{})
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
result, _, err := client.Clusters.List(context.Background(), "test-org", nil)
if err != nil {
t.Fatal(err)
}
if len(result) != 0 {
t.Errorf("expected 0 clusters, got %d", len(result))
}
})
}
func TestGetCluster(t *testing.T) {
t.Parallel()
cluster := buildkite.Cluster{
ID: "cluster-1",
Name: "Production",
Description: "Production cluster",
Color: "#FF0000",
Emoji: ":rocket:",
}
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("expected GET, got %s", r.Method)
}
if !strings.Contains(r.URL.Path, "/clusters/cluster-1") {
t.Errorf("unexpected path: %s", r.URL.Path)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(cluster)
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
result, _, err := client.Clusters.Get(context.Background(), "test-org", "cluster-1")
if err != nil {
t.Fatal(err)
}
if result.Name != "Production" {
t.Errorf("expected name 'Production', got %q", result.Name)
}
if result.Color != "#FF0000" {
t.Errorf("expected color '#FF0000', got %q", result.Color)
}
}
func TestCreateCluster(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Errorf("expected POST, got %s", r.Method)
}
if !strings.Contains(r.URL.Path, "/clusters") {
t.Errorf("unexpected path: %s", r.URL.Path)
}
var input buildkite.ClusterCreate
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
t.Fatal(err)
}
if input.Name != "New Cluster" {
t.Errorf("expected name 'New Cluster', got %q", input.Name)
}
if input.Description != "A brand new cluster" {
t.Errorf("expected description 'A brand new cluster', got %q", input.Description)
}
if input.Color != "#FF0000" {
t.Errorf("expected color '#FF0000', got %q", input.Color)
}
if input.Emoji != ":rocket:" {
t.Errorf("expected emoji ':rocket:', got %q", input.Emoji)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(buildkite.Cluster{
ID: "new-cluster-id",
Name: input.Name,
Description: input.Description,
Color: input.Color,
Emoji: input.Emoji,
})
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
result, _, err := client.Clusters.Create(context.Background(), "test-org", buildkite.ClusterCreate{
Name: "New Cluster",
Description: "A brand new cluster",
Color: "#FF0000",
Emoji: ":rocket:",
})
if err != nil {
t.Fatal(err)
}
if result.ID != "new-cluster-id" {
t.Errorf("expected ID 'new-cluster-id', got %q", result.ID)
}
if result.Name != "New Cluster" {
t.Errorf("expected name 'New Cluster', got %q", result.Name)
}
}
func TestUpdateCluster(t *testing.T) {
t.Parallel()
t.Run("updates cluster metadata", func(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PATCH" {
t.Errorf("expected PATCH, got %s", r.Method)
}
if !strings.Contains(r.URL.Path, "/clusters/cluster-1") {
t.Errorf("unexpected path: %s", r.URL.Path)
}
var input buildkite.ClusterUpdate
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
t.Fatal(err)
}
if input.Name != "Updated Name" {
t.Errorf("expected name 'Updated Name', got %q", input.Name)
}
if input.Description != "Updated description" {
t.Errorf("expected description 'Updated description', got %q", input.Description)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(buildkite.Cluster{
ID: "cluster-1",
Name: input.Name,
Description: input.Description,
})
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
result, _, err := client.Clusters.Update(context.Background(), "test-org", "cluster-1", buildkite.ClusterUpdate{
Name: "Updated Name",
Description: "Updated description",
})
if err != nil {
t.Fatal(err)
}
if result.Name != "Updated Name" {
t.Errorf("expected name 'Updated Name', got %q", result.Name)
}
if result.Description != "Updated description" {
t.Errorf("expected description 'Updated description', got %q", result.Description)
}
})
t.Run("updates default queue", func(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PATCH" {
t.Errorf("expected PATCH, got %s", r.Method)
}
var input buildkite.ClusterUpdate
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
t.Fatal(err)
}
if input.DefaultQueueID != "queue-123" {
t.Errorf("expected default_queue_id 'queue-123', got %q", input.DefaultQueueID)
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(buildkite.Cluster{
ID: "cluster-1",
Name: "Production",
DefaultQueueID: input.DefaultQueueID,
})
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
result, _, err := client.Clusters.Update(context.Background(), "test-org", "cluster-1", buildkite.ClusterUpdate{
DefaultQueueID: "queue-123",
})
if err != nil {
t.Fatal(err)
}
if result.DefaultQueueID != "queue-123" {
t.Errorf("expected default_queue_id 'queue-123', got %q", result.DefaultQueueID)
}
})
}
func TestDeleteCluster(t *testing.T) {
t.Parallel()
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("expected DELETE, got %s", r.Method)
}
if !strings.Contains(r.URL.Path, "/clusters/cluster-to-delete") {
t.Errorf("unexpected path: %s", r.URL.Path)
}
w.WriteHeader(http.StatusNoContent)
}))
defer s.Close()
client, err := buildkite.NewOpts(buildkite.WithBaseURL(s.URL))
if err != nil {
t.Fatal(err)
}
_, err = client.Clusters.Delete(context.Background(), "test-org", "cluster-to-delete")
if err != nil {
t.Fatal(err)
}
}
func TestUpdateCmdValidate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
cmd UpdateCmd
wantErr bool
}{
{
name: "no flags set",
cmd: UpdateCmd{ClusterUUID: "cluster-1"},
wantErr: true,
},
{
name: "only name",
cmd: UpdateCmd{ClusterUUID: "cluster-1", Name: "New Name"},
wantErr: false,
},
{
name: "only description",
cmd: UpdateCmd{ClusterUUID: "cluster-1", Description: "New description"},
wantErr: false,
},
{
name: "only emoji",
cmd: UpdateCmd{ClusterUUID: "cluster-1", Emoji: ":rocket:"},
wantErr: false,
},
{
name: "only color",
cmd: UpdateCmd{ClusterUUID: "cluster-1", Color: "#FF0000"},
wantErr: false,
},
{
name: "only default-queue-id",
cmd: UpdateCmd{ClusterUUID: "cluster-1", DefaultQueueID: "queue-123"},
wantErr: false,
},
{
name: "multiple fields",
cmd: UpdateCmd{ClusterUUID: "cluster-1", Name: "New Name", Description: "New desc", Color: "#00FF00"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
err := tt.cmd.Validate()
if (err != nil) != tt.wantErr {
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestRenderClusterText(t *testing.T) {
t.Parallel()
ts := buildkite.Timestamp{}
cluster := buildkite.Cluster{
ID: "cluster-123",
GraphQLID: "graphql-123",
Name: "Production",
Description: "Production cluster",
Color: "#FF0000",
Emoji: ":rocket:",
WebURL: "https://buildkite.com/orgs/test-org/clusters/cluster-123",
CreatedBy: buildkite.ClusterCreator{
ID: "user-1",
Name: "Test User",
},
CreatedAt: &ts,
}
result := renderClusterText(cluster)
expectedStrings := []string{
"Viewing Production",
"cluster-123",
"Production cluster",
"#FF0000",
":rocket:",
"Test User",
}
for _, expected := range expectedStrings {
if !strings.Contains(result, expected) {
t.Errorf("expected output to contain %q, got:\n%s", expected, result)
}
}
}
================================================
FILE: cmd/cluster/create.go
================================================
package cluster
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type CreateCmd struct {
Name string `help:"The name of the cluster" required:""`
Description string `help:"A description of the cluster" optional:""`
Emoji string `help:"An emoji for the cluster (e.g. :rocket:)" optional:""`
Color string `help:"A color hex code for the cluster (e.g. #FF0000)" optional:""`
output.OutputFlags
}
func (c *CreateCmd) Help() string {
return `
Create a new cluster in the organization.
Examples:
# Create a cluster with just a name
$ bk cluster create --name "My Cluster"
# Create a cluster with all fields
$ bk cluster create --name "My Cluster" --description "Runs production workloads" --emoji :rocket: --color "#FF0000"
# Create a cluster and output as JSON
$ bk cluster create --name "My Cluster" -o json
`
}
func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
input := buildkite.ClusterCreate{
Name: c.Name,
Description: c.Description,
Emoji: c.Emoji,
Color: c.Color,
}
var cluster buildkite.Cluster
if err = bkIO.SpinWhile(f, "Creating cluster", func() error {
var apiErr error
cluster, _, apiErr = f.RestAPIClient.Clusters.Create(ctx, f.Config.OrganizationSlug(), input)
return apiErr
}); err != nil {
return fmt.Errorf("error creating cluster: %v", err)
}
clusterView := output.Viewable[buildkite.Cluster]{
Data: cluster,
Render: renderClusterText,
}
if format != output.FormatText {
return output.Write(os.Stdout, clusterView, format)
}
fmt.Fprintf(os.Stdout, "Cluster %s created successfully\n\n", cluster.Name)
return output.Write(os.Stdout, clusterView, format)
}
================================================
FILE: cmd/cluster/delete.go
================================================
package cluster
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
)
type DeleteCmd struct {
ClusterUUID string `arg:"" help:"Cluster UUID to delete" name:"cluster-uuid"`
}
func (c *DeleteCmd) Help() string {
return `
Delete a cluster from the organization.
You will be prompted to confirm deletion unless --yes is set.
Examples:
# Delete a cluster (with confirmation prompt)
$ bk cluster delete my-cluster-uuid
# Delete a cluster without confirmation
$ bk cluster delete my-cluster-uuid --yes
`
}
func (c *DeleteCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
confirmed, err := bkIO.Confirm(f, fmt.Sprintf("Are you sure you want to delete cluster %s?", c.ClusterUUID))
if err != nil {
return err
}
if !confirmed {
fmt.Fprintln(os.Stderr, "Deletion cancelled.")
return nil
}
if err = bkIO.SpinWhile(f, "Deleting cluster", func() error {
_, err = f.RestAPIClient.Clusters.Delete(ctx, f.Config.OrganizationSlug(), c.ClusterUUID)
return err
}); err != nil {
return fmt.Errorf("error deleting cluster: %v", err)
}
fmt.Fprintln(os.Stderr, "Cluster deleted successfully.")
return nil
}
================================================
FILE: cmd/cluster/list.go
================================================
package cluster
import (
"context"
"errors"
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
"github.com/buildkite/cli/v3/internal/cluster"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type ListCmd struct {
output.OutputFlags
}
func (c *ListCmd) Help() string {
return `
List the clusters for an organization.
Examples:
# List all clusters
$ bk cluster list
# List clusters in JSON format
$ bk cluster list -o json
`
}
func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
clusters, err := listClusters(ctx, f)
if err != nil {
return err
}
if format != output.FormatText {
return output.Write(os.Stdout, clusters, format)
}
summary := cluster.ClusterViewTable(clusters...)
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() { _ = cleanup() }()
fmt.Fprintf(writer, "%v\n", summary)
return nil
}
func listClusters(ctx context.Context, f *factory.Factory) ([]buildkite.Cluster, error) {
var clusters []buildkite.Cluster
var err error
if err = bkIO.SpinWhile(f, "Loading clusters information", func() error {
var apiErr error
clusters, _, apiErr = f.RestAPIClient.Clusters.List(ctx, f.Config.OrganizationSlug(), nil)
return apiErr
}); err != nil {
return nil, fmt.Errorf("error fetching cluster list: %v", err)
}
if len(clusters) < 1 {
return nil, errors.New("no clusters found in organization")
}
clusterList := make([]buildkite.Cluster, len(clusters))
var wg sync.WaitGroup
errChan := make(chan error, len(clusters))
for i, c := range clusters {
wg.Add(1)
go func(i int, c buildkite.Cluster) {
defer wg.Done()
clusterList[i] = buildkite.Cluster{
Color: c.Color,
CreatedAt: c.CreatedAt,
CreatedBy: c.CreatedBy,
DefaultQueueID: c.DefaultQueueID,
DefaultQueueURL: c.DefaultQueueURL,
Description: c.Description,
Emoji: c.Emoji,
GraphQLID: c.GraphQLID,
ID: c.ID,
Name: c.Name,
QueuesURL: c.QueuesURL,
URL: c.URL,
WebURL: c.WebURL,
}
}(i, c)
}
go func() {
wg.Wait()
close(errChan)
}()
for err := range errChan {
if err != nil {
return nil, err
}
}
return clusterList, nil
}
================================================
FILE: cmd/cluster/update.go
================================================
package cluster
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type UpdateCmd struct {
ClusterUUID string `arg:"" help:"Cluster UUID to update" name:"cluster-uuid"`
Name string `help:"New name for the cluster" optional:""`
Description string `help:"New description for the cluster" optional:""`
Emoji string `help:"New emoji for the cluster (e.g. :rocket:)" optional:""`
Color string `help:"New color hex code for the cluster (e.g. #FF0000)" optional:""`
DefaultQueueID string `help:"UUID of the queue to set as the default" optional:"" name:"default-queue-id"`
output.OutputFlags
}
func (c *UpdateCmd) Help() string {
return `
Update a cluster's settings.
At least one of --name, --description, --emoji, --color, or --default-queue-id must be provided.
Examples:
# Update a cluster's name
$ bk cluster update my-cluster-uuid --name "New Name"
# Update description and color
$ bk cluster update my-cluster-uuid --description "Updated description" --color "#00FF00"
# Set the default queue
$ bk cluster update my-cluster-uuid --default-queue-id my-queue-uuid
# Output the updated cluster as JSON
$ bk cluster update my-cluster-uuid --name "New Name" -o json
`
}
func (c *UpdateCmd) Validate() error {
if c.Name == "" && c.Description == "" && c.Emoji == "" && c.Color == "" && c.DefaultQueueID == "" {
return fmt.Errorf("at least one of --name, --description, --emoji, --color, or --default-queue-id must be provided")
}
return nil
}
func (c *UpdateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
input := buildkite.ClusterUpdate{
Name: c.Name,
Description: c.Description,
Emoji: c.Emoji,
Color: c.Color,
DefaultQueueID: c.DefaultQueueID,
}
var cluster buildkite.Cluster
if err = bkIO.SpinWhile(f, "Updating cluster", func() error {
var apiErr error
cluster, _, apiErr = f.RestAPIClient.Clusters.Update(ctx, f.Config.OrganizationSlug(), c.ClusterUUID, input)
return apiErr
}); err != nil {
return fmt.Errorf("error updating cluster: %v", err)
}
clusterView := output.Viewable[buildkite.Cluster]{
Data: cluster,
Render: renderClusterText,
}
if format != output.FormatText {
return output.Write(os.Stdout, clusterView, format)
}
fmt.Fprintf(os.Stdout, "Cluster %s updated successfully\n\n", cluster.Name)
return output.Write(os.Stdout, clusterView, format)
}
================================================
FILE: cmd/cluster/view.go
================================================
package cluster
import (
"context"
"fmt"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/alecthomas/kong"
"github.com/buildkite/cli/v3/internal/cli"
bkIO "github.com/buildkite/cli/v3/internal/io"
"github.com/buildkite/cli/v3/pkg/cmd/factory"
"github.com/buildkite/cli/v3/pkg/cmd/validation"
"github.com/buildkite/cli/v3/pkg/output"
buildkite "github.com/buildkite/go-buildkite/v4"
)
type ViewCmd struct {
ClusterUUID string `arg:"" help:"Cluster UUID to view" name:"cluster-uuid"`
output.OutputFlags
}
func (c *ViewCmd) Help() string {
return `
It accepts cluster UUID.
Examples:
# View a cluster
$ bk cluster view my-cluster-uuid
# View cluster in JSON format
$ bk cluster view my-cluster-uuid -o json
`
}
func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
f, err := factory.New(factory.WithDebug(globals.EnableDebug()))
if err != nil {
return err
}
f.SkipConfirm = globals.SkipConfirmation()
f.NoInput = globals.DisableInput()
f.Quiet = globals.IsQuiet()
f.NoPager = f.NoPager || globals.DisablePager()
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
return err
}
format := output.ResolveFormat(c.Output, f.Config.OutputFormat())
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
var cluster buildkite.Cluster
if err = bkIO.SpinWhile(f, "Loading cluster information", func() error {
var apiErr error
cluster, _, apiErr = f.RestAPIClient.Clusters.Get(ctx, f.Config.OrganizationSlug(), c.ClusterUUID)
return apiErr
}); err != nil {
return err
}
clusterView := output.Viewable[buildkite.Cluster]{
Data: cluster,
Render: renderClusterText,
}
if format != output.FormatText {
return output.Write(os.Stdout, clusterView, format)
}
writer, cleanup := bkIO.Pager(f.NoPager, f.Config.Pager())
defer func() { _ = cleanup() }()
return output.Write(writer, clusterView, format)
}
func renderClusterText(c buildkite.Cluster) string {
rows := [][]string{
{"Description", output.ValueOrDash(c.Description)},
{"Color", output.ValueOrDash(c.Color)},
{"Emoji", output.ValueOrDash(c.Emoji)},
{"ID", output.ValueOrDash(c.ID)},
{"GraphQL ID", output.ValueOrDash(c.GraphQLID)},
{"Default Queue ID", output.ValueOrDash(c.DefaultQueueID)},
{"Web URL", output.ValueOrDash(c.WebURL)},
{"API URL", output.ValueOrDash(c.URL)},
{"Queues URL", output.ValueOrDash(c.QueuesURL)},
{"Queue URL", output.ValueOrDash(c.DefaultQueueURL)},
}
if c.CreatedBy.ID != "" {
rows = append(
rows,
[]string{"Created By Name", output.ValueOrDash(c.CreatedBy.Name)},
[]string{"Created By Email", output.ValueOrDash(c.CreatedBy.Email)},
[]string{"Created By ID", output.ValueOrDash(c.CreatedBy.ID)},
)
}
if c.CreatedAt != nil {
rows = append(rows, []string{"Created At", c.CreatedAt.Format(time.RFC3339)})
}
var sb strings.Builder
fmt.Fprintf(&sb, "Viewing %s\n\n", output.ValueOrDash(c.Name))
table := output.Table(
[]string{"Field", "Value"},
rows,
map[string]string{"field": "dim", "value": "italic"},
)
sb.WriteString(table)
return sb.String()
}
================================================
FILE: cmd/config/config.go
================================================
// Package config provides commands for managing CLI configuration
package config
import (
"fmt"
"slices"
"strconv"
"github.com/buildkite/cli/v3/internal/config"
)
// ConfigCmd is the root command for managing CLI configuration
type ConfigCmd struct {
List ListCmd `cmd:"" help:"List configuration values." aliases:"ls"`
Get GetCmd `cmd:"" help:"Get a configuration value."`
Set SetCmd `cmd:"" help:"Set a configuration value."`
Unset UnsetCmd `cmd:"" help:"Remove a configuration value."`
}
func (c ConfigCmd) Help() string {
return `Manage CLI configuration settings.
Configuration is stored in two locations:
User config: ~/.config/bk.yaml (global defaults)
Local config: .bk.yaml (repo-specific overrides)
Precedence: Environment variable > Local config > User config > Default
Examples:
$ bk config list # Show all config values
$ bk config get output_format # Get a specific value
$ bk config set output_format yaml # Set default output to YAML
$ bk config set no_pager true --local # Disable pager for this repo
$ bk config unset pager # Reset pager to default`
}
// ConfigKey represents a valid configuration key
type ConfigKey string
const (
KeySelectedOrg ConfigKey = "selected_org"
KeyOutputFormat ConfigKey = "output_format"
KeyNoPager ConfigKey = "no_pager"
KeyQuiet ConfigKey = "quiet"
KeyNoInput ConfigKey = "no_input"
KeyPager ConfigKey = "pager"
KeyTelemetry ConfigKey = "telemetry"
KeyExperiments C
gitextract_4e0fgwb8/ ├── .buildkite/ │ ├── hooks/ │ │ └── pre-command │ ├── pipeline.release.yml │ ├── pipeline.yml │ ├── release.sh │ ├── tag.sh │ └── upload-packages.sh ├── .dockerignore ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ ├── config.yml │ │ └── feature_request.yml │ └── pull_request_template.md ├── .gitignore ├── .golangci.yaml ├── .goreleaser.yaml ├── .graphqlrc.yml ├── AGENT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.md ├── README.md ├── cmd/ │ ├── agent/ │ │ ├── agent_test.go │ │ ├── install.go │ │ ├── list.go │ │ ├── list_test.go │ │ ├── pause.go │ │ ├── pause_test.go │ │ ├── resume.go │ │ ├── resume_test.go │ │ ├── run.go │ │ ├── stop.go │ │ ├── stop_test.go │ │ ├── util.go │ │ ├── view.go │ │ └── view_test.go │ ├── api/ │ │ ├── api.go │ │ └── api_test.go │ ├── artifacts/ │ │ ├── download.go │ │ └── list.go │ ├── auth/ │ │ ├── login.go │ │ ├── login_test.go │ │ ├── logout.go │ │ ├── status.go │ │ ├── switch.go │ │ ├── switch_test.go │ │ └── token.go │ ├── build/ │ │ ├── cancel.go │ │ ├── create.go │ │ ├── download.go │ │ ├── list.go │ │ ├── list_test.go │ │ ├── rebuild.go │ │ ├── view.go │ │ ├── view_test.go │ │ └── watch.go │ ├── cluster/ │ │ ├── cluster_test.go │ │ ├── create.go │ │ ├── delete.go │ │ ├── list.go │ │ ├── update.go │ │ └── view.go │ ├── config/ │ │ ├── config.go │ │ ├── config_test.go │ │ ├── get.go │ │ ├── list.go │ │ ├── set.go │ │ └── unset.go │ ├── configure/ │ │ ├── configure.go │ │ ├── configure_case_test.go │ │ └── configure_test.go │ ├── generate/ │ │ └── generate.go │ ├── init/ │ │ ├── init.go │ │ └── init_test.go │ ├── job/ │ │ ├── cancel.go │ │ ├── cancel_test.go │ │ ├── graphql/ │ │ │ ├── cancel.graphql │ │ │ ├── jobs.graphql │ │ │ ├── retry.graphql │ │ │ └── unblock.graphql │ │ ├── list.go │ │ ├── list_test.go │ │ ├── log.go │ │ ├── reprioritize.go │ │ ├── retry.go │ │ ├── unblock.go │ │ └── unblock_test.go │ ├── maintainer/ │ │ ├── create.go │ │ ├── delete.go │ │ ├── list.go │ │ └── maintainer_test.go │ ├── organization/ │ │ └── list.go │ ├── pipeline/ │ │ ├── convert.go │ │ ├── convert_test.go │ │ ├── copy.go │ │ ├── create.go │ │ ├── create_test.go │ │ ├── graphql/ │ │ │ └── create_webhook.graphql │ │ ├── list.go │ │ ├── validate.go │ │ ├── validate_test.go │ │ └── view.go │ ├── pkg/ │ │ ├── push.go │ │ └── push_test.go │ ├── preflight/ │ │ ├── cleanup_cmd.go │ │ ├── cleanup_cmd_test.go │ │ ├── event.go │ │ ├── event_test.go │ │ ├── job_presenter.go │ │ ├── job_presenter_test.go │ │ ├── preflight.go │ │ ├── preflight_test.go │ │ ├── render.go │ │ ├── render_test.go │ │ ├── result.go │ │ ├── result_test.go │ │ ├── test_presenter.go │ │ ├── test_presenter_test.go │ │ ├── tty.go │ │ └── tty_test.go │ ├── queue/ │ │ ├── create.go │ │ ├── delete.go │ │ ├── list.go │ │ ├── pause.go │ │ ├── queue_test.go │ │ ├── resume.go │ │ ├── update.go │ │ └── view.go │ ├── secret/ │ │ ├── create.go │ │ ├── delete.go │ │ ├── get.go │ │ ├── list.go │ │ ├── secret_test.go │ │ └── update.go │ ├── skill/ │ │ ├── skill.go │ │ └── skill_test.go │ ├── use/ │ │ └── use.go │ ├── user/ │ │ └── invite.go │ ├── version/ │ │ ├── update_check.go │ │ ├── update_check_test.go │ │ └── version.go │ └── whoami/ │ └── whoami.go ├── docs/ │ └── shell-prompt-integration.md ├── fixtures/ │ ├── build.json │ └── config/ │ ├── local.basic.yaml │ └── user.basic.yaml ├── genqlient.yaml ├── go.mod ├── go.sum ├── internal/ │ ├── agent/ │ │ ├── download.go │ │ ├── download_test.go │ │ ├── platform.go │ │ ├── platform_test.go │ │ ├── token.go │ │ └── token_test.go │ ├── annotation/ │ │ ├── annotation.go │ │ └── list.go │ ├── artifact/ │ │ ├── artifact.go │ │ └── view.go │ ├── build/ │ │ ├── build.go │ │ ├── resolver/ │ │ │ ├── cli.go │ │ │ ├── cli_test.go │ │ │ ├── options/ │ │ │ │ ├── options.go │ │ │ │ └── options_test.go │ │ │ ├── resolver.go │ │ │ ├── url.go │ │ │ └── with_options.go │ │ ├── state/ │ │ │ ├── state.go │ │ │ └── state_test.go │ │ ├── view/ │ │ │ ├── shared/ │ │ │ │ └── summary.go │ │ │ ├── view.go │ │ │ └── view_test.go │ │ └── watch/ │ │ ├── job.go │ │ ├── test_tracker.go │ │ ├── test_tracker_test.go │ │ ├── tracker.go │ │ ├── tracker_test.go │ │ ├── watch.go │ │ └── watch_test.go │ ├── cli/ │ │ └── context.go │ ├── cluster/ │ │ ├── list_queues.graphql │ │ ├── query.go │ │ └── view.go │ ├── config/ │ │ ├── config.go │ │ └── config_test.go │ ├── emoji/ │ │ ├── emoji.go │ │ └── emoji_test.go │ ├── errors/ │ │ ├── README.md │ │ ├── api.go │ │ ├── api_test.go │ │ ├── errors.go │ │ ├── errors_test.go │ │ ├── handler.go │ │ └── handler_test.go │ ├── graphql/ │ │ └── generated.go │ ├── http/ │ │ ├── README.md │ │ ├── client.go │ │ ├── client_test.go │ │ ├── ratelimit.go │ │ ├── ratelimit_test.go │ │ ├── refresh_transport.go │ │ └── refresh_transport_test.go │ ├── io/ │ │ ├── confirm.go │ │ ├── input.go │ │ ├── pager.go │ │ ├── pager_test.go │ │ ├── progress.go │ │ ├── progress_test.go │ │ ├── prompt.go │ │ ├── prompt_test.go │ │ ├── readline.go │ │ ├── spinner.go │ │ ├── spinner_test.go │ │ └── terminal.go │ ├── job/ │ │ └── view.go │ ├── organization/ │ │ └── organization.graphql │ ├── pipeline/ │ │ ├── pipeline.go │ │ └── resolver/ │ │ ├── cli.go │ │ ├── cli_test.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── flag.go │ │ ├── flag_test.go │ │ ├── picker.go │ │ ├── picker_test.go │ │ ├── repository.go │ │ ├── repository_test.go │ │ ├── resolver.go │ │ └── resolver_test.go │ ├── preflight/ │ │ ├── branch_build.go │ │ ├── branch_build_test.go │ │ ├── cleanup.go │ │ ├── cleanup_test.go │ │ ├── exit_policy.go │ │ ├── git.go │ │ ├── run_summary.go │ │ ├── run_summary_test.go │ │ ├── snapshot.go │ │ └── snapshot_test.go │ ├── secret/ │ │ └── view.go │ ├── user/ │ │ └── user.graphql │ ├── util/ │ │ └── util.go │ └── validation/ │ ├── errors.go │ ├── rule.go │ ├── validator.go │ └── validator_test.go ├── lefthook.yml ├── main.go ├── main_test.go ├── mise.toml ├── pkg/ │ ├── analytics/ │ │ ├── analytics.go │ │ └── logger.go │ ├── cmd/ │ │ ├── factory/ │ │ │ ├── factory.go │ │ │ └── factory_test.go │ │ └── validation/ │ │ ├── config.go │ │ └── config_test.go │ ├── keyring/ │ │ ├── keyring.go │ │ └── keyring_test.go │ ├── oauth/ │ │ ├── oauth.go │ │ ├── oauth_test.go │ │ └── refresh_test.go │ └── output/ │ ├── color.go │ ├── flags.go │ ├── flags_test.go │ ├── output.go │ ├── output_test.go │ ├── table.go │ ├── table_test.go │ ├── value.go │ ├── viewable.go │ └── viewable_test.go ├── renovate.json └── schema.graphql
SYMBOL INDEX (1940 symbols across 230 files)
FILE: cmd/agent/agent_test.go
function TestParseAgentArg (line 10) | func TestParseAgentArg(t *testing.T) {
FILE: cmd/agent/install.go
type InstallCmd (line 25) | type InstallCmd struct
method Help (line 33) | func (i *InstallCmd) Help() string {
method Run (line 54) | func (i *InstallCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlag...
method createTokenAndConfig (line 126) | func (i *InstallCmd) createTokenAndConfig(globals cli.GlobalFlags) err...
FILE: cmd/agent/list.go
constant stateRunning (line 20) | stateRunning = "running"
constant stateIdle (line 21) | stateIdle = "idle"
constant statePaused (line 22) | statePaused = "paused"
type ListCmd (line 27) | type ListCmd struct
method Help (line 38) | func (c *ListCmd) Help() string {
method Run (line 73) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function validateState (line 199) | func validateState(state string) error {
function filterAgents (line 212) | func filterAgents(agents []buildkite.Agent, state string, tags []string)...
function matchesState (line 222) | func matchesState(a buildkite.Agent, state string) bool {
function matchesTags (line 240) | func matchesTags(a buildkite.Agent, tags []string) bool {
function hasTag (line 253) | func hasTag(metadata []string, tag string) bool {
function extractQueue (line 257) | func extractQueue(metadata []string) string {
function displayState (line 266) | func displayState(a buildkite.Agent) string {
FILE: cmd/agent/list_test.go
function testFilterAgents (line 16) | func testFilterAgents(agents []buildkite.Agent, state string, tags []str...
function TestCmdAgentList (line 20) | func TestCmdAgentList(t *testing.T) {
function TestAgentListStateFilter (line 184) | func TestAgentListStateFilter(t *testing.T) {
function TestAgentListInvalidState (line 227) | func TestAgentListInvalidState(t *testing.T) {
function TestDisplayState (line 240) | func TestDisplayState(t *testing.T) {
function TestAgentListTagsFilter (line 280) | func TestAgentListTagsFilter(t *testing.T) {
function TestAgentListPagination (line 320) | func TestAgentListPagination(t *testing.T) {
FILE: cmd/agent/pause.go
type PauseCmd (line 14) | type PauseCmd struct
method Help (line 20) | func (c *PauseCmd) Help() string {
method Run (line 42) | func (c *PauseCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags)...
FILE: cmd/agent/pause_test.go
function TestPauseCmdValidation (line 7) | func TestPauseCmdValidation(t *testing.T) {
type validationError (line 55) | type validationError
method Error (line 57) | func (e validationError) Error() string { return string(e) }
function errValidation (line 58) | func errValidation(msg string) error { return validationError(msg) }
FILE: cmd/agent/resume.go
type ResumeCmd (line 13) | type ResumeCmd struct
method Help (line 17) | func (c *ResumeCmd) Help() string {
method Run (line 27) | func (c *ResumeCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/agent/resume_test.go
function TestResumeCmdStructure (line 7) | func TestResumeCmdStructure(t *testing.T) {
function TestResumeCmdHelp (line 19) | func TestResumeCmdHelp(t *testing.T) {
FILE: cmd/agent/run.go
type RunCmd (line 22) | type RunCmd struct
method Help (line 28) | func (r *RunCmd) Help() string {
method Run (line 49) | func (r *RunCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) e...
FILE: cmd/agent/stop.go
type StopCmd (line 22) | type StopCmd struct
method Help (line 28) | func (c *StopCmd) Help() string {
method Run (line 51) | func (c *StopCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
type stopResult (line 227) | type stopResult struct
function pluralize (line 232) | func pluralize(word string, count int) string {
function stopAgent (line 239) | func stopAgent(ctx context.Context, id string, f *factory.Factory, force...
FILE: cmd/agent/stop_test.go
function TestStopCmdStructure (line 13) | func TestStopCmdStructure(t *testing.T) {
function TestStopCmdHelp (line 35) | func TestStopCmdHelp(t *testing.T) {
function TestStopAgentErrorCollection (line 50) | func TestStopAgentErrorCollection(t *testing.T) {
function TestStopAgentBulkOperationErrorHandling (line 95) | func TestStopAgentBulkOperationErrorHandling(t *testing.T) {
function TestStopProgressOutput (line 183) | func TestStopProgressOutput(t *testing.T) {
function TestPluralize (line 212) | func TestPluralize(t *testing.T) {
FILE: cmd/agent/util.go
function parseAgentArg (line 10) | func parseAgentArg(agent string, conf *config.Config) (string, string) {
FILE: cmd/agent/view.go
type ViewCmd (line 20) | type ViewCmd struct
method Help (line 26) | func (c *ViewCmd) Help() string {
method Run (line 44) | func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function parseMetadata (line 121) | func parseMetadata(metadataList []string) (string, string) {
function parseQueue (line 148) | func parseQueue(metadata string) string {
FILE: cmd/agent/view_test.go
function TestParseMetadata (line 5) | func TestParseMetadata(t *testing.T) {
FILE: cmd/api/api.go
type ApiCmd (line 23) | type ApiCmd struct
method Help (line 33) | func (c *ApiCmd) Help() string {
method Run (line 87) | func (c *ApiCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) e...
method handleGraphQLQuery (line 186) | func (c *ApiCmd) handleGraphQLQuery(ctx context.Context, f *factory.Fa...
function buildFullEndpoint (line 66) | func buildFullEndpoint(endpoint, orgSlug string, isAnalytics bool) string {
FILE: cmd/api/api_test.go
function TestBuildFullEndpoint (line 7) | func TestBuildFullEndpoint(t *testing.T) {
FILE: cmd/artifacts/download.go
type DownloadCmd (line 22) | type DownloadCmd struct
method Help (line 29) | func (c *DownloadCmd) Help() string {
method Run (line 54) | func (c *DownloadCmd) Run(kongCtx *kong.Context, globals cli.GlobalFla...
method downloadOne (line 105) | func (c *DownloadCmd) downloadOne(ctx context.Context, f *factory.Fact...
method downloadAll (line 124) | func (c *DownloadCmd) downloadAll(ctx context.Context, f *factory.Fact...
function findArtifact (line 159) | func findArtifact(ctx context.Context, f *factory.Factory, org, pipeline...
function listArtifacts (line 183) | func listArtifacts(ctx context.Context, f *factory.Factory, org, pipelin...
function downloadArtifact (line 214) | func downloadArtifact(ctx context.Context, f *factory.Factory, artifact ...
function downloadToFile (line 222) | func downloadToFile(ctx context.Context, f *factory.Factory, url, destPa...
FILE: cmd/artifacts/list.go
type ListCmd (line 22) | type ListCmd struct
method Help (line 29) | func (c *ListCmd) Help() string {
method Run (line 50) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function displayArtifacts (line 132) | func displayArtifacts(artifacts []buildkite.Artifact, writer io.Writer, ...
FILE: cmd/auth/login.go
type LoginCmd (line 22) | type LoginCmd struct
method Help (line 36) | func (c *LoginCmd) Help() string {
method Run (line 104) | func (c *LoginCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags)...
function organizationIdentifier (line 28) | func organizationIdentifier(org string) (orgSlug, orgUUID string) {
function LoginWithToken (line 75) | func LoginWithToken(f *factory.Factory, org, token string) error {
function formatDuration (line 213) | func formatDuration(seconds int) string {
FILE: cmd/auth/login_test.go
function TestOrganizationIdentifier (line 5) | func TestOrganizationIdentifier(t *testing.T) {
FILE: cmd/auth/logout.go
type LogoutCmd (line 12) | type LogoutCmd struct
method Run (line 17) | func (c *LogoutCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
method logoutAll (line 30) | func (c *LogoutCmd) logoutAll(f *factory.Factory) error {
method logoutOrg (line 51) | func (c *LogoutCmd) logoutOrg(f *factory.Factory) error {
FILE: cmd/auth/status.go
type StatusOutput (line 20) | type StatusOutput struct
method TextOutput (line 25) | func (w StatusOutput) TextOutput() string {
type StatusCmd (line 40) | type StatusCmd struct
method Help (line 44) | func (c *StatusCmd) Help() string {
method Run (line 54) | func (c *StatusCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/auth/switch.go
type SwitchCmd (line 12) | type SwitchCmd struct
method Help (line 16) | func (c *SwitchCmd) Help() string {
method Run (line 28) | func (c *SwitchCmd) Run(globals cli.GlobalFlags) error {
function switchRun (line 44) | func switchRun(org *string, conf *config.Config, inGitRepo bool, noInput...
FILE: cmd/auth/switch_test.go
function setEnv (line 12) | func setEnv(t *testing.T, key, value string) {
function TestCmdSwitch (line 30) | func TestCmdSwitch(t *testing.T) {
FILE: cmd/auth/token.go
type TokenCmd (line 12) | type TokenCmd struct
method Help (line 14) | func (c *TokenCmd) Help() string {
method Run (line 31) | func (c *TokenCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags)...
FILE: cmd/build/cancel.go
type CancelCmd (line 18) | type CancelCmd struct
method Help (line 24) | func (c *CancelCmd) Help() string {
method Run (line 34) | func (c *CancelCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
function cancelBuild (line 78) | func cancelBuild(ctx context.Context, org string, pipeline string, build...
FILE: cmd/build/create.go
type CreateCmd (line 21) | type CreateCmd struct
method Help (line 34) | func (c *CreateCmd) Help() string {
method Run (line 48) | func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
function parseAuthor (line 138) | func parseAuthor(author string) buildkite.Author {
function createBuild (line 169) | func createBuild(ctx context.Context, org string, pipeline string, f *fa...
function renderResult (line 228) | func renderResult(result string) string {
FILE: cmd/build/download.go
type DownloadCmd (line 21) | type DownloadCmd struct
method Help (line 29) | func (c *DownloadCmd) Help() string {
method Run (line 48) | func (c *DownloadCmd) Run(kongCtx *kong.Context, globals cli.GlobalFla...
function download (line 121) | func download(ctx context.Context, build *build.Build, f *factory.Factor...
FILE: cmd/build/list.go
constant maxBuildLimit (line 25) | maxBuildLimit = 5000
constant pageSize (line 26) | pageSize = 100
type ListCmd (line 29) | type ListCmd struct
method Help (line 45) | func (c *ListCmd) Help() string {
method Run (line 100) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
method buildListOptions (line 180) | func (c *ListCmd) buildListOptions() (*buildkite.BuildsListOptions, er...
method fetchBuilds (line 224) | func (c *ListCmd) fetchBuilds(ctx context.Context, f *factory.Factory,...
method getBuildsByPipeline (line 360) | func (c *ListCmd) getBuildsByPipeline(ctx context.Context, f *factory....
method applyClientSideFilters (line 375) | func (c *ListCmd) applyClientSideFilters(builds []buildkite.Build) ([]...
function isValidEmail (line 450) | func isValidEmail(s string) bool {
function resolveCreatorEmailToUserID (line 455) | func resolveCreatorEmailToUserID(ctx context.Context, f *factory.Factory...
function displayBuilds (line 484) | func displayBuilds(builds []buildkite.Build, format output.Format, write...
function formatDuration (line 546) | func formatDuration(d time.Duration) string {
FILE: cmd/build/list_test.go
type buildListOptions (line 13) | type buildListOptions struct
function applyClientSideFilters (line 18) | func applyClientSideFilters(builds []buildkite.Build, opts buildListOpti...
function TestBuildListOptions_MetaData (line 26) | func TestBuildListOptions_MetaData(t *testing.T) {
function TestBuildListOptions_EmptyMetaData (line 52) | func TestBuildListOptions_EmptyMetaData(t *testing.T) {
function TestDisplayBuilds_EmptyJSON (line 65) | func TestDisplayBuilds_EmptyJSON(t *testing.T) {
function TestDisplayBuilds_EmptyYAML (line 78) | func TestDisplayBuilds_EmptyYAML(t *testing.T) {
function TestFilterBuilds (line 91) | func TestFilterBuilds(t *testing.T) {
FILE: cmd/build/rebuild.go
type RebuildCmd (line 19) | type RebuildCmd struct
method Help (line 28) | func (c *RebuildCmd) Help() string {
method Run (line 50) | func (c *RebuildCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlag...
function rebuild (line 113) | func rebuild(ctx context.Context, org string, pipeline string, buildId s...
FILE: cmd/build/view.go
type ViewCmd (line 23) | type ViewCmd struct
method Help (line 34) | func (c *ViewCmd) Help() string {
method buildGetOptions (line 67) | func (c *ViewCmd) buildGetOptions() *buildkite.BuildGetOptions {
method Run (line 74) | func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
FILE: cmd/build/view_test.go
function TestViewCmd_BuildGetOptions_WithJobStates (line 7) | func TestViewCmd_BuildGetOptions_WithJobStates(t *testing.T) {
function TestViewCmd_BuildGetOptions_Empty (line 31) | func TestViewCmd_BuildGetOptions_Empty(t *testing.T) {
function TestViewCmd_BuildGetOptions_SingleState (line 40) | func TestViewCmd_BuildGetOptions_SingleState(t *testing.T) {
FILE: cmd/build/watch.go
type WatchCmd (line 24) | type WatchCmd struct
method Help (line 31) | func (c *WatchCmd) Help() string {
method Run (line 50) | func (c *WatchCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags)...
FILE: cmd/cluster/cluster_test.go
function TestListClusters (line 14) | func TestListClusters(t *testing.T) {
function TestGetCluster (line 93) | func TestGetCluster(t *testing.T) {
function TestCreateCluster (line 135) | func TestCreateCluster(t *testing.T) {
function TestUpdateCluster (line 203) | func TestUpdateCluster(t *testing.T) {
function TestDeleteCluster (line 305) | func TestDeleteCluster(t *testing.T) {
function TestUpdateCmdValidate (line 330) | func TestUpdateCmdValidate(t *testing.T) {
function TestRenderClusterText (line 387) | func TestRenderClusterText(t *testing.T) {
FILE: cmd/cluster/create.go
type CreateCmd (line 19) | type CreateCmd struct
method Help (line 27) | func (c *CreateCmd) Help() string {
method Run (line 43) | func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/cluster/delete.go
type DeleteCmd (line 17) | type DeleteCmd struct
method Help (line 21) | func (c *DeleteCmd) Help() string {
method Run (line 36) | func (c *DeleteCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/cluster/list.go
type ListCmd (line 22) | type ListCmd struct
method Help (line 26) | func (c *ListCmd) Help() string {
method Run (line 39) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function listClusters (line 78) | func listClusters(ctx context.Context, f *factory.Factory) ([]buildkite....
FILE: cmd/cluster/update.go
type UpdateCmd (line 19) | type UpdateCmd struct
method Help (line 29) | func (c *UpdateCmd) Help() string {
method Validate (line 50) | func (c *UpdateCmd) Validate() error {
method Run (line 57) | func (c *UpdateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/cluster/view.go
type ViewCmd (line 21) | type ViewCmd struct
method Help (line 26) | func (c *ViewCmd) Help() string {
method Run (line 39) | func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function renderClusterText (line 83) | func renderClusterText(c buildkite.Cluster) string {
FILE: cmd/config/config.go
type ConfigCmd (line 13) | type ConfigCmd struct
method Help (line 20) | func (c ConfigCmd) Help() string {
type ConfigKey (line 38) | type ConfigKey
method IsLocalOnly (line 75) | func (k ConfigKey) IsLocalOnly() bool {
method IsUserOnly (line 80) | func (k ConfigKey) IsUserOnly() bool {
method IsBool (line 90) | func (k ConfigKey) IsBool() bool {
method ValidValues (line 100) | func (k ConfigKey) ValidValues() []string {
constant KeySelectedOrg (line 41) | KeySelectedOrg ConfigKey = "selected_org"
constant KeyOutputFormat (line 42) | KeyOutputFormat ConfigKey = "output_format"
constant KeyNoPager (line 43) | KeyNoPager ConfigKey = "no_pager"
constant KeyQuiet (line 44) | KeyQuiet ConfigKey = "quiet"
constant KeyNoInput (line 45) | KeyNoInput ConfigKey = "no_input"
constant KeyPager (line 46) | KeyPager ConfigKey = "pager"
constant KeyTelemetry (line 47) | KeyTelemetry ConfigKey = "telemetry"
constant KeyExperiments (line 48) | KeyExperiments ConfigKey = "experiments"
function AllKeys (line 52) | func AllKeys() []ConfigKey {
function ValidateKey (line 66) | func ValidateKey(key string) (ConfigKey, error) {
function parseBoolOrDefault (line 112) | func parseBoolOrDefault(value string, defaultVal bool) (bool, error) {
function SetConfigValue (line 119) | func SetConfigValue(conf *config.Config, key ConfigKey, value string, lo...
FILE: cmd/config/config_test.go
function TestValidateKey (line 7) | func TestValidateKey(t *testing.T) {
function TestConfigKeyIsBool (line 46) | func TestConfigKeyIsBool(t *testing.T) {
function TestConfigKeyIsUserOnly (line 71) | func TestConfigKeyIsUserOnly(t *testing.T) {
function TestConfigKeyValidValues (line 96) | func TestConfigKeyValidValues(t *testing.T) {
FILE: cmd/config/get.go
type GetCmd (line 9) | type GetCmd struct
method Help (line 13) | func (c *GetCmd) Help() string {
method Run (line 33) | func (c *GetCmd) Run() error {
FILE: cmd/config/list.go
type ListCmd (line 10) | type ListCmd struct
method Help (line 15) | func (c *ListCmd) Help() string {
method Run (line 26) | func (c *ListCmd) Run() error {
FILE: cmd/config/set.go
type SetCmd (line 10) | type SetCmd struct
method Help (line 16) | func (c *SetCmd) Help() string {
method Run (line 42) | func (c *SetCmd) Run() error {
FILE: cmd/config/unset.go
type UnsetCmd (line 9) | type UnsetCmd struct
method Help (line 14) | func (c *UnsetCmd) Help() string {
method Run (line 28) | func (c *UnsetCmd) Run() error {
FILE: cmd/configure/configure.go
type ConfigureCmd (line 18) | type ConfigureCmd struct
method Help (line 41) | func (c *ConfigureCmd) Help() string {
method Run (line 52) | func (c *ConfigureCmd) Run(kongCtx *kong.Context, globals cli.GlobalFl...
type ConfigureDefaultCmd (line 26) | type ConfigureDefaultCmd struct
type ConfigureAddCmd (line 28) | type ConfigureAddCmd struct
method Help (line 30) | func (c *ConfigureAddCmd) Help() string {
function ConfigureWithCredentials (line 84) | func ConfigureWithCredentials(f *factory.Factory, org, token string) err...
function ConfigureRun (line 88) | func ConfigureRun(f *factory.Factory, org string) error {
function getTokenForOrg (line 122) | func getTokenForOrg(f *factory.Factory, org string) string {
function promptForInput (line 127) | func promptForInput(prompt string, isPassword bool) (string, error) {
FILE: cmd/configure/configure_case_test.go
function TestConfigurePreservesOrganizationCase (line 12) | func TestConfigurePreservesOrganizationCase(t *testing.T) {
FILE: cmd/configure/configure_test.go
function TestGetTokenForOrg (line 12) | func TestGetTokenForOrg(t *testing.T) {
function TestConfigureWithCredentials (line 60) | func TestConfigureWithCredentials(t *testing.T) {
function TestConfigureTokenReuse (line 88) | func TestConfigureTokenReuse(t *testing.T) {
FILE: cmd/generate/generate.go
function main (line 15) | func main() {
FILE: cmd/init/init.go
constant defaultPipelineYAML (line 12) | defaultPipelineYAML = `steps:
type InitCmd (line 17) | type InitCmd struct
method Run (line 19) | func (c *InitCmd) Run(kongCtx *kong.Context) error {
function findExistingPipelineFile (line 41) | func findExistingPipelineFile(base string) (bool, string) {
FILE: cmd/init/init_test.go
function TestFindExistingPipelineFileWithNoFile (line 9) | func TestFindExistingPipelineFileWithNoFile(t *testing.T) {
function TestFindExistingPipelineFile (line 21) | func TestFindExistingPipelineFile(t *testing.T) {
FILE: cmd/job/cancel.go
type CancelCmd (line 16) | type CancelCmd struct
method Help (line 21) | func (c *CancelCmd) Help() string {
method Run (line 35) | func (c *CancelCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
method cancelJob (line 64) | func (c *CancelCmd) cancelJob(ctx context.Context, displayID, apiID st...
FILE: cmd/job/cancel_test.go
function TestCancelCmdStructure (line 9) | func TestCancelCmdStructure(t *testing.T) {
function TestGraphQLIDGeneration (line 26) | func TestGraphQLIDGeneration(t *testing.T) {
FILE: cmd/job/list.go
constant maxJobLimit (line 26) | maxJobLimit = 5000
constant pageSize (line 27) | pageSize = 100
type ListCmd (line 30) | type ListCmd struct
method Help (line 43) | func (c *ListCmd) Help() string {
method Run (line 106) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
type jobListOptions (line 88) | type jobListOptions struct
method withoutQueue (line 100) | func (opts jobListOptions) withoutQueue() jobListOptions {
function fetchJobs (line 199) | func fetchJobs(ctx context.Context, f *factory.Factory, org string, opts...
type listJobsByQueue (line 269) | type listJobsByQueue
function listJobsWithPagination (line 271) | func listJobsWithPagination(ctx context.Context, f *factory.Factory, org...
function fetchJobsWithQueueFilter (line 309) | func fetchJobsWithQueueFilter(ctx context.Context, f *factory.Factory, o...
constant maxConcurrentRequests (line 324) | maxConcurrentRequests = 10
type ClusterInfo (line 326) | type ClusterInfo struct
function lookupQueueIDs (line 331) | func lookupQueueIDs(ctx context.Context, f *factory.Factory, org, queueN...
function fetchAllClusters (line 344) | func fetchAllClusters(ctx context.Context, client graphql.Client, org st...
function fetchQueuesFromClusters (line 377) | func fetchQueuesFromClusters(ctx context.Context, client graphql.Client,...
function fetchQueuesForCluster (line 422) | func fetchQueuesForCluster(ctx context.Context, client graphql.Client, c...
function listJobsByClusterQueue (line 458) | func listJobsByClusterQueue(ctx context.Context, f *factory.Factory, org...
function convertGraphQLJobToBuildkiteJob (line 485) | func convertGraphQLJobToBuildkiteJob(jobNode *bkGraphQL.ListJobsByQueueO...
function listJobsByAgentQueryRules (line 521) | func listJobsByAgentQueryRules(ctx context.Context, f *factory.Factory, ...
function convertGraphQLAgentQueryRulesJobToBuildkiteJob (line 548) | func convertGraphQLAgentQueryRulesJobToBuildkiteJob(jobNode *bkGraphQL.L...
function convertTimestamp (line 593) | func convertTimestamp(t *time.Time) *buildkite.Timestamp {
function convertAgent (line 600) | func convertAgent(agentNode *bkGraphQL.ListJobsByQueueOrganizationJobsJo...
function derefString (line 613) | func derefString(s *string) string {
function mapGraphQLState (line 621) | func mapGraphQLState(graphqlState, exitStatus string) string {
function jobListOptionsFromFlags (line 649) | func jobListOptionsFromFlags(opts *jobListOptions) (*buildkite.BuildsLis...
function getBuildsByPipeline (line 676) | func getBuildsByPipeline(ctx context.Context, f *factory.Factory, org, p...
function applyClientSideFilters (line 691) | func applyClientSideFilters(jobs []buildkite.Job, opts jobListOptions) (...
function matchesQueue (line 778) | func matchesQueue(job buildkite.Job, queueFilter string) bool {
function sortJobs (line 800) | func sortJobs(jobs []buildkite.Job, orderBy string) []buildkite.Job {
function getJobDuration (line 830) | func getJobDuration(job buildkite.Job) time.Duration {
function displayJobs (line 840) | func displayJobs(jobs []buildkite.Job, format output.Format, writer io.W...
function formatDuration (line 904) | func formatDuration(d time.Duration) string {
function containsString (line 918) | func containsString(slice []string, item string) bool {
FILE: cmd/job/list_test.go
function TestDisplayJobs_EmptyJSON (line 13) | func TestDisplayJobs_EmptyJSON(t *testing.T) {
function TestDisplayJobs_EmptyYAML (line 26) | func TestDisplayJobs_EmptyYAML(t *testing.T) {
function TestFilterJobs (line 39) | func TestFilterJobs(t *testing.T) {
FILE: cmd/job/log.go
type LogCmd (line 18) | type LogCmd struct
method Help (line 25) | func (c *LogCmd) Help() string {
method Run (line 39) | func (c *LogCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) e...
function stripTimestamps (line 114) | func stripTimestamps(content string) string {
FILE: cmd/job/reprioritize.go
type ReprioritizeCmd (line 18) | type ReprioritizeCmd struct
method Help (line 25) | func (c *ReprioritizeCmd) Help() string {
method Run (line 36) | func (c *ReprioritizeCmd) Run(kongCtx *kong.Context, globals cli.Globa...
FILE: cmd/job/retry.go
constant jobCommandPrefix (line 16) | jobCommandPrefix = "JobTypeCommand---"
type RetryCmd (line 18) | type RetryCmd struct
method Help (line 22) | func (c *RetryCmd) Help() string {
method Run (line 31) | func (c *RetryCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags)...
FILE: cmd/job/unblock.go
constant jobBlockPrefix (line 21) | jobBlockPrefix = "JobTypeBlock---"
type UnblockCmd (line 23) | type UnblockCmd struct
method Help (line 28) | func (c *UnblockCmd) Help() string {
method Run (line 47) | func (c *UnblockCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlag...
function validateUnblockResponse (line 110) | func validateUnblockResponse(result *bkGraphQL.UnblockJobResponse) error {
FILE: cmd/job/unblock_test.go
function TestValidateUnblockResponse (line 9) | func TestValidateUnblockResponse(t *testing.T) {
FILE: cmd/maintainer/create.go
type CreateCmd (line 20) | type CreateCmd struct
method Help (line 27) | func (c *CreateCmd) Help() string {
method Validate (line 42) | func (c *CreateCmd) Validate() error {
method Run (line 49) | func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
function renderMaintainerText (line 100) | func renderMaintainerText(m buildkite.ClusterMaintainerEntry) string {
FILE: cmd/maintainer/delete.go
type DeleteCmd (line 17) | type DeleteCmd struct
method Help (line 22) | func (c *DeleteCmd) Help() string {
method Run (line 40) | func (c *DeleteCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/maintainer/list.go
type ListCmd (line 19) | type ListCmd struct
method Help (line 24) | func (c *ListCmd) Help() string {
method Run (line 37) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
FILE: cmd/maintainer/maintainer_test.go
function TestListMaintainers (line 14) | func TestListMaintainers(t *testing.T) {
function TestCreateMaintainer (line 98) | func TestCreateMaintainer(t *testing.T) {
function TestDeleteMaintainer (line 149) | func TestDeleteMaintainer(t *testing.T) {
FILE: cmd/organization/list.go
type ListCmd (line 15) | type ListCmd struct
method Help (line 24) | func (c *ListCmd) Help() string {
method Run (line 36) | func (c *ListCmd) Run(globals cli.GlobalFlags) error {
type Organization (line 19) | type Organization struct
FILE: cmd/pipeline/convert.go
constant convertEndpoint (line 23) | convertEndpoint = "https://m4vrh5pvtd.execute-api.us-east-1.amazonaws.co...
type conversionRequest (line 25) | type conversionRequest struct
type conversionResponse (line 30) | type conversionResponse struct
type statusResponse (line 37) | type statusResponse struct
type ConvertCmd (line 47) | type ConvertCmd struct
method Help (line 54) | func (c *ConvertCmd) Help() string {
method Run (line 89) | func (c *ConvertCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlag...
function detectVendor (line 192) | func detectVendor(filePath string) (string, error) {
function submitConversionJob (line 214) | func submitConversionJob(req conversionRequest) (*conversionResponse, er...
function submitConversionJobAtEndpoint (line 218) | func submitConversionJobAtEndpoint(endpoint string, req conversionReques...
function pollJobStatus (line 255) | func pollJobStatus(jobID string, timeoutSeconds int) (*statusResponse, e...
type pollConfig (line 270) | type pollConfig struct
function pollJobStatusWithConfig (line 278) | func pollJobStatusWithConfig(jobID string, cfg pollConfig) (*statusRespo...
FILE: cmd/pipeline/convert_test.go
constant conversionIntegrationTestsEnv (line 15) | conversionIntegrationTestsEnv = "BK_RUN_INTEGRATION_TESTS"
function TestConversionAPIEndpoint (line 17) | func TestConversionAPIEndpoint(t *testing.T) {
function TestDetectVendor (line 79) | func TestDetectVendor(t *testing.T) {
function TestContains (line 162) | func TestContains(t *testing.T) {
function TestSubmitConversionJob (line 204) | func TestSubmitConversionJob(t *testing.T) {
function TestPollJobStatus (line 261) | func TestPollJobStatus(t *testing.T) {
function TestPollJobStatusTimeout (line 313) | func TestPollJobStatusTimeout(t *testing.T) {
function TestMigrateCommandCreation (line 350) | func TestMigrateCommandCreation(t *testing.T) {
function TestMigrateAutoDetection (line 372) | func TestMigrateAutoDetection(t *testing.T) {
FILE: cmd/pipeline/copy.go
type CopyCmd (line 20) | type CopyCmd struct
method orgSlug (line 37) | func (c *CopyCmd) orgSlug(f *factory.Factory) string {
method Validate (line 45) | func (c *CopyCmd) Validate() error {
method Help (line 55) | func (c *CopyCmd) Help() string {
method Run (line 97) | func (c *CopyCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
method resolveSourcePipeline (line 148) | func (c *CopyCmd) resolveSourcePipeline(ctx context.Context, f *factor...
method resolveTarget (line 175) | func (c *CopyCmd) resolveTarget(f *factory.Factory, sourceName string)...
method resolveCluster (line 208) | func (c *CopyCmd) resolveCluster(ctx context.Context, f *factory.Facto...
method fetchSourcePipeline (line 224) | func (c *CopyCmd) fetchSourcePipeline(ctx context.Context, f *factory....
method runDryRun (line 243) | func (c *CopyCmd) runDryRun(kongCtx *kong.Context, f *factory.Factory,...
method runCopy (line 256) | func (c *CopyCmd) runCopy(kongCtx *kong.Context, f *factory.Factory, s...
method getClientForOrg (line 298) | func (c *CopyCmd) getClientForOrg(f *factory.Factory, org string) (*bu...
method buildCreatePipeline (line 310) | func (c *CopyCmd) buildCreatePipeline(source *buildkite.Pipeline, targ...
method findPipelineByName (line 351) | func (c *CopyCmd) findPipelineByName(ctx context.Context, client *buil...
type copyTarget (line 32) | type copyTarget struct
function parseTarget (line 194) | func parseTarget(target, defaultOrg string) *copyTarget {
FILE: cmd/pipeline/create.go
type CreateCmd (line 22) | type CreateCmd struct
method orgSlug (line 35) | func (c *CreateCmd) orgSlug(conf *config.Config) string {
method Validate (line 42) | func (c *CreateCmd) Validate() error {
method Help (line 52) | func (c *CreateCmd) Help() string {
method Run (line 82) | func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
method runPipelineCreateDryRun (line 102) | func (c *CreateCmd) runPipelineCreateDryRun(kongCtx *kong.Context, f *...
method runPipelineCreate (line 117) | func (c *CreateCmd) runPipelineCreate(kongCtx *kong.Context, f *factor...
method createPipeline (line 146) | func (c *CreateCmd) createPipeline(ctx context.Context, f *factory.Fac...
method findPipelineByName (line 182) | func (c *CreateCmd) findPipelineByName(ctx context.Context, f *factory...
method createPipelineDryRun (line 253) | func (c *CreateCmd) createPipelineDryRun(ctx context.Context, f *facto...
method resolveClusterUUID (line 432) | func (c *CreateCmd) resolveClusterUUID(ctx context.Context, f *factory...
type PipelineDryRun (line 203) | type PipelineDryRun struct
function initialisePipelineDryRun (line 241) | func initialisePipelineDryRun() PipelineDryRun {
function generateSlug (line 305) | func generateSlug(name string) string {
function extractRepoPath (line 327) | func extractRepoPath(repoURL string) string {
function getAvailablePipelineSlug (line 341) | func getAvailablePipelineSlug(ctx context.Context, f *factory.Factory, o...
function getClusterUrl (line 376) | func getClusterUrl(orgSlug, clusterID string) string {
function getClusters (line 383) | func getClusters(ctx context.Context, f *factory.Factory, org string) (m...
function listClusterNames (line 417) | func listClusterNames(ctx context.Context, f *factory.Factory, org strin...
function resolveClusterName (line 443) | func resolveClusterName(ctx context.Context, f *factory.Factory, org, cl...
function getCreatedByDetails (line 461) | func getCreatedByDetails(ctx context.Context, f *factory.Factory) *build...
function isGitHubURL (line 470) | func isGitHubURL(repoURL string) bool {
function getRepositoryURL (line 478) | func getRepositoryURL(f *factory.Factory, repoFlag string) string {
function createWebhook (line 500) | func createWebhook(ctx context.Context, f *factory.Factory, pipelineGrap...
FILE: cmd/pipeline/create_test.go
function TestIsGitHubURL (line 9) | func TestIsGitHubURL(t *testing.T) {
function TestGetRepositoryURL (line 80) | func TestGetRepositoryURL(t *testing.T) {
function TestExtractRepoPath (line 118) | func TestExtractRepoPath(t *testing.T) {
FILE: cmd/pipeline/list.go
constant maxPipelineLimit (line 19) | maxPipelineLimit = 3000
constant pageSize (line 20) | pageSize = 100
type ListCmd (line 23) | type ListCmd struct
method Help (line 31) | func (c *ListCmd) Help() string {
method Run (line 58) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
method runPipelineList (line 81) | func (c *ListCmd) runPipelineList(ctx context.Context, f *factory.Fact...
method pipelineListOptionsFromFlags (line 110) | func (c *ListCmd) pipelineListOptionsFromFlags() *buildkite.PipelineLi...
method fetchPipelines (line 127) | func (c *ListCmd) fetchPipelines(ctx context.Context, f *factory.Facto...
method displayPipelines (line 153) | func (c *ListCmd) displayPipelines(pipelines []buildkite.Pipeline, f *...
FILE: cmd/pipeline/validate.go
constant schemaURL (line 17) | schemaURL = "https://raw.githubusercontent.com/buildkite/pipeline-schema...
type ValidateCmd (line 47) | type ValidateCmd struct
method Help (line 51) | func (c *ValidateCmd) Help() string {
method Run (line 71) | func (c *ValidateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFla...
function findPipelineFile (line 113) | func findPipelineFile() (string, error) {
function fileExists (line 144) | func fileExists(path string) bool {
function validatePipeline (line 153) | func validatePipeline(w io.Writer, filePath string) error {
function formatValidationError (line 214) | func formatValidationError(err gojsonschema.ResultError) string {
FILE: cmd/pipeline/validate_test.go
function TestValidatePipeline (line 16) | func TestValidatePipeline(t *testing.T) {
function TestFindPipelineFile (line 178) | func TestFindPipelineFile(t *testing.T) {
function TestFormatValidationError (line 240) | func TestFormatValidationError(t *testing.T) {
function TestFileExists (line 320) | func TestFileExists(t *testing.T) {
FILE: cmd/pipeline/view.go
type ViewCmd (line 22) | type ViewCmd struct
method Help (line 31) | func (c *ViewCmd) Help() string {
method Run (line 52) | func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function renderPipelineText (line 134) | func renderPipelineText(p buildkite.Pipeline) string {
FILE: cmd/pkg/push.go
type PushCmd (line 28) | type PushCmd struct
method Help (line 36) | func (c *PushCmd) Help() string {
method Run (line 56) | func (c *PushCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
method Validate (line 120) | func (c *PushCmd) Validate() error {
function isStdinReadable (line 110) | func isStdinReadable() (bool, error) {
FILE: cmd/pkg/push_test.go
function TestPackagePushCommandArgs (line 10) | func TestPackagePushCommandArgs(t *testing.T) {
FILE: cmd/preflight/cleanup_cmd.go
type CleanupCmd (line 19) | type CleanupCmd struct
method Help (line 27) | func (c *CleanupCmd) Help() string {
method Run (line 31) | func (c *CleanupCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlag...
FILE: cmd/preflight/cleanup_cmd_test.go
function TestCleanupCmd_Run (line 19) | func TestCleanupCmd_Run(t *testing.T) {
function createPreflightBranch (line 397) | func createPreflightBranch(t *testing.T, worktree, branch string) {
FILE: cmd/preflight/event.go
type EventType (line 12) | type EventType
constant EventOperation (line 15) | EventOperation EventType = "operation"
constant EventBuildStatus (line 16) | EventBuildStatus EventType = "build_status"
constant EventJobFailure (line 17) | EventJobFailure EventType = "job_failure"
constant EventJobRetryPassed (line 18) | EventJobRetryPassed EventType = "job_retry_passed"
constant EventBuildSummary (line 19) | EventBuildSummary EventType = "build_summary"
constant EventTestFailure (line 20) | EventTestFailure EventType = "test_failure"
type Event (line 25) | type Event struct
method ApplySummaryMeta (line 85) | func (e *Event) ApplySummaryMeta(meta summaryMeta) {
method ApplyJobResults (line 97) | func (e *Event) ApplyJobResults(finalBuild buildkite.Build, tracker *w...
function newBuildSummaryEvent (line 72) | func newBuildSummaryEvent(preflightID, pipeline string, buildNumber int,...
FILE: cmd/preflight/event_test.go
function TestEvent_Operation (line 11) | func TestEvent_Operation(t *testing.T) {
function TestEvent_BuildStatus (line 30) | func TestEvent_BuildStatus(t *testing.T) {
function TestEvent_JobFailure (line 56) | func TestEvent_JobFailure(t *testing.T) {
function TestEvent_BuildSummaryStoppedEarly (line 82) | func TestEvent_BuildSummaryStoppedEarly(t *testing.T) {
FILE: cmd/preflight/job_presenter.go
type jobPresenter (line 12) | type jobPresenter struct
method failParts (line 18) | func (p jobPresenter) failParts(j buildkite.Job, action string) (symbo...
method Line (line 43) | func (p jobPresenter) Line(j buildkite.Job) string {
method PassedLine (line 48) | func (p jobPresenter) PassedLine(j buildkite.Job) string {
method RetryPassedLine (line 53) | func (p jobPresenter) RetryPassedLine(j buildkite.Job) string {
method ColoredRetryPassedLine (line 58) | func (p jobPresenter) ColoredRetryPassedLine(j buildkite.Job) string {
method ColoredPassedLine (line 68) | func (p jobPresenter) ColoredPassedLine(j buildkite.Job, style lipglos...
method ColoredLine (line 78) | func (p jobPresenter) ColoredLine(j buildkite.Job) string {
method jobLink (line 95) | func (p jobPresenter) jobLink(j buildkite.Job) string {
FILE: cmd/preflight/job_presenter_test.go
function TestJobPresenter_FailedLine (line 11) | func TestJobPresenter_FailedLine(t *testing.T) {
function TestJobPresenter_SoftFailedLine (line 28) | func TestJobPresenter_SoftFailedLine(t *testing.T) {
function TestJobPresenter_FailedNoExit (line 44) | func TestJobPresenter_FailedNoExit(t *testing.T) {
function TestJobPresenter_PassedLine (line 63) | func TestJobPresenter_PassedLine(t *testing.T) {
function TestJobPresenter_PassedLine_WithEmoji (line 72) | func TestJobPresenter_PassedLine_WithEmoji(t *testing.T) {
function TestJobPresenter_RetryPassedLine (line 86) | func TestJobPresenter_RetryPassedLine(t *testing.T) {
function TestJobPresenter_RetryPassedLine_MultipleRetries (line 95) | func TestJobPresenter_RetryPassedLine_MultipleRetries(t *testing.T) {
function TestJobPresenter_ColoredRetryPassedLine (line 104) | func TestJobPresenter_ColoredRetryPassedLine(t *testing.T) {
function TestJobPresenter_ColoredRetryPassedLine_WithEmoji (line 113) | func TestJobPresenter_ColoredRetryPassedLine_WithEmoji(t *testing.T) {
function TestJobPresenter_ColoredLine (line 122) | func TestJobPresenter_ColoredLine(t *testing.T) {
function TestJobPresenter_ColoredLine_UsesClickableJobLink (line 135) | func TestJobPresenter_ColoredLine_UsesClickableJobLink(t *testing.T) {
function TestJobPresenter_ColoredLine_DerivesClickableJobLinkFromBuildURL (line 154) | func TestJobPresenter_ColoredLine_DerivesClickableJobLinkFromBuildURL(t ...
function TestJobPresenter_ColoredLine_SoftFailed (line 171) | func TestJobPresenter_ColoredLine_SoftFailed(t *testing.T) {
function TestJobPresenter_ColoredLine_WithEmoji (line 183) | func TestJobPresenter_ColoredLine_WithEmoji(t *testing.T) {
function assertStringContainsAll (line 196) | func assertStringContainsAll(t *testing.T, got string, want []string) {
FILE: cmd/preflight/preflight.go
type RunCmd (line 32) | type RunCmd struct
method Help (line 101) | func (c *RunCmd) Help() string {
method Validate (line 105) | func (c *RunCmd) Validate() error {
method Run (line 112) | func (c *RunCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) e...
method loadFinalResult (line 375) | func (c *RunCmd) loadFinalResult(ctx context.Context, client *buildkit...
method loadSummary (line 402) | func (c *RunCmd) loadSummary(ctx context.Context, client *buildkite.Cl...
constant defaultAwaitTestResultsDuration (line 51) | defaultAwaitTestResultsDuration = 30 * time.Second
function HelpText (line 53) | func HelpText() string {
type summaryMeta (line 59) | type summaryMeta struct
function preflightUserAgentSuffix (line 65) | func preflightUserAgentSuffix() string {
type awaitTestResultsFlag (line 76) | type awaitTestResultsFlag struct
method Decode (line 81) | func (f *awaitTestResultsFlag) Decode(ctx *kong.DecodeContext) error {
method IsBool (line 99) | func (f awaitTestResultsFlag) IsBool() bool { return true }
function cleanupRemoteBranch (line 345) | func cleanupRemoteBranch(renderer renderer, repoRoot, branch, ref, prefl...
function cancelBuild (line 354) | func cancelBuild(f *factory.Factory, renderer renderer, org, pipeline st...
type preflightContext (line 420) | type preflightContext struct
function setup (line 431) | func setup(pipelineFlag string, globals cli.GlobalFlags) (*preflightCont...
function resolveRepositoryRoot (line 485) | func resolveRepositoryRoot(f *factory.Factory, debug bool) (string, erro...
FILE: cmd/preflight/preflight_test.go
type stubGlobals (line 29) | type stubGlobals struct
method SkipConfirmation (line 31) | func (s stubGlobals) SkipConfirmation() bool { return false }
method DisableInput (line 32) | func (s stubGlobals) DisableInput() bool { return false }
method IsQuiet (line 33) | func (s stubGlobals) IsQuiet() bool { return false }
method DisablePager (line 34) | func (s stubGlobals) DisablePager() bool { return false }
method EnableDebug (line 35) | func (s stubGlobals) EnableDebug() bool { return false }
function unsetEnv (line 39) | func unsetEnv(t *testing.T, key string) {
function TestParseExitConditions (line 60) | func TestParseExitConditions(t *testing.T) {
function TestPreflightCmd_Run (line 102) | func TestPreflightCmd_Run(t *testing.T) {
type recordingRenderer (line 1872) | type recordingRenderer struct
method Render (line 1876) | func (r *recordingRenderer) Render(Event) error { return nil }
method Close (line 1878) | func (r *recordingRenderer) Close() error {
function initTestRepo (line 1883) | func initTestRepo(t *testing.T) string {
function runGit (line 1907) | func runGit(t *testing.T, dir string, args ...string) string {
function captureStdout (line 1921) | func captureStdout(t *testing.T, fn func()) string {
function decodeJSONLEvents (line 1949) | func decodeJSONLEvents(t *testing.T, output string) []Event {
FILE: cmd/preflight/render.go
type renderer (line 19) | type renderer interface
function newRenderer (line 24) | func newRenderer(stdout io.Writer, jsonMode bool, textMode bool, cancel ...
type plainRenderer (line 38) | type plainRenderer struct
method Render (line 47) | func (r *plainRenderer) Render(e Event) error {
method Close (line 119) | func (r *plainRenderer) Close() error { return nil }
function newPlainRenderer (line 43) | func newPlainRenderer(stdout io.Writer) *plainRenderer {
type jsonRenderer (line 121) | type jsonRenderer struct
method Render (line 131) | func (r *jsonRenderer) Render(e Event) error {
method Close (line 135) | func (r *jsonRenderer) Close() error { return nil }
function newJSONRenderer (line 125) | func newJSONRenderer(stdout io.Writer) *jsonRenderer {
function summaryHeader (line 137) | func summaryHeader(e Event) string {
function summaryStopReasonLabel (line 153) | func summaryStopReasonLabel(reason string) string {
function summaryBuildLine (line 166) | func summaryBuildLine(e Event) string {
function summaryBuildLabel (line 174) | func summaryBuildLabel(e Event) string {
function formatDuration (line 181) | func formatDuration(d time.Duration) string {
function plural (line 200) | func plural(n int, word string) string {
constant summaryTestFailureDisplayLimit (line 207) | summaryTestFailureDisplayLimit = 10
function buildSummaryDetails (line 209) | func buildSummaryDetails(e Event, colored bool, width int) string {
function summaryTestsSection (line 236) | func summaryTestsSection(tests map[string]internalpreflight.SummaryTestR...
function orderedSummaryTestRuns (line 276) | func orderedSummaryTestRuns(tests map[string]internalpreflight.SummaryTe...
function summarySuiteWidths (line 297) | func summarySuiteWidths(tests []internalpreflight.SummaryTestRun) summar...
function summarySuiteLabel (line 309) | func summarySuiteLabel(name, slug, fallback string) string {
function jobLogCommand (line 321) | func jobLogCommand(pipeline string, buildNumber int, jobID string) string {
function terminalHyperlink (line 325) | func terminalHyperlink(label, url string) string {
function timestampPrefix (line 332) | func timestampPrefix(t time.Time) string {
function formatTimestampedDetail (line 336) | func formatTimestampedDetail(title, detail string, t time.Time) string {
function formatTimestampedBlock (line 340) | func formatTimestampedBlock(text string, t time.Time) string {
function indentAllLines (line 350) | func indentAllLines(text string, indentWidth int) string {
FILE: cmd/preflight/render_test.go
function TestPlainRenderer_Render_Operation (line 18) | func TestPlainRenderer_Render_Operation(t *testing.T) {
function TestPlainRenderer_Render_OperationWithDetail (line 38) | func TestPlainRenderer_Render_OperationWithDetail(t *testing.T) {
function TestPlainRenderer_Render_OperationWithMultiLineDetail (line 59) | func TestPlainRenderer_Render_OperationWithMultiLineDetail(t *testing.T) {
function TestFormatTimestampedDetail_UsesLeftAlignedTimestampIndent (line 85) | func TestFormatTimestampedDetail_UsesLeftAlignedTimestampIndent(t *testi...
function TestFormatTimestampedBlock_IndentsContinuationLines (line 99) | func TestFormatTimestampedBlock_IndentsContinuationLines(t *testing.T) {
function TestPlainRenderer_Render_BuildStatus (line 113) | func TestPlainRenderer_Render_BuildStatus(t *testing.T) {
function TestPlainRenderer_Render_BuildStatusDeduplicates (line 135) | func TestPlainRenderer_Render_BuildStatusDeduplicates(t *testing.T) {
function TestPlainRenderer_Render_JobFailure (line 157) | func TestPlainRenderer_Render_JobFailure(t *testing.T) {
function TestPlainRenderer_Render_JobRetryPassed (line 187) | func TestPlainRenderer_Render_JobRetryPassed(t *testing.T) {
function TestJSONRenderer_Render_JobRetryPassed (line 219) | func TestJSONRenderer_Render_JobRetryPassed(t *testing.T) {
function TestPlainRenderer_Render_TestFailure (line 253) | func TestPlainRenderer_Render_TestFailure(t *testing.T) {
function TestJSONRenderer_Render_Operation (line 291) | func TestJSONRenderer_Render_Operation(t *testing.T) {
function TestJSONRenderer_Render_BuildStatus (line 318) | func TestJSONRenderer_Render_BuildStatus(t *testing.T) {
function TestJSONRenderer_Render_JobFailure (line 349) | func TestJSONRenderer_Render_JobFailure(t *testing.T) {
function TestJSONRenderer_Render_MultipleEvents_JSONL (line 390) | func TestJSONRenderer_Render_MultipleEvents_JSONL(t *testing.T) {
function TestTestPresenter_Line_FailedAttemptIncludesSummaryAndFailureDetails (line 410) | func TestTestPresenter_Line_FailedAttemptIncludesSummaryAndFailureDetail...
function TestFormatTestStatusIcon_UsesLatestExecution (line 458) | func TestFormatTestStatusIcon_UsesLatestExecution(t *testing.T) {
function TestFormatTestStatusIcon_NilExecution (line 470) | func TestFormatTestStatusIcon_NilExecution(t *testing.T) {
function TestTestAttemptCounts_FormatsCorrectly (line 480) | func TestTestAttemptCounts_FormatsCorrectly(t *testing.T) {
function TestTestPresenter_Line_PassedLatestAttemptOnlyShowsSummaryLine (line 497) | func TestTestPresenter_Line_PassedLatestAttemptOnlyShowsSummaryLine(t *t...
function TestLatestTestExecution_PicksNewestTimestamp (line 532) | func TestLatestTestExecution_PicksNewestTimestamp(t *testing.T) {
function TestLatestTestExecution_IgnoresExecutionsWithoutTimestamps (line 557) | func TestLatestTestExecution_IgnoresExecutionsWithoutTimestamps(t *testi...
function TestTestPresenter_ColoredLine_AddsANSIStyles (line 572) | func TestTestPresenter_ColoredLine_AddsANSIStyles(t *testing.T) {
function stripANSI (line 603) | func stripANSI(s string) string {
function TestNewRenderer_NonFileWriterDefaultsToPlain (line 607) | func TestNewRenderer_NonFileWriterDefaultsToPlain(t *testing.T) {
function TestNewRenderer_TextModeForcesPlain (line 615) | func TestNewRenderer_TextModeForcesPlain(t *testing.T) {
function TestNewRenderer_JSONModeReturnsJSON (line 623) | func TestNewRenderer_JSONModeReturnsJSON(t *testing.T) {
function TestPlainRenderer_Render_BuildSummaryPassed (line 631) | func TestPlainRenderer_Render_BuildSummaryPassed(t *testing.T) {
function TestPlainRenderer_Render_BuildSummaryFailed (line 665) | func TestPlainRenderer_Render_BuildSummaryFailed(t *testing.T) {
function TestPlainRenderer_Render_BuildSummaryStoppedEarly (line 702) | func TestPlainRenderer_Render_BuildSummaryStoppedEarly(t *testing.T) {
function TestPlainRenderer_Render_BuildSummaryIncludesTests (line 737) | func TestPlainRenderer_Render_BuildSummaryIncludesTests(t *testing.T) {
function TestJSONRenderer_Render_BuildSummaryPassed (line 781) | func TestJSONRenderer_Render_BuildSummaryPassed(t *testing.T) {
function TestJSONRenderer_Render_BuildSummaryFailed (line 811) | func TestJSONRenderer_Render_BuildSummaryFailed(t *testing.T) {
function TestJSONRenderer_Render_BuildSummaryStoppedEarly (line 843) | func TestJSONRenderer_Render_BuildSummaryStoppedEarly(t *testing.T) {
function TestJSONRenderer_Render_BuildSummaryIncludesTests (line 880) | func TestJSONRenderer_Render_BuildSummaryIncludesTests(t *testing.T) {
function TestFormatDuration (line 941) | func TestFormatDuration(t *testing.T) {
function scriptJob (line 966) | func scriptJob(id, name, state string, softFailed bool, startedAt, finis...
FILE: cmd/preflight/result.go
type resultKind (line 11) | type resultKind
constant resultCompletedPass (line 14) | resultCompletedPass resultKind = iota
constant resultCompletedFailure (line 15) | resultCompletedFailure
constant resultIncompleteFailure (line 16) | resultIncompleteFailure
constant resultIncomplete (line 17) | resultIncomplete
constant resultUnknown (line 18) | resultUnknown
type Result (line 21) | type Result struct
method Passed (line 49) | func (r Result) Passed() bool {
method Error (line 53) | func (r Result) Error() error {
function NewResult (line 26) | func NewResult(build buildkite.Build) Result {
FILE: cmd/preflight/result_test.go
function TestResult (line 11) | func TestResult(t *testing.T) {
function TestResultPassed (line 68) | func TestResultPassed(t *testing.T) {
function TestResultError (line 88) | func TestResultError(t *testing.T) {
FILE: cmd/preflight/test_presenter.go
type testPresenter (line 15) | type testPresenter struct
method Line (line 24) | func (p testPresenter) Line(t buildkite.BuildTest) string {
method ColoredLine (line 28) | func (p testPresenter) ColoredLine(t buildkite.BuildTest) string {
method SummarySuiteLine (line 32) | func (p testPresenter) SummarySuiteLine(summary internalpreflight.Summ...
method SummaryFailureLine (line 52) | func (p testPresenter) SummaryFailureLine(failure internalpreflight.Su...
method line (line 94) | func (p testPresenter) line(t buildkite.BuildTest, colored bool) string {
type summarySuiteColumnWidths (line 17) | type summarySuiteColumnWidths struct
function testAttemptCounts (line 130) | func testAttemptCounts(t buildkite.BuildTest) string {
function latestTestExecution (line 141) | func latestTestExecution(t buildkite.BuildTest) *buildkite.BuildTestExec...
function testExecutionsInTimestampOrder (line 155) | func testExecutionsInTimestampOrder(executions []buildkite.BuildTestExec...
function isFailedTestExecution (line 176) | func isFailedTestExecution(execution *buildkite.BuildTestExecution) bool {
function formatTestDetail (line 184) | func formatTestDetail(text string, colored bool) string {
function formatTestStatusIcon (line 192) | func formatTestStatusIcon(execution *buildkite.BuildTestExecution, color...
function truncateToWidth (line 219) | func truncateToWidth(s string, width int) string {
function trimLeftToWidth (line 240) | func trimLeftToWidth(s string, width int) string {
function trimRightToWidth (line 256) | func trimRightToWidth(s string, width int) string {
function padRightToWidth (line 273) | func padRightToWidth(s string, width int) string {
FILE: cmd/preflight/test_presenter_test.go
function TestTestPresenter_SummarySuiteLine (line 10) | func TestTestPresenter_SummarySuiteLine(t *testing.T) {
function TestTestPresenter_SummaryFailureLine_WrapsAndIndents (line 21) | func TestTestPresenter_SummaryFailureLine_WrapsAndIndents(t *testing.T) {
FILE: cmd/preflight/tty.go
type ttyModel (line 22) | type ttyModel struct
method Init (line 37) | func (m ttyModel) Init() tea.Cmd {
method Update (line 41) | func (m ttyModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
method statusText (line 119) | func (m ttyModel) statusText() string {
method hardwrapLine (line 134) | func (m ttyModel) hardwrapLine(s string) string {
method render (line 141) | func (m ttyModel) render() string {
method View (line 171) | func (m ttyModel) View() string {
function newTTYModel (line 30) | func newTTYModel() ttyModel {
function buildSummaryView (line 181) | func buildSummaryView(e Event, width int) string {
type ttyRenderer (line 207) | type ttyRenderer struct
method Render (line 227) | func (r *ttyRenderer) Render(e Event) error {
method Close (line 232) | func (r *ttyRenderer) Close() error {
function newTTYRenderer (line 213) | func newTTYRenderer(cancel context.CancelFunc) *ttyRenderer {
FILE: cmd/preflight/tty_test.go
function TestBuildSummaryView_ReturnsOutput (line 11) | func TestBuildSummaryView_ReturnsOutput(t *testing.T) {
FILE: cmd/queue/create.go
type CreateCmd (line 19) | type CreateCmd struct
method Validate (line 27) | func (c *CreateCmd) Validate() error {
method Help (line 41) | func (c *CreateCmd) Help() string {
method Run (line 58) | func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/queue/delete.go
type DeleteCmd (line 17) | type DeleteCmd struct
method Help (line 22) | func (c *DeleteCmd) Help() string {
method Run (line 35) | func (c *DeleteCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/queue/list.go
type ListCmd (line 19) | type ListCmd struct
method Validate (line 26) | func (c *ListCmd) Validate() error {
method Help (line 38) | func (c *ListCmd) Help() string {
method Run (line 52) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
FILE: cmd/queue/pause.go
type PauseCmd (line 19) | type PauseCmd struct
method Help (line 26) | func (c *PauseCmd) Help() string {
method Run (line 42) | func (c *PauseCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags)...
FILE: cmd/queue/queue_test.go
function newTestQueue (line 15) | func newTestQueue(key, id string, paused bool) buildkite.ClusterQueue {
function TestCmdQueueList (line 25) | func TestCmdQueueList(t *testing.T) {
function TestCmdQueueCreate (line 128) | func TestCmdQueueCreate(t *testing.T) {
function TestCmdQueueUpdate (line 194) | func TestCmdQueueUpdate(t *testing.T) {
function TestCmdQueueDelete (line 266) | func TestCmdQueueDelete(t *testing.T) {
function TestCmdQueuePause (line 298) | func TestCmdQueuePause(t *testing.T) {
function TestCmdQueueResume (line 340) | func TestCmdQueueResume(t *testing.T) {
function TestRenderQueueText (line 375) | func TestRenderQueueText(t *testing.T) {
FILE: cmd/queue/resume.go
type ResumeCmd (line 19) | type ResumeCmd struct
method Help (line 25) | func (c *ResumeCmd) Help() string {
method Run (line 38) | func (c *ResumeCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/queue/update.go
type UpdateCmd (line 19) | type UpdateCmd struct
method Validate (line 27) | func (c *UpdateCmd) Validate() error {
method Help (line 45) | func (c *UpdateCmd) Help() string {
method Run (line 64) | func (c *UpdateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/queue/view.go
type ViewCmd (line 21) | type ViewCmd struct
method Help (line 27) | func (c *ViewCmd) Help() string {
method Run (line 38) | func (c *ViewCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
function renderQueueText (line 82) | func renderQueueText(q buildkite.ClusterQueue) string {
FILE: cmd/secret/create.go
type CreateCmd (line 19) | type CreateCmd struct
method Help (line 28) | func (c *CreateCmd) Help() string {
method Run (line 47) | func (c *CreateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/secret/delete.go
type DeleteCmd (line 17) | type DeleteCmd struct
method Help (line 22) | func (c *DeleteCmd) Help() string {
method Run (line 37) | func (c *DeleteCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/secret/get.go
type GetCmd (line 21) | type GetCmd struct
method Help (line 27) | func (c *GetCmd) Help() string {
method Run (line 40) | func (c *GetCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) e...
function renderSecretText (line 84) | func renderSecretText(s buildkite.ClusterSecret) string {
FILE: cmd/secret/list.go
type ListCmd (line 21) | type ListCmd struct
method Help (line 26) | func (c *ListCmd) Help() string {
method Run (line 39) | func (c *ListCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) ...
FILE: cmd/secret/secret_test.go
function TestListSecrets (line 14) | func TestListSecrets(t *testing.T) {
function TestGetSecret (line 93) | func TestGetSecret(t *testing.T) {
function TestCreateSecret (line 134) | func TestCreateSecret(t *testing.T) {
function TestDeleteSecret (line 191) | func TestDeleteSecret(t *testing.T) {
function TestUpdateSecret (line 216) | func TestUpdateSecret(t *testing.T) {
function TestUpdateCmdValidate (line 300) | func TestUpdateCmdValidate(t *testing.T) {
function TestRenderSecretText (line 347) | func TestRenderSecretText(t *testing.T) {
FILE: cmd/secret/update.go
type UpdateCmd (line 19) | type UpdateCmd struct
method Help (line 28) | func (c *UpdateCmd) Help() string {
method Validate (line 46) | func (c *UpdateCmd) Validate() error {
method Run (line 53) | func (c *UpdateCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: cmd/skill/skill.go
constant defaultRepo (line 15) | defaultRepo = "buildkite/skills"
constant defaultBranch (line 16) | defaultBranch = "main"
type AddCmd (line 19) | type AddCmd struct
method Help (line 29) | func (c *AddCmd) Help() string {
method Run (line 52) | func (c *AddCmd) Run() error {
type UpdateCmd (line 59) | type UpdateCmd struct
method Help (line 68) | func (c *UpdateCmd) Help() string {
method Run (line 82) | func (c *UpdateCmd) Run() error {
type DeleteCmd (line 131) | type DeleteCmd struct
method Help (line 138) | func (c *DeleteCmd) Help() string {
method Run (line 148) | func (c *DeleteCmd) Run() error {
type target (line 180) | type target struct
method SkillsDir (line 186) | func (t target) SkillsDir() string {
function resolveTarget (line 193) | func resolveTarget(agent string, global bool, customPath string) (target...
function resolveTargets (line 201) | func resolveTargets(agent string, global bool, customPath string) ([]tar...
function dirExists (line 262) | func dirExists(path string) bool {
function installSkill (line 267) | func installSkill(name, agent string, global bool, customPath string, fo...
function installSkillToTargets (line 275) | func installSkillToTargets(name string, targets []target, force bool, re...
function installSkillsToTargets (line 279) | func installSkillsToTargets(plan map[string][]target, force bool, repo, ...
function validateSkillName (line 331) | func validateSkillName(name string) error {
function downloadRepoArchive (line 344) | func downloadRepoArchive(repo, branch, dest string) error {
function extractSkill (line 364) | func extractSkill(archive, skillName, dest string) error {
FILE: cmd/skill/skill_test.go
function TestResolveTargetDetectsProjectAgent (line 10) | func TestResolveTargetDetectsProjectAgent(t *testing.T) {
function TestResolveTargetErrorsWithoutProjectAgent (line 40) | func TestResolveTargetErrorsWithoutProjectAgent(t *testing.T) {
function TestResolveTargetUsesCustomPath (line 56) | func TestResolveTargetUsesCustomPath(t *testing.T) {
function TestResolveTargetsGlobalUsesAllExistingAgentDirs (line 74) | func TestResolveTargetsGlobalUsesAllExistingAgentDirs(t *testing.T) {
function TestResolveTargetsGlobalDoesNotCreateAgentDirs (line 96) | func TestResolveTargetsGlobalDoesNotCreateAgentDirs(t *testing.T) {
function TestValidateSkillNameRejectsPathsURLsAndPatterns (line 108) | func TestValidateSkillNameRejectsPathsURLsAndPatterns(t *testing.T) {
function TestDeleteErrorsWhenSkillIsNotInstalled (line 116) | func TestDeleteErrorsWhenSkillIsNotInstalled(t *testing.T) {
function TestExtractSkill (line 124) | func TestExtractSkill(t *testing.T) {
function createZip (line 152) | func createZip(t *testing.T, path string, files map[string]string) {
FILE: cmd/use/use.go
type UseCmd (line 12) | type UseCmd struct
method Help (line 16) | func (c *UseCmd) Help() string {
method Run (line 28) | func (c *UseCmd) Run(globals cli.GlobalFlags) error {
function useRun (line 44) | func useRun(org *string, conf *config.Config, inGitRepo bool, noInput bo...
FILE: cmd/user/invite.go
type InviteCmd (line 15) | type InviteCmd struct
method Help (line 19) | func (c *InviteCmd) Help() string {
method Run (line 30) | func (c *InviteCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
function createInvite (line 54) | func createInvite(ctx context.Context, f *factory.Factory, orgID string,...
FILE: cmd/version/update_check.go
type githubRelease (line 14) | type githubRelease struct
function CheckForUpdate (line 21) | func CheckForUpdate(currentVersion string) (string, bool) {
function isNewer (line 54) | func isNewer(a, b string) bool {
function parseVersion (line 74) | func parseVersion(v string) []int {
function FormatUpdateNudge (line 92) | func FormatUpdateNudge(latestVersion string) string {
FILE: cmd/version/update_check_test.go
function TestCheckForUpdate_NewerVersionAvailable (line 10) | func TestCheckForUpdate_NewerVersionAvailable(t *testing.T) {
function TestCheckForUpdate_SameVersion (line 27) | func TestCheckForUpdate_SameVersion(t *testing.T) {
function TestCheckForUpdate_OlderVersion (line 41) | func TestCheckForUpdate_OlderVersion(t *testing.T) {
function TestCheckForUpdate_DevVersion (line 55) | func TestCheckForUpdate_DevVersion(t *testing.T) {
function TestCheckForUpdate_NonReleaseVersionSkipsLookup (line 62) | func TestCheckForUpdate_NonReleaseVersionSkipsLookup(t *testing.T) {
function TestCheckForUpdate_ServerError (line 81) | func TestCheckForUpdate_ServerError(t *testing.T) {
function TestCheckForUpdate_InvalidJSON (line 95) | func TestCheckForUpdate_InvalidJSON(t *testing.T) {
function TestCheckForUpdate_ServerDown (line 109) | func TestCheckForUpdate_ServerDown(t *testing.T) {
function TestIsNewer (line 118) | func TestIsNewer(t *testing.T) {
function TestParseVersion (line 143) | func TestParseVersion(t *testing.T) {
FILE: cmd/version/version.go
type VersionCmd (line 11) | type VersionCmd struct
method Run (line 13) | func (c *VersionCmd) Run() error {
function Format (line 23) | func Format(ver string) string {
FILE: cmd/whoami/whoami.go
type WhoAmIOutput (line 19) | type WhoAmIOutput struct
method TextOutput (line 24) | func (w WhoAmIOutput) TextOutput() string {
type WhoAmICmd (line 39) | type WhoAmICmd struct
method Help (line 43) | func (c *WhoAmICmd) Help() string {
method Run (line 56) | func (c *WhoAmICmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags...
FILE: internal/agent/download.go
type ExistingInstall (line 20) | type ExistingInstall struct
function FindExisting (line 27) | func FindExisting(targetOS string) *ExistingInstall {
function ResolveLatestVersion (line 52) | func ResolveLatestVersion() (string, error) {
function BuildDownloadURL (line 80) | func BuildDownloadURL(version, os, arch string) string {
function BuildSHA256SumsURL (line 96) | func BuildSHA256SumsURL(version string) string {
function FetchExpectedSHA256 (line 105) | func FetchExpectedSHA256(sumsURL, archiveFilename string) (string, error) {
function VerifySHA256 (line 134) | func VerifySHA256(path, expected string) error {
function DownloadToTemp (line 156) | func DownloadToTemp(url string) (string, error) {
function ExtractBinary (line 182) | func ExtractBinary(archive, dest, targetOS string) error {
function BinaryName (line 190) | func BinaryName(targetOS string) string {
function extractTarGz (line 197) | func extractTarGz(archive, dest string) error {
function extractZip (line 241) | func extractZip(archive, dest string) error {
FILE: internal/agent/download_test.go
function TestBuildDownloadURL (line 18) | func TestBuildDownloadURL(t *testing.T) {
function TestBuildSHA256SumsURL (line 62) | func TestBuildSHA256SumsURL(t *testing.T) {
function TestFetchExpectedSHA256 (line 72) | func TestFetchExpectedSHA256(t *testing.T) {
function TestVerifySHA256 (line 112) | func TestVerifySHA256(t *testing.T) {
function TestBinaryName (line 139) | func TestBinaryName(t *testing.T) {
function TestExtractTarGz (line 162) | func TestExtractTarGz(t *testing.T) {
function TestExtractTarGz_MissingBinary (line 218) | func TestExtractTarGz_MissingBinary(t *testing.T) {
function TestExtractZip (line 253) | func TestExtractZip(t *testing.T) {
function TestExtractZip_MissingBinary (line 305) | func TestExtractZip_MissingBinary(t *testing.T) {
FILE: internal/agent/platform.go
function DefaultBinDir (line 9) | func DefaultBinDir(targetOS string) string {
function DefaultBuildPath (line 26) | func DefaultBuildPath(targetOS string) string {
function DefaultConfigPath (line 43) | func DefaultConfigPath(targetOS string) string {
FILE: internal/agent/platform_test.go
function TestDefaultBinDir (line 8) | func TestDefaultBinDir(t *testing.T) {
function TestDefaultBuildPath (line 32) | func TestDefaultBuildPath(t *testing.T) {
function TestDefaultConfigPath (line 56) | func TestDefaultConfigPath(t *testing.T) {
FILE: internal/agent/token.go
function FindCluster (line 15) | func FindCluster(ctx context.Context, f *factory.Factory, org, clusterID...
function CreateAgentToken (line 35) | func CreateAgentToken(ctx context.Context, f *factory.Factory, org, clus...
function WriteAgentConfig (line 48) | func WriteAgentConfig(path, token, buildPath string, tags []string) error {
FILE: internal/agent/token_test.go
function TestWriteAgentConfig (line 9) | func TestWriteAgentConfig(t *testing.T) {
function TestWriteAgentConfig_CreatesParentDirs (line 40) | func TestWriteAgentConfig_CreatesParentDirs(t *testing.T) {
FILE: internal/annotation/annotation.go
function StripTags (line 6) | func StripTags(html string) string {
FILE: internal/annotation/list.go
function AnnotationSummary (line 11) | func AnnotationSummary(annotation *buildkite.Annotation) string {
FILE: internal/artifact/artifact.go
function FormatBytes (line 6) | func FormatBytes(bytes int64) string {
FILE: internal/artifact/view.go
function ArtifactSummary (line 9) | func ArtifactSummary(artifact *buildkite.Artifact) string {
FILE: internal/build/build.go
type Build (line 3) | type Build struct
FILE: internal/build/resolver/cli.go
function ResolveFromPositionalArgument (line 14) | func ResolveFromPositionalArgument(args []string, index int, pipeline pi...
function parseBuildArg (line 36) | func parseBuildArg(ctx context.Context, arg string, pipeline pipelineRes...
FILE: internal/build/resolver/cli_test.go
function TestParseBuildArg (line 13) | func TestParseBuildArg(t *testing.T) {
FILE: internal/build/resolver/options/options.go
type OptionsFn (line 15) | type OptionsFn
type AggregateResolver (line 17) | type AggregateResolver
method WithResolverWhen (line 19) | func (ar AggregateResolver) WithResolverWhen(condition bool, resovler ...
function ResolveBranchFromFlag (line 27) | func ResolveBranchFromFlag(branch string) OptionsFn {
function ResolveBranchFromRepository (line 37) | func ResolveBranchFromRepository(repo *git.Repository) OptionsFn {
function getBranchFromGit (line 63) | func getBranchFromGit() (string, error) {
function ResolveUserFromFlag (line 79) | func ResolveUserFromFlag(user string) OptionsFn {
function ResolveCurrentUser (line 90) | func ResolveCurrentUser(ctx context.Context, f *factory.Factory) Options...
FILE: internal/build/resolver/options/options_test.go
function TestResolveBranchFromGitFallback (line 14) | func TestResolveBranchFromGitFallback(t *testing.T) {
function testRepository (line 50) | func testRepository(t *testing.T, remoteURLs ...string) *git.Repository {
FILE: internal/build/resolver/resolver.go
type BuildResolverFn (line 12) | type BuildResolverFn
type AggregateResolver (line 14) | type AggregateResolver
method Resolve (line 21) | func (ar AggregateResolver) Resolve(ctx context.Context) (*build.Build...
method WithResolverWhen (line 35) | func (ar AggregateResolver) WithResolverWhen(condition bool, resovler ...
function NewAggregateResolver (line 44) | func NewAggregateResolver(resolvers ...BuildResolverFn) AggregateResolver {
FILE: internal/build/resolver/url.go
function ResolveFromURL (line 12) | func ResolveFromURL(args []string) BuildResolverFn {
function splitBuildURL (line 27) | func splitBuildURL(url string) *build.Build {
FILE: internal/build/resolver/with_options.go
function ResolveBuildWithOpts (line 14) | func ResolveBuildWithOpts(f *factory.Factory, pipelineResolver pipelineR...
FILE: internal/build/state/state.go
type State (line 3) | type State
constant Scheduled (line 6) | Scheduled State = "scheduled"
constant Running (line 7) | Running State = "running"
constant Blocked (line 8) | Blocked State = "blocked"
constant Canceling (line 9) | Canceling State = "canceling"
constant Failing (line 10) | Failing State = "failing"
constant Passed (line 11) | Passed State = "passed"
constant Failed (line 12) | Failed State = "failed"
constant Canceled (line 13) | Canceled State = "canceled"
constant Skipped (line 14) | Skipped State = "skipped"
constant NotRun (line 15) | NotRun State = "not_run"
function IsTerminal (line 18) | func IsTerminal(state State) bool {
function IsIncomplete (line 27) | func IsIncomplete(state State) bool {
FILE: internal/build/state/state_test.go
function TestIsTerminal (line 5) | func TestIsTerminal(t *testing.T) {
function TestIsIncomplete (line 33) | func TestIsIncomplete(t *testing.T) {
FILE: internal/build/view/shared/summary.go
function BuildSummary (line 9) | func BuildSummary(b *buildkite.Build, organization, pipeline string) str...
function BuildSummaryWithJobs (line 14) | func BuildSummaryWithJobs(b *buildkite.Build, organization, pipeline str...
function RenderJobSummary (line 19) | func RenderJobSummary(j buildkite.Job) string {
FILE: internal/build/view/view.go
type ViewOptions (line 16) | type ViewOptions struct
method Validate (line 23) | func (o *ViewOptions) Validate() error {
type BuildView (line 37) | type BuildView struct
method Render (line 80) | func (v *BuildView) Render() string {
function NewBuildView (line 46) | func NewBuildView(build *buildkite.Build, artifacts []buildkite.Artifact...
function BuildSummary (line 56) | func BuildSummary(b *buildkite.Build, organization, pipeline string) str...
function BuildSummaryWithJobs (line 60) | func BuildSummaryWithJobs(b *buildkite.Build, organization, pipeline str...
function RenderJobSummary (line 75) | func RenderJobSummary(j buildkite.Job) string {
function buildSummary (line 109) | func buildSummary(b *buildkite.Build, organization, pipeline string) str...
function renderJobs (line 136) | func renderJobs(jobs []buildkite.Job) string {
function renderArtifacts (line 173) | func renderArtifacts(artifacts []buildkite.Artifact) string {
function renderAnnotations (line 190) | func renderAnnotations(annotations []buildkite.Annotation) string {
function filterScriptJobs (line 206) | func filterScriptJobs(jobs []buildkite.Job) []buildkite.Job {
function creatorName (line 216) | func creatorName(build *buildkite.Build) string {
function formatJobDuration (line 229) | func formatJobDuration(job buildkite.Job) string {
constant ellipsis (line 240) | ellipsis = "…"
function truncateText (line 242) | func truncateText(text string, maxLength int) string {
function formatDuration (line 250) | func formatDuration(d time.Duration) string {
function shortenCommit (line 257) | func shortenCommit(commit string) string {
FILE: internal/build/view/view_test.go
function TestBuildSummary_NilBuild (line 10) | func TestBuildSummary_NilBuild(t *testing.T) {
function TestBuildSummary_ValidBuild (line 24) | func TestBuildSummary_ValidBuild(t *testing.T) {
function TestBuildSummaryWithJobs_NilBuild (line 42) | func TestBuildSummaryWithJobs_NilBuild(t *testing.T) {
function TestBuildSummaryWithJobs_ValidBuild (line 53) | func TestBuildSummaryWithJobs_ValidBuild(t *testing.T) {
function TestBuildView_Render_NilBuild (line 73) | func TestBuildView_Render_NilBuild(t *testing.T) {
function TestBuildView_Render_ValidBuild (line 85) | func TestBuildView_Render_ValidBuild(t *testing.T) {
function TestCreatorName_NilBuild (line 118) | func TestCreatorName_NilBuild(t *testing.T) {
function TestCreatorName_WithCreator (line 126) | func TestCreatorName_WithCreator(t *testing.T) {
function TestCreatorName_WithAuthor (line 141) | func TestCreatorName_WithAuthor(t *testing.T) {
function TestCreatorName_NoCreatorOrAuthor (line 156) | func TestCreatorName_NoCreatorOrAuthor(t *testing.T) {
FILE: internal/build/watch/job.go
type FormattedJob (line 10) | type FormattedJob struct
method DisplayName (line 20) | func (j FormattedJob) DisplayName() string {
method Duration (line 31) | func (j FormattedJob) Duration() time.Duration {
method IsTerminalFailureState (line 42) | func (j FormattedJob) IsTerminalFailureState() bool {
method IsSoftFailed (line 46) | func (j FormattedJob) IsSoftFailed() bool {
method IsFailed (line 50) | func (j FormattedJob) IsFailed() bool {
function NewFormattedJob (line 15) | func NewFormattedJob(j buildkite.Job) FormattedJob {
FILE: internal/build/watch/test_tracker.go
type TestTracker (line 9) | type TestTracker struct
method Update (line 22) | func (t *TestTracker) Update(tests []buildkite.BuildTest) []buildkite....
function NewTestTracker (line 14) | func NewTestTracker() *TestTracker {
FILE: internal/build/watch/test_tracker_test.go
function TestTestTracker_Update (line 9) | func TestTestTracker_Update(t *testing.T) {
FILE: internal/build/watch/tracker.go
type trackedJob (line 12) | type trackedJob struct
type JobSummary (line 20) | type JobSummary struct
method String (line 32) | func (s JobSummary) String() string {
type BuildStatus (line 57) | type BuildStatus struct
type JobTracker (line 67) | type JobTracker struct
method Update (line 79) | func (t *JobTracker) Update(b buildkite.Build) BuildStatus {
method PassedJobs (line 137) | func (t *JobTracker) PassedJobs() []buildkite.Job {
method FailedJobs (line 150) | func (t *JobTracker) FailedJobs() []buildkite.Job {
method summarize (line 180) | func (t *JobTracker) summarize(b buildkite.Build) JobSummary {
function NewJobTracker (line 72) | func NewJobTracker() *JobTracker {
function sortJobsByStartTime (line 162) | func sortJobsByStartTime(jobs []buildkite.Job) {
function isActiveState (line 213) | func isActiveState(state string) bool {
FILE: internal/build/watch/tracker_test.go
function TestJobTracker_Update (line 11) | func TestJobTracker_Update(t *testing.T) {
function TestJobTracker_Update_RetriedJobs (line 240) | func TestJobTracker_Update_RetriedJobs(t *testing.T) {
function TestJobTracker_FailedJobs (line 374) | func TestJobTracker_FailedJobs(t *testing.T) {
function TestJobTracker_PassedJobs_ExcludesSuperseded (line 440) | func TestJobTracker_PassedJobs_ExcludesSuperseded(t *testing.T) {
function TestJobTracker_PassedJobs_SortedByStartTime (line 458) | func TestJobTracker_PassedJobs_SortedByStartTime(t *testing.T) {
function TestJobTracker_FailedJobs_SortedByStartTime (line 482) | func TestJobTracker_FailedJobs_SortedByStartTime(t *testing.T) {
function TestJobTracker_Summarize (line 502) | func TestJobTracker_Summarize(t *testing.T) {
function TestJobSummary_String (line 640) | func TestJobSummary_String(t *testing.T) {
function TestJob_DisplayName (line 683) | func TestJob_DisplayName(t *testing.T) {
function TestJob_Duration (line 704) | func TestJob_Duration(t *testing.T) {
FILE: internal/build/watch/watch.go
constant DefaultMaxConsecutiveErrors (line 17) | DefaultMaxConsecutiveErrors = 10
constant DefaultRequestTimeout (line 20) | DefaultRequestTimeout = 30 * time.Second
type StatusFunc (line 25) | type StatusFunc
type TestStatusFunc (line 29) | type TestStatusFunc
type WatchOpt (line 32) | type WatchOpt
type watchConfig (line 34) | type watchConfig struct
function WithRetriedJobs (line 41) | func WithRetriedJobs() WatchOpt {
function WithTestTracking (line 49) | func WithTestTracking(fn TestStatusFunc) WatchOpt {
function WatchBuild (line 57) | func WatchBuild(
function pollTestFailures (line 135) | func pollTestFailures(ctx context.Context, client *buildkite.Client, org...
function isPermanentTestPollingError (line 172) | func isPermanentTestPollingError(err error) bool {
FILE: internal/build/watch/watch_test.go
function TestWatchBuild (line 16) | func TestWatchBuild(t *testing.T) {
function TestPollTestFailures (line 262) | func TestPollTestFailures(t *testing.T) {
function newTestClient (line 339) | func newTestClient(t *testing.T, baseURL string) *buildkite.Client {
FILE: internal/cli/context.go
type GlobalFlags (line 3) | type GlobalFlags interface
type Globals (line 11) | type Globals struct
method SkipConfirmation (line 19) | func (g Globals) SkipConfirmation() bool {
method DisableInput (line 23) | func (g Globals) DisableInput() bool {
method IsQuiet (line 27) | func (g Globals) IsQuiet() bool {
method DisablePager (line 31) | func (g Globals) DisablePager() bool {
method EnableDebug (line 35) | func (g Globals) EnableDebug() bool {
FILE: internal/cluster/query.go
function GetQueues (line 12) | func GetQueues(ctx context.Context, f *factory.Factory, orgSlug string, ...
function GetQueueAgentCount (line 55) | func GetQueueAgentCount(ctx context.Context, f *factory.Factory, orgSlug...
FILE: internal/cluster/view.go
function ClusterViewTable (line 13) | func ClusterViewTable(c ...buildkite.Cluster) string {
function renderSingleClusterDetail (line 38) | func renderSingleClusterDetail(c buildkite.Cluster) string {
FILE: internal/config/config.go
constant DefaultGraphQLEndpoint (line 35) | DefaultGraphQLEndpoint = "https://graphql.buildkite.com/v1"
constant ExperimentPreflight (line 38) | ExperimentPreflight = "preflight"
constant DefaultExperiments (line 40) | DefaultExperiments = ExperimentPreflight
constant appData (line 42) | appData = "AppData"
constant configFilePath (line 43) | configFilePath = "bk.yaml"
constant localConfigFilePath (line 44) | localConfigFilePath = "." + configFilePath
constant xdgConfigHome (line 45) | xdgConfigHome = "XDG_CONFIG_HOME"
type orgConfig (line 48) | type orgConfig struct
type fileConfig (line 52) | type fileConfig struct
method getToken (line 554) | func (cfg fileConfig) getToken(org string) string {
type Config (line 67) | type Config struct
method OrganizationSlug (line 110) | func (conf *Config) OrganizationSlug() string {
method SelectOrganization (line 119) | func (conf *Config) SelectOrganization(org string, inGitRepo bool) err...
method APIToken (line 131) | func (conf *Config) APIToken() string {
method APITokenForOrg (line 137) | func (conf *Config) APITokenForOrg(org string) string {
method RefreshTokenForOrg (line 167) | func (conf *Config) RefreshTokenForOrg(org string) string {
method RefreshToken (line 181) | func (conf *Config) RefreshToken() string {
method HasStoredTokenForOrg (line 187) | func (conf *Config) HasStoredTokenForOrg(org string) bool {
method EnsureOrganization (line 209) | func (conf *Config) EnsureOrganization(org string) error {
method ConfiguredOrganizations (line 223) | func (conf *Config) ConfiguredOrganizations() []string {
method GetGraphQLEndpoint (line 231) | func (conf *Config) GetGraphQLEndpoint() string {
method RESTAPIEndpoint (line 239) | func (conf *Config) RESTAPIEndpoint() string {
method PagerDisabled (line 248) | func (conf *Config) PagerDisabled() bool {
method SetNoPager (line 263) | func (conf *Config) SetNoPager(v bool, saveLocal bool) error {
method OutputFormat (line 274) | func (conf *Config) OutputFormat() string {
method SetOutputFormat (line 283) | func (conf *Config) SetOutputFormat(v string, saveLocal bool) error {
method Quiet (line 294) | func (conf *Config) Quiet() bool {
method SetQuiet (line 306) | func (conf *Config) SetQuiet(v bool, saveLocal bool) error {
method NoInput (line 317) | func (conf *Config) NoInput() bool {
method SetNoInput (line 326) | func (conf *Config) SetNoInput(v bool) error {
method Pager (line 333) | func (conf *Config) Pager() string {
method SetPager (line 342) | func (conf *Config) SetPager(v string) error {
method TelemetryEnabled (line 350) | func (conf *Config) TelemetryEnabled() bool {
method SetTelemetry (line 363) | func (conf *Config) SetTelemetry(v bool) error {
method Experiments (line 370) | func (conf *Config) Experiments() string {
method HasExperiment (line 381) | func (conf *Config) HasExperiment(name string) bool {
method SetExperiments (line 391) | func (conf *Config) SetExperiments(v string) error {
method ClearAllOrganizations (line 410) | func (conf *Config) ClearAllOrganizations() error {
method HasConfiguredOrganization (line 416) | func (conf *Config) HasConfiguredOrganization(slug string) bool {
method PreferredPipelines (line 421) | func (conf *Config) PreferredPipelines() []pipeline.Pipeline {
method SetPreferredPipelines (line 440) | func (conf *Config) SetPreferredPipelines(pipelines []pipeline.Pipelin...
method writeUser (line 567) | func (conf *Config) writeUser() error {
method writeLocal (line 571) | func (conf *Config) writeLocal() error {
function New (line 76) | func New(fs afero.Fs, repo *git.Repository) *Config {
function lookupBoolEnv (line 396) | func lookupBoolEnv(key string) (bool, bool) {
function firstNonEmpty (line 454) | func firstNonEmpty(s ...string) string {
function configFile (line 465) | func configFile() string {
function createIfNotExistsConfigDir (line 481) | func createIfNotExistsConfigDir() (string, error) {
function loadFileConfig (line 500) | func loadFileConfig(fs afero.Fs, path string) (fileConfig, error) {
function writeFileConfig (line 532) | func writeFileConfig(fs afero.Fs, path string, cfg fileConfig) error {
FILE: internal/config/config_test.go
function setEnv (line 12) | func setEnv(t *testing.T, key, value string) {
function unsetEnv (line 30) | func unsetEnv(t *testing.T, key string) {
function prepareTestDirectory (line 40) | func prepareTestDirectory(fs afero.Fs, fixturePath, configPath string) e...
function TestConfig (line 65) | func TestConfig(t *testing.T) {
function TestAPITokenForOrgNoKeyring (line 326) | func TestAPITokenForOrgNoKeyring(t *testing.T) {
function TestExperiments (line 357) | func TestExperiments(t *testing.T) {
function TestHasExperimentEnvOverride (line 422) | func TestHasExperimentEnvOverride(t *testing.T) {
function TestHasExperiment (line 435) | func TestHasExperiment(t *testing.T) {
FILE: internal/emoji/emoji.go
function getRenderer (line 20) | func getRenderer() *termoji.Renderer {
function Render (line 41) | func Render(text string) string {
function Split (line 59) | func Split(text string) (prefix, rest string) {
FILE: internal/emoji/emoji_test.go
function TestRender_standardEmoji (line 7) | func TestRender_standardEmoji(t *testing.T) {
function TestRender_plainText (line 15) | func TestRender_plainText(t *testing.T) {
function TestSplit (line 22) | func TestSplit(t *testing.T) {
FILE: internal/errors/api.go
type APIErrorResponse (line 13) | type APIErrorResponse struct
function WrapAPIError (line 20) | func WrapAPIError(err error, operation string) error {
function handleHTTPError (line 43) | func handleHTTPError(httpErr *httpClient.ErrorResponse, operation string...
function handleBadRequestError (line 94) | func handleBadRequestError(httpErr *httpClient.ErrorResponse, details st...
function suggestForNotFound (line 115) | func suggestForNotFound(url string) []string {
FILE: internal/errors/api_test.go
function TestWrapAPIError (line 10) | func TestWrapAPIError(t *testing.T) {
function TestHandleHTTPError (line 57) | func TestHandleHTTPError(t *testing.T) {
type simpleError (line 226) | type simpleError struct
method Error (line 230) | func (e *simpleError) Error() string {
FILE: internal/errors/errors.go
type Error (line 52) | type Error struct
method Error (line 67) | func (e *Error) Error() string {
method FormattedError (line 96) | func (e *Error) FormattedError() string {
method Unwrap (line 131) | func (e *Error) Unwrap() error {
method Is (line 139) | func (e *Error) Is(target error) bool {
function NewError (line 144) | func NewError(original error, category error, details string, suggestion...
function WithSuggestions (line 154) | func WithSuggestions(err error, suggestions ...string) error {
function WithDetails (line 165) | func WithDetails(err error, details string) error {
function NewConfigurationError (line 180) | func NewConfigurationError(err error, details string, suggestions ...str...
function NewValidationError (line 185) | func NewValidationError(err error, details string, suggestions ...string...
function NewAPIError (line 190) | func NewAPIError(err error, details string, suggestions ...string) error {
function NewResourceNotFoundError (line 195) | func NewResourceNotFoundError(err error, details string, suggestions ......
function NewPermissionDeniedError (line 200) | func NewPermissionDeniedError(err error, details string, suggestions ......
function NewAuthenticationError (line 205) | func NewAuthenticationError(err error, details string, suggestions ...st...
function NewInternalError (line 210) | func NewInternalError(err error, details string, suggestions ...string) ...
function NewSnapshotError (line 215) | func NewSnapshotError(err error, details string, suggestions ...string) ...
function NewUserAbortedError (line 220) | func NewUserAbortedError(err error, details string, suggestions ...strin...
function NewPreflightCompletedFailureError (line 225) | func NewPreflightCompletedFailureError(err error, details string, sugges...
function NewPreflightIncompleteFailureError (line 230) | func NewPreflightIncompleteFailureError(err error, details string, sugge...
function NewPreflightIncompleteError (line 235) | func NewPreflightIncompleteError(err error, details string, suggestions ...
function NewPreflightUnknownError (line 240) | func NewPreflightUnknownError(err error, details string, suggestions ......
function IsNotFound (line 245) | func IsNotFound(err error) bool {
function IsValidationError (line 250) | func IsValidationError(err error) bool {
function IsAPIError (line 255) | func IsAPIError(err error) bool {
function IsAuthenticationError (line 260) | func IsAuthenticationError(err error) bool {
function IsPermissionDeniedError (line 265) | func IsPermissionDeniedError(err error) bool {
function IsConfigurationError (line 270) | func IsConfigurationError(err error) bool {
function IsPreflightCompletedFailure (line 275) | func IsPreflightCompletedFailure(err error) bool {
function IsPreflightIncompleteFailure (line 280) | func IsPreflightIncompleteFailure(err error) bool {
function IsPreflightIncomplete (line 285) | func IsPreflightIncomplete(err error) bool {
function IsPreflightUnknown (line 290) | func IsPreflightUnknown(err error) bool {
function IsUserAborted (line 295) | func IsUserAborted(err error) bool {
FILE: internal/errors/errors_test.go
function TestErrorInterface (line 10) | func TestErrorInterface(t *testing.T) {
function TestErrorCategorization (line 50) | func TestErrorCategorization(t *testing.T) {
function TestErrorWrapping (line 87) | func TestErrorWrapping(t *testing.T) {
function TestErrorCreationHelpers (line 171) | func TestErrorCreationHelpers(t *testing.T) {
FILE: internal/errors/handler.go
constant ExitCodeSuccess (line 12) | ExitCodeSuccess = 0
constant ExitCodeGenericError (line 14) | ExitCodeGenericError = 1
constant ExitCodeValidationError (line 16) | ExitCodeValidationError = 2
constant ExitCodeAPIError (line 17) | ExitCodeAPIError = 3
constant ExitCodeNotFoundError (line 18) | ExitCodeNotFoundError = 4
constant ExitCodePermissionError (line 19) | ExitCodePermissionError = 5
constant ExitCodeConfigError (line 20) | ExitCodeConfigError = 6
constant ExitCodeAuthError (line 21) | ExitCodeAuthError = 7
constant ExitCodeInternalError (line 22) | ExitCodeInternalError = 8
constant ExitCodePreflightCompletedFailure (line 23) | ExitCodePreflightCompletedFailure = 9
constant ExitCodePreflightIncompleteFailure (line 24) | ExitCodePreflightIncompleteFailure = 10
constant ExitCodePreflightIncomplete (line 25) | ExitCodePreflightIncomplete = 11
constant ExitCodePreflightUnknown (line 26) | ExitCodePreflightUnknown = 12
constant ExitCodeUserAbortedError (line 27) | ExitCodeUserAbortedError = 130
type Handler (line 31) | type Handler struct
method WithWriter (line 50) | func (h *Handler) WithWriter(w io.Writer) *Handler {
method WithExitFunc (line 56) | func (h *Handler) WithExitFunc(f func(int)) *Handler {
method WithVerbose (line 62) | func (h *Handler) WithVerbose(v bool) *Handler {
method Handle (line 68) | func (h *Handler) Handle(err error) {
method getExitCode (line 89) | func (h *Handler) getExitCode(err error) int {
method formatError (line 121) | func (h *Handler) formatError(err error) string {
method getCategoryPrefix (line 152) | func (h *Handler) getCategoryPrefix(category error) string {
method HandleWithDetails (line 184) | func (h *Handler) HandleWithDetails(err error, operation string) {
method PrintWarning (line 225) | func (h *Handler) PrintWarning(format string, args ...interface{}) {
function NewHandler (line 41) | func NewHandler() *Handler {
function MessageForError (line 231) | func MessageForError(err error) string {
function GetExitCodeForError (line 241) | func GetExitCodeForError(err error) int {
FILE: internal/errors/handler_test.go
function stripANSI (line 11) | func stripANSI(s string) string {
function TestHandler (line 34) | func TestHandler(t *testing.T) {
FILE: internal/graphql/generated.go
type CancelJobJobTypeCommandCancelJobTypeCommandCancelPayload (line 18) | type CancelJobJobTypeCommandCancelJobTypeCommandCancelPayload struct
method GetClientMutationId (line 25) | func (v *CancelJobJobTypeCommandCancelJobTypeCommandCancelPayload) Get...
method GetJobTypeCommand (line 30) | func (v *CancelJobJobTypeCommandCancelJobTypeCommandCancelPayload) Get...
type CancelJobJobTypeCommandCancelJobTypeCommandCancelPayloadJobTypeCommand (line 38) | type CancelJobJobTypeCommandCancelJobTypeCommandCancelPayloadJobTypeComm...
method GetId (line 49) | func (v *CancelJobJobTypeCommandCancelJobTypeCommandCancelPayloadJobTy...
method GetUuid (line 54) | func (v *CancelJobJobTypeCommandCancelJobTypeCommandCancelPayloadJobTy...
method GetState (line 59) | func (v *CancelJobJobTypeCommandCancelJobTypeCommandCancelPayloadJobTy...
method GetUrl (line 64) | func (v *CancelJobJobTypeCommandCancelJobTypeCommandCancelPayloadJobTy...
type CancelJobResponse (line 69) | type CancelJobResponse struct
method GetJobTypeCommandCancel (line 75) | func (v *CancelJobResponse) GetJobTypeCommandCancel() *CancelJobJobTyp...
type FindClustersOrganization (line 83) | type FindClustersOrganization struct
method GetClusters (line 89) | func (v *FindClustersOrganization) GetClusters() *FindClustersOrganiza...
type FindClustersOrganizationClustersClusterConnection (line 94) | type FindClustersOrganizationClustersClusterConnection struct
method GetEdges (line 100) | func (v *FindClustersOrganizationClustersClusterConnection) GetEdges()...
method GetPageInfo (line 105) | func (v *FindClustersOrganizationClustersClusterConnection) GetPageInf...
type FindClustersOrganizationClustersClusterConnectionEdgesClusterEdge (line 110) | type FindClustersOrganizationClustersClusterConnectionEdgesClusterEdge s...
method GetNode (line 115) | func (v *FindClustersOrganizationClustersClusterConnectionEdgesCluster...
type FindClustersOrganizationClustersClusterConnectionEdgesClusterEdgeNodeCluster (line 120) | type FindClustersOrganizationClustersClusterConnectionEdgesClusterEdgeNo...
method GetId (line 127) | func (v *FindClustersOrganizationClustersClusterConnectionEdgesCluster...
method GetName (line 132) | func (v *FindClustersOrganizationClustersClusterConnectionEdgesCluster...
type FindClustersOrganizationClustersClusterConnectionPageInfo (line 140) | type FindClustersOrganizationClustersClusterConnectionPageInfo struct
method GetHasNextPage (line 148) | func (v *FindClustersOrganizationClustersClusterConnectionPageInfo) Ge...
method GetEndCursor (line 153) | func (v *FindClustersOrganizationClustersClusterConnectionPageInfo) Ge...
type FindClustersResponse (line 158) | type FindClustersResponse struct
method GetOrganization (line 164) | func (v *FindClustersResponse) GetOrganization() *FindClustersOrganiza...
type FindQueuesForClusterNode (line 224) | type FindQueuesForClusterNode interface
function __unmarshalFindQueuesForClusterNode (line 312) | func __unmarshalFindQueuesForClusterNode(b []byte, v *FindQueuesForClust...
function __marshalFindQueuesForClusterNode (line 491) | func __marshalFindQueuesForClusterNode(v *FindQueuesForClusterNode) ([]b...
type FindQueuesForClusterNodeAPIAccessToken (line 923) | type FindQueuesForClusterNodeAPIAccessToken struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 230) | func (v *FindQueuesForClusterNodeAPIAccessToken) implementsGraphQLInte...
method GetTypename (line 928) | func (v *FindQueuesForClusterNodeAPIAccessToken) GetTypename() *string...
type FindQueuesForClusterNodeAPIAccessTokenCode (line 934) | type FindQueuesForClusterNodeAPIAccessTokenCode struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 232) | func (v *FindQueuesForClusterNodeAPIAccessTokenCode) implementsGraphQL...
method GetTypename (line 939) | func (v *FindQueuesForClusterNodeAPIAccessTokenCode) GetTypename() *st...
type FindQueuesForClusterNodeAPIApplication (line 945) | type FindQueuesForClusterNodeAPIApplication struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 234) | func (v *FindQueuesForClusterNodeAPIApplication) implementsGraphQLInte...
method GetTypename (line 950) | func (v *FindQueuesForClusterNodeAPIApplication) GetTypename() *string...
type FindQueuesForClusterNodeAgent (line 956) | type FindQueuesForClusterNodeAgent struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 236) | func (v *FindQueuesForClusterNodeAgent) implementsGraphQLInterfaceFind...
method GetTypename (line 961) | func (v *FindQueuesForClusterNodeAgent) GetTypename() *string { return...
type FindQueuesForClusterNodeAgentToken (line 967) | type FindQueuesForClusterNodeAgentToken struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 237) | func (v *FindQueuesForClusterNodeAgentToken) implementsGraphQLInterfac...
method GetTypename (line 972) | func (v *FindQueuesForClusterNodeAgentToken) GetTypename() *string { r...
type FindQueuesForClusterNodeAnnotation (line 978) | type FindQueuesForClusterNodeAnnotation struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 238) | func (v *FindQueuesForClusterNodeAnnotation) implementsGraphQLInterfac...
method GetTypename (line 983) | func (v *FindQueuesForClusterNodeAnnotation) GetTypename() *string { r...
type FindQueuesForClusterNodeArtifact (line 989) | type FindQueuesForClusterNodeArtifact struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 239) | func (v *FindQueuesForClusterNodeArtifact) implementsGraphQLInterfaceF...
method GetTypename (line 994) | func (v *FindQueuesForClusterNodeArtifact) GetTypename() *string { ret...
type FindQueuesForClusterNodeAuditEvent (line 1000) | type FindQueuesForClusterNodeAuditEvent struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 240) | func (v *FindQueuesForClusterNodeAuditEvent) implementsGraphQLInterfac...
method GetTypename (line 1005) | func (v *FindQueuesForClusterNodeAuditEvent) GetTypename() *string { r...
type FindQueuesForClusterNodeAuthorizationBitbucket (line 1011) | type FindQueuesForClusterNodeAuthorizationBitbucket struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 241) | func (v *FindQueuesForClusterNodeAuthorizationBitbucket) implementsGra...
method GetTypename (line 1016) | func (v *FindQueuesForClusterNodeAuthorizationBitbucket) GetTypename()...
type FindQueuesForClusterNodeAuthorizationGitHub (line 1022) | type FindQueuesForClusterNodeAuthorizationGitHub struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 243) | func (v *FindQueuesForClusterNodeAuthorizationGitHub) implementsGraphQ...
method GetTypename (line 1027) | func (v *FindQueuesForClusterNodeAuthorizationGitHub) GetTypename() *s...
type FindQueuesForClusterNodeAuthorizationGitHubApp (line 1033) | type FindQueuesForClusterNodeAuthorizationGitHubApp struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 245) | func (v *FindQueuesForClusterNodeAuthorizationGitHubApp) implementsGra...
method GetTypename (line 1038) | func (v *FindQueuesForClusterNodeAuthorizationGitHubApp) GetTypename()...
type FindQueuesForClusterNodeAuthorizationGitHubEnterprise (line 1044) | type FindQueuesForClusterNodeAuthorizationGitHubEnterprise struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 247) | func (v *FindQueuesForClusterNodeAuthorizationGitHubEnterprise) implem...
method GetTypename (line 1049) | func (v *FindQueuesForClusterNodeAuthorizationGitHubEnterprise) GetTyp...
type FindQueuesForClusterNodeAuthorizationGoogle (line 1057) | type FindQueuesForClusterNodeAuthorizationGoogle struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 249) | func (v *FindQueuesForClusterNodeAuthorizationGoogle) implementsGraphQ...
method GetTypename (line 1062) | func (v *FindQueuesForClusterNodeAuthorizationGoogle) GetTypename() *s...
type FindQueuesForClusterNodeAuthorizationSAML (line 1068) | type FindQueuesForClusterNodeAuthorizationSAML struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 251) | func (v *FindQueuesForClusterNodeAuthorizationSAML) implementsGraphQLI...
method GetTypename (line 1073) | func (v *FindQueuesForClusterNodeAuthorizationSAML) GetTypename() *str...
type FindQueuesForClusterNodeBuild (line 1079) | type FindQueuesForClusterNodeBuild struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 253) | func (v *FindQueuesForClusterNodeBuild) implementsGraphQLInterfaceFind...
method GetTypename (line 1084) | func (v *FindQueuesForClusterNodeBuild) GetTypename() *string { return...
type FindQueuesForClusterNodeChangelog (line 1090) | type FindQueuesForClusterNodeChangelog struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 254) | func (v *FindQueuesForClusterNodeChangelog) implementsGraphQLInterface...
method GetTypename (line 1095) | func (v *FindQueuesForClusterNodeChangelog) GetTypename() *string { re...
type FindQueuesForClusterNodeCluster (line 1098) | type FindQueuesForClusterNodeCluster struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 255) | func (v *FindQueuesForClusterNodeCluster) implementsGraphQLInterfaceFi...
method GetTypename (line 1107) | func (v *FindQueuesForClusterNodeCluster) GetTypename() *string { retu...
method GetId (line 1110) | func (v *FindQueuesForClusterNodeCluster) GetId() string { return v.Id }
method GetName (line 1113) | func (v *FindQueuesForClusterNodeCluster) GetName() string { return v....
method GetQueues (line 1116) | func (v *FindQueuesForClusterNodeCluster) GetQueues() *FindQueuesForCl...
type FindQueuesForClusterNodeClusterQueue (line 1121) | type FindQueuesForClusterNodeClusterQueue struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 256) | func (v *FindQueuesForClusterNodeClusterQueue) implementsGraphQLInterf...
method GetTypename (line 1126) | func (v *FindQueuesForClusterNodeClusterQueue) GetTypename() *string {...
type FindQueuesForClusterNodeClusterQueueToken (line 1132) | type FindQueuesForClusterNodeClusterQueueToken struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 257) | func (v *FindQueuesForClusterNodeClusterQueueToken) implementsGraphQLI...
method GetTypename (line 1137) | func (v *FindQueuesForClusterNodeClusterQueueToken) GetTypename() *str...
type FindQueuesForClusterNodeClusterQueuesClusterQueueConnection (line 1140) | type FindQueuesForClusterNodeClusterQueuesClusterQueueConnection struct
method GetEdges (line 1146) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnection) ...
method GetPageInfo (line 1151) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnection) ...
type FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEdgesClusterQueueEdge (line 1156) | type FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEdgesClu...
method GetNode (line 1161) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEd...
type FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEdgesClusterQueueEdgeNodeClusterQueue (line 1166) | type FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEdgesClu...
method GetId (line 1172) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEd...
method GetKey (line 1177) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionEd...
type FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionPageInfo (line 1185) | type FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionPageInfo...
method GetHasNextPage (line 1193) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionPa...
method GetEndCursor (line 1198) | func (v *FindQueuesForClusterNodeClusterQueuesClusterQueueConnectionPa...
type FindQueuesForClusterNodeClusterToken (line 1206) | type FindQueuesForClusterNodeClusterToken struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 259) | func (v *FindQueuesForClusterNodeClusterToken) implementsGraphQLInterf...
method GetTypename (line 1211) | func (v *FindQueuesForClusterNodeClusterToken) GetTypename() *string {...
type FindQueuesForClusterNodeEmail (line 1217) | type FindQueuesForClusterNodeEmail struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 260) | func (v *FindQueuesForClusterNodeEmail) implementsGraphQLInterfaceFind...
method GetTypename (line 1222) | func (v *FindQueuesForClusterNodeEmail) GetTypename() *string { return...
type FindQueuesForClusterNodeJobEventAssigned (line 1228) | type FindQueuesForClusterNodeJobEventAssigned struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 261) | func (v *FindQueuesForClusterNodeJobEventAssigned) implementsGraphQLIn...
method GetTypename (line 1233) | func (v *FindQueuesForClusterNodeJobEventAssigned) GetTypename() *stri...
type FindQueuesForClusterNodeJobEventBuildStepUploadCreated (line 1239) | type FindQueuesForClusterNodeJobEventBuildStepUploadCreated struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 263) | func (v *FindQueuesForClusterNodeJobEventBuildStepUploadCreated) imple...
method GetTypename (line 1244) | func (v *FindQueuesForClusterNodeJobEventBuildStepUploadCreated) GetTy...
type FindQueuesForClusterNodeJobEventCanceled (line 1252) | type FindQueuesForClusterNodeJobEventCanceled struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 265) | func (v *FindQueuesForClusterNodeJobEventCanceled) implementsGraphQLIn...
method GetTypename (line 1257) | func (v *FindQueuesForClusterNodeJobEventCanceled) GetTypename() *stri...
type FindQueuesForClusterNodeJobEventFinished (line 1263) | type FindQueuesForClusterNodeJobEventFinished struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 267) | func (v *FindQueuesForClusterNodeJobEventFinished) implementsGraphQLIn...
method GetTypename (line 1268) | func (v *FindQueuesForClusterNodeJobEventFinished) GetTypename() *stri...
type FindQueuesForClusterNodeJobEventGeneric (line 1274) | type FindQueuesForClusterNodeJobEventGeneric struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 269) | func (v *FindQueuesForClusterNodeJobEventGeneric) implementsGraphQLInt...
method GetTypename (line 1279) | func (v *FindQueuesForClusterNodeJobEventGeneric) GetTypename() *strin...
type FindQueuesForClusterNodeJobEventRetried (line 1285) | type FindQueuesForClusterNodeJobEventRetried struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 271) | func (v *FindQueuesForClusterNodeJobEventRetried) implementsGraphQLInt...
method GetTypename (line 1290) | func (v *FindQueuesForClusterNodeJobEventRetried) GetTypename() *strin...
type FindQueuesForClusterNodeJobEventTimedOut (line 1296) | type FindQueuesForClusterNodeJobEventTimedOut struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 273) | func (v *FindQueuesForClusterNodeJobEventTimedOut) implementsGraphQLIn...
method GetTypename (line 1301) | func (v *FindQueuesForClusterNodeJobEventTimedOut) GetTypename() *stri...
type FindQueuesForClusterNodeJobTypeBlock (line 1307) | type FindQueuesForClusterNodeJobTypeBlock struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 275) | func (v *FindQueuesForClusterNodeJobTypeBlock) implementsGraphQLInterf...
method GetTypename (line 1312) | func (v *FindQueuesForClusterNodeJobTypeBlock) GetTypename() *string {...
type FindQueuesForClusterNodeJobTypeCommand (line 1318) | type FindQueuesForClusterNodeJobTypeCommand struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 276) | func (v *FindQueuesForClusterNodeJobTypeCommand) implementsGraphQLInte...
method GetTypename (line 1323) | func (v *FindQueuesForClusterNodeJobTypeCommand) GetTypename() *string...
type FindQueuesForClusterNodeJobTypeTrigger (line 1329) | type FindQueuesForClusterNodeJobTypeTrigger struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 278) | func (v *FindQueuesForClusterNodeJobTypeTrigger) implementsGraphQLInte...
method GetTypename (line 1334) | func (v *FindQueuesForClusterNodeJobTypeTrigger) GetTypename() *string...
type FindQueuesForClusterNodeJobTypeWait (line 1340) | type FindQueuesForClusterNodeJobTypeWait struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 280) | func (v *FindQueuesForClusterNodeJobTypeWait) implementsGraphQLInterfa...
method GetTypename (line 1345) | func (v *FindQueuesForClusterNodeJobTypeWait) GetTypename() *string { ...
type FindQueuesForClusterNodeNotificationServiceSlack (line 1351) | type FindQueuesForClusterNodeNotificationServiceSlack struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 281) | func (v *FindQueuesForClusterNodeNotificationServiceSlack) implementsG...
method GetTypename (line 1356) | func (v *FindQueuesForClusterNodeNotificationServiceSlack) GetTypename...
type FindQueuesForClusterNodeOrganization (line 1362) | type FindQueuesForClusterNodeOrganization struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 283) | func (v *FindQueuesForClusterNodeOrganization) implementsGraphQLInterf...
method GetTypename (line 1367) | func (v *FindQueuesForClusterNodeOrganization) GetTypename() *string {...
type FindQueuesForClusterNodeOrganizationBanner (line 1373) | type FindQueuesForClusterNodeOrganizationBanner struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 284) | func (v *FindQueuesForClusterNodeOrganizationBanner) implementsGraphQL...
method GetTypename (line 1378) | func (v *FindQueuesForClusterNodeOrganizationBanner) GetTypename() *st...
type FindQueuesForClusterNodeOrganizationInvitation (line 1384) | type FindQueuesForClusterNodeOrganizationInvitation struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 286) | func (v *FindQueuesForClusterNodeOrganizationInvitation) implementsGra...
method GetTypename (line 1389) | func (v *FindQueuesForClusterNodeOrganizationInvitation) GetTypename()...
type FindQueuesForClusterNodeOrganizationMember (line 1395) | type FindQueuesForClusterNodeOrganizationMember struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 288) | func (v *FindQueuesForClusterNodeOrganizationMember) implementsGraphQL...
method GetTypename (line 1400) | func (v *FindQueuesForClusterNodeOrganizationMember) GetTypename() *st...
type FindQueuesForClusterNodePipeline (line 1406) | type FindQueuesForClusterNodePipeline struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 290) | func (v *FindQueuesForClusterNodePipeline) implementsGraphQLInterfaceF...
method GetTypename (line 1411) | func (v *FindQueuesForClusterNodePipeline) GetTypename() *string { ret...
type FindQueuesForClusterNodePipelineMetric (line 1417) | type FindQueuesForClusterNodePipelineMetric struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 291) | func (v *FindQueuesForClusterNodePipelineMetric) implementsGraphQLInte...
method GetTypename (line 1422) | func (v *FindQueuesForClusterNodePipelineMetric) GetTypename() *string...
type FindQueuesForClusterNodePipelineSchedule (line 1428) | type FindQueuesForClusterNodePipelineSchedule struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 293) | func (v *FindQueuesForClusterNodePipelineSchedule) implementsGraphQLIn...
method GetTypename (line 1433) | func (v *FindQueuesForClusterNodePipelineSchedule) GetTypename() *stri...
type FindQueuesForClusterNodePipelineTemplate (line 1439) | type FindQueuesForClusterNodePipelineTemplate struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 295) | func (v *FindQueuesForClusterNodePipelineTemplate) implementsGraphQLIn...
method GetTypename (line 1444) | func (v *FindQueuesForClusterNodePipelineTemplate) GetTypename() *stri...
type FindQueuesForClusterNodeSSOProviderGitHubApp (line 1450) | type FindQueuesForClusterNodeSSOProviderGitHubApp struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 297) | func (v *FindQueuesForClusterNodeSSOProviderGitHubApp) implementsGraph...
method GetTypename (line 1455) | func (v *FindQueuesForClusterNodeSSOProviderGitHubApp) GetTypename() *...
type FindQueuesForClusterNodeSSOProviderGoogleGSuite (line 1461) | type FindQueuesForClusterNodeSSOProviderGoogleGSuite struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 299) | func (v *FindQueuesForClusterNodeSSOProviderGoogleGSuite) implementsGr...
method GetTypename (line 1466) | func (v *FindQueuesForClusterNodeSSOProviderGoogleGSuite) GetTypename(...
type FindQueuesForClusterNodeSSOProviderSAML (line 1472) | type FindQueuesForClusterNodeSSOProviderSAML struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 301) | func (v *FindQueuesForClusterNodeSSOProviderSAML) implementsGraphQLInt...
method GetTypename (line 1477) | func (v *FindQueuesForClusterNodeSSOProviderSAML) GetTypename() *strin...
type FindQueuesForClusterNodeSecret (line 1483) | type FindQueuesForClusterNodeSecret struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 303) | func (v *FindQueuesForClusterNodeSecret) implementsGraphQLInterfaceFin...
method GetTypename (line 1488) | func (v *FindQueuesForClusterNodeSecret) GetTypename() *string { retur...
type FindQueuesForClusterNodeSuite (line 1494) | type FindQueuesForClusterNodeSuite struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 304) | func (v *FindQueuesForClusterNodeSuite) implementsGraphQLInterfaceFind...
method GetTypename (line 1499) | func (v *FindQueuesForClusterNodeSuite) GetTypename() *string { return...
type FindQueuesForClusterNodeTeam (line 1505) | type FindQueuesForClusterNodeTeam struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 305) | func (v *FindQueuesForClusterNodeTeam) implementsGraphQLInterfaceFindQ...
method GetTypename (line 1510) | func (v *FindQueuesForClusterNodeTeam) GetTypename() *string { return ...
type FindQueuesForClusterNodeTeamMember (line 1516) | type FindQueuesForClusterNodeTeamMember struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 306) | func (v *FindQueuesForClusterNodeTeamMember) implementsGraphQLInterfac...
method GetTypename (line 1521) | func (v *FindQueuesForClusterNodeTeamMember) GetTypename() *string { r...
type FindQueuesForClusterNodeTeamPipeline (line 1527) | type FindQueuesForClusterNodeTeamPipeline struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 307) | func (v *FindQueuesForClusterNodeTeamPipeline) implementsGraphQLInterf...
method GetTypename (line 1532) | func (v *FindQueuesForClusterNodeTeamPipeline) GetTypename() *string {...
type FindQueuesForClusterNodeTeamSuite (line 1538) | type FindQueuesForClusterNodeTeamSuite struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 308) | func (v *FindQueuesForClusterNodeTeamSuite) implementsGraphQLInterface...
method GetTypename (line 1543) | func (v *FindQueuesForClusterNodeTeamSuite) GetTypename() *string { re...
type FindQueuesForClusterNodeUser (line 1549) | type FindQueuesForClusterNodeUser struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 309) | func (v *FindQueuesForClusterNodeUser) implementsGraphQLInterfaceFindQ...
method GetTypename (line 1554) | func (v *FindQueuesForClusterNodeUser) GetTypename() *string { return ...
type FindQueuesForClusterNodeViewer (line 1560) | type FindQueuesForClusterNodeViewer struct
method implementsGraphQLInterfaceFindQueuesForClusterNode (line 310) | func (v *FindQueuesForClusterNodeViewer) implementsGraphQLInterfaceFin...
method GetTypename (line 1565) | func (v *FindQueuesForClusterNodeViewer) GetTypename() *string { retur...
type FindQueuesForClusterResponse (line 1568) | type FindQueuesForClusterResponse struct
method GetNode (line 1574) | func (v *FindQueuesForClusterResponse) GetNode() *FindQueuesForCluster...
method UnmarshalJSON (line 1576) | func (v *FindQueuesForClusterResponse) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 1614) | func (v *FindQueuesForClusterResponse) MarshalJSON() ([]byte, error) {
method __premarshalJSON (line 1622) | func (v *FindQueuesForClusterResponse) __premarshalJSON() (*__premarsh...
type __premarshalFindQueuesForClusterResponse (line 1610) | type __premarshalFindQueuesForClusterResponse struct
type FindUserByEmailOrganization (line 1646) | type FindUserByEmailOrganization struct
method GetMembers (line 1652) | func (v *FindUserByEmailOrganization) GetMembers() *FindUserByEmailOrg...
type FindUserByEmailOrganizationMembersOrganizationMemberConnection (line 1657) | type FindUserByEmailOrganizationMembersOrganizationMemberConnection struct
method GetEdges (line 1662) | func (v *FindUserByEmailOrganizationMembersOrganizationMemberConnectio...
type FindUserByEmailOrganizationMembersOrganizationMemberConnectionEdgesOrganizationMemberEdge (line 1667) | type FindUserByEmailOrganizationMembersOrganizationMemberConnectionEdges...
method GetNode (line 1672) | func (v *FindUserByEmailOrganizationMembersOrganizationMemberConnectio...
type FindUserByEmailOrganizationMembersOrganizationMemberConnectionEdgesOrganizationMemberEdgeNodeOrganizationMember (line 1680) | type FindUserByEmailOrganizationMembersOrganizationMemberConnectionEdges...
method GetUser (line 1685) | func (v *FindUserByEmailOrganizationMembersOrganizationMemberConnectio...
type FindUserByEmailOrganizationMembersOrganizationMemberConnectionEdgesOrganizationMemberEdgeNodeOrganizationMemberUser (line 1693) | type FindUserByEmailOrganizationMembersOrganizationMemberConnectionEdges...
method GetId (line 1698) | func (v *FindUserByEmailOrganizationMembersOrganizationMemberConnectio...
type FindUserByEmailResponse (line 1703) | type FindUserByEmailResponse struct
method GetOrganization (line 1709) | func (v *FindUserByEmailResponse) GetOrganization() *FindUserByEmailOr...
type GetClusterQueueAgentOrganization (line 1717) | type GetClusterQueueAgentOrganization struct
method GetAgents (line 1722) | func (v *GetClusterQueueAgentOrganization) GetAgents() *GetClusterQueu...
type GetClusterQueueAgentOrganizationAgentsAgentConnection (line 1727) | type GetClusterQueueAgentOrganizationAgentsAgentConnection struct
method GetEdges (line 1732) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnection) GetEdg...
type GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAgentEdge (line 1737) | type GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAgentEdge...
method GetNode (line 1742) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
type GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAgentEdgeNodeAgent (line 1750) | type GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAgentEdge...
method GetName (line 1762) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
method GetHostname (line 1767) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
method GetVersion (line 1772) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
method GetId (line 1777) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
method GetClusterQueue (line 1782) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
type GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAgentEdgeNodeAgentClusterQueue (line 1787) | type GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAgentEdge...
method GetId (line 1794) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
method GetUuid (line 1799) | func (v *GetClusterQueueAgentOrganizationAgentsAgentConnectionEdgesAge...
type GetClusterQueueAgentResponse (line 1804) | type GetClusterQueueAgentResponse struct
method GetOrganization (line 1810) | func (v *GetClusterQueueAgentResponse) GetOrganization() *GetClusterQu...
type GetClusterQueuesOrganization (line 1818) | type GetClusterQueuesOrganization struct
method GetCluster (line 1824) | func (v *GetClusterQueuesOrganization) GetCluster() *GetClusterQueuesO...
type GetClusterQueuesOrganizationCluster (line 1829) | type GetClusterQueuesOrganizationCluster struct
method GetName (line 1838) | func (v *GetClusterQueuesOrganizationCluster) GetName() string { retur...
method GetDescription (line 1841) | func (v *GetClusterQueuesOrganizationCluster) GetDescription() *string...
method GetQueues (line 1844) | func (v *GetClusterQueuesOrganizationCluster) GetQueues() *GetClusterQ...
type GetClusterQueuesOrganizationClusterQueuesClusterQueueConnection (line 1849) | type GetClusterQueuesOrganizationClusterQueuesClusterQueueConnection struct
method GetEdges (line 1854) | func (v *GetClusterQueuesOrganizationClusterQueuesClusterQueueConnecti...
type GetClusterQueuesOrganizationClusterQueuesClusterQueueConnectionEdgesClusterQueueEdge (line 1859) | type GetClusterQueuesOrganizationClusterQueuesClusterQueueConnectionEdge...
method GetNode (line 1864) | func (v *GetClusterQueuesOrganizationClusterQueuesClusterQueueConnecti...
type GetClusterQueuesOrganizationClusterQueuesClusterQueueConnectionEdgesClusterQueueEdgeNodeClusterQueue (line 1869) | type GetClusterQueuesOrganizationClusterQueuesClusterQueueConnectionEdge...
method GetId (line 1878) | func (v *GetClusterQueuesOrganizationClusterQueuesClusterQueueConnecti...
method GetUuid (line 1883) | func (v *GetClusterQueuesOrganizationClusterQueuesClusterQueueConnecti...
method GetKey (line 1888) | func (v *GetClusterQueuesOrganizationClusterQueuesClusterQueueConnecti...
method GetDescription (line 1893) | func (v *GetClusterQueuesOrganizationClusterQueuesClusterQueueConnecti...
type GetClusterQueuesResponse (line 1898) | type GetClusterQueuesResponse struct
method GetOrganization (line 1904) | func (v *GetClusterQueuesResponse) GetOrganization() *GetClusterQueues...
type GetOrganizationIDOrganization (line 1912) | type GetOrganizationIDOrganization struct
method GetId (line 1917) | func (v *GetOrganizationIDOrganization) GetId() string { return v.Id }
type GetOrganizationIDResponse (line 1920) | type GetOrganizationIDResponse struct
method GetOrganization (line 1926) | func (v *GetOrganizationIDResponse) GetOrganization() *GetOrganization...
type InviteUserOrganizationInvitationCreateOrganizationInvitationCreatePayload (line 1934) | type InviteUserOrganizationInvitationCreateOrganizationInvitationCreateP...
method GetClientMutationId (line 1940) | func (v *InviteUserOrganizationInvitationCreateOrganizationInvitationC...
type InviteUserResponse (line 1945) | type InviteUserResponse struct
method GetOrganizationInvitationCreate (line 1951) | func (v *InviteUserResponse) GetOrganizationInvitationCreate() *Invite...
type JobStates (line 1956) | type JobStates
constant JobStatesPending (line 1960) | JobStatesPending JobStates = "PENDING"
constant JobStatesWaiting (line 1962) | JobStatesWaiting JobStates = "WAITING"
constant JobStatesWaitingFailed (line 1964) | JobStatesWaitingFailed JobStates = "WAITING_FAILED"
constant JobStatesBlocked (line 1966) | JobStatesBlocked JobStates = "BLOCKED"
constant JobStatesBlockedFailed (line 1968) | JobStatesBlockedFailed JobStates = "BLOCKED_FAILED"
constant JobStatesUnblocked (line 1970) | JobStatesUnblocked JobStates = "UNBLOCKED"
constant JobStatesUnblockedFailed (line 1972) | JobStatesUnblockedFailed JobStates = "UNBLOCKED_FAILED"
constant JobStatesLimiting (line 1974) | JobStatesLimiting JobStates = "LIMITING"
constant JobStatesLimited (line 1976) | JobStatesLimited JobStates = "LIMITED"
constant JobStatesScheduled (line 1978) | JobStatesScheduled JobStates = "SCHEDULED"
constant JobStatesAssigned (line 1980) | JobStatesAssigned JobStates = "ASSIGNED"
constant JobStatesAccepted (line 1982) | JobStatesAccepted JobStates = "ACCEPTED"
constant JobStatesRunning (line 1984) | JobStatesRunning JobStates = "RUNNING"
constant JobStatesFinished (line 1986) | JobStatesFinished JobStates = "FINISHED"
constant JobStatesCanceling (line 1988) | JobStatesCanceling JobStates = "CANCELING"
constant JobStatesCanceled (line 1990) | JobStatesCanceled JobStates = "CANCELED"
constant JobStatesTimingOut (line 1992) | JobStatesTimingOut JobStates = "TIMING_OUT"
constant JobStatesTimedOut (line 1994) | JobStatesTimedOut JobStates = "TIMED_OUT"
constant JobStatesSkipped (line 1996) | JobStatesSkipped JobStates = "SKIPPED"
constant JobStatesBroken (line 1998) | JobStatesBroken JobStates = "BROKEN"
constant JobStatesExpired (line 2000) | JobStatesExpired JobStates = "EXPIRED"
type ListJobsByAgentQueryRulesOrganization (line 2031) | type ListJobsByAgentQueryRulesOrganization struct
method GetJobs (line 2036) | func (v *ListJobsByAgentQueryRulesOrganization) GetJobs() *ListJobsByA...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnection (line 2041) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnection struct
method GetEdges (line 2047) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnection) GetEd...
method GetPageInfo (line 2052) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnection) GetPa...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdge (line 2057) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdge ...
method GetNode (line 2062) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method UnmarshalJSON (line 2066) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method MarshalJSON (line 2104) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method __premarshalJSON (line 2112) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
type __premarshalListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdge (line 2100) | type __premarshalListJobsByAgentQueryRulesOrganizationJobsJobConnectionE...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2142) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeN...
function __unmarshalListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2157) | func __unmarshalListJobsByAgentQueryRulesOrganizationJobsJobConnectionEd...
function __marshalListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2192) | func __marshalListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdge...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeBlock (line 2240) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeN...
method implementsGraphQLInterfaceListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2148) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetTypename (line 2245) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommand (line 2253) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeN...
method implementsGraphQLInterfaceListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2150) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetTypename (line 2277) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetId (line 2282) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetUuid (line 2287) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetCommand (line 2292) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetState (line 2297) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetExitStatus (line 2302) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetUrl (line 2307) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetStartedAt (line 2312) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetFinishedAt (line 2317) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetCreatedAt (line 2322) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetAgent (line 2327) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandAgent (line 2335) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeN...
method GetId (line 2346) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetName (line 2351) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetHostname (line 2356) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetMetaData (line 2361) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeTrigger (line 2369) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeN...
method implementsGraphQLInterfaceListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2152) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetTypename (line 2374) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeWait (line 2382) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeN...
method implementsGraphQLInterfaceListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2154) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
method GetTypename (line 2387) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionEdgesJo...
type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionPageInfo (line 2395) | type ListJobsByAgentQueryRulesOrganizationJobsJobConnectionPageInfo struct
method GetEndCursor (line 2403) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionPageInf...
method GetHasNextPage (line 2408) | func (v *ListJobsByAgentQueryRulesOrganizationJobsJobConnectionPageInf...
type ListJobsByAgentQueryRulesResponse (line 2413) | type ListJobsByAgentQueryRulesResponse struct
method GetOrganization (line 2419) | func (v *ListJobsByAgentQueryRulesResponse) GetOrganization() *ListJob...
type ListJobsByQueueOrganization (line 2427) | type ListJobsByQueueOrganization struct
method GetJobs (line 2432) | func (v *ListJobsByQueueOrganization) GetJobs() *ListJobsByQueueOrgani...
type ListJobsByQueueOrganizationJobsJobConnection (line 2437) | type ListJobsByQueueOrganizationJobsJobConnection struct
method GetEdges (line 2443) | func (v *ListJobsByQueueOrganizationJobsJobConnection) GetEdges() []*L...
method GetPageInfo (line 2448) | func (v *ListJobsByQueueOrganizationJobsJobConnection) GetPageInfo() *...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge (line 2453) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge struct
method GetNode (line 2458) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge) Get...
method UnmarshalJSON (line 2462) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge) Unm...
method MarshalJSON (line 2500) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge) Mar...
method __premarshalJSON (line 2508) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge) __p...
type __premarshalListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge (line 2496) | type __premarshalListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdg...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2538) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob int...
function __unmarshalListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2553) | func __unmarshalListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdge...
function __marshalListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2588) | func __marshalListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNo...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeBlock (line 2636) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2544) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 2641) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommand (line 2649) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2546) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 2677) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetId (line 2682) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetUuid (line 2687) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetCommand (line 2692) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetState (line 2697) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetExitStatus (line 2702) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetUrl (line 2707) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetStartedAt (line 2712) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetFinishedAt (line 2717) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetCreatedAt (line 2722) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetCluster (line 2727) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetClusterQueue (line 2732) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetAgent (line 2737) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandAgent (line 2745) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method GetId (line 2756) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetName (line 2761) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetHostname (line 2766) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetMetaData (line 2771) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandCluster (line 2776) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method GetId (line 2783) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetName (line 2788) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandClusterQueue (line 2793) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method GetId (line 2799) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetKey (line 2804) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeTrigger (line 2812) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2548) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 2817) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeWait (line 2825) | type ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2550) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 2830) | func (v *ListJobsByQueueOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByQueueOrganizationJobsJobConnectionPageInfo (line 2838) | type ListJobsByQueueOrganizationJobsJobConnectionPageInfo struct
method GetEndCursor (line 2846) | func (v *ListJobsByQueueOrganizationJobsJobConnectionPageInfo) GetEndC...
method GetHasNextPage (line 2851) | func (v *ListJobsByQueueOrganizationJobsJobConnectionPageInfo) GetHasN...
type ListJobsByQueueResponse (line 2856) | type ListJobsByQueueResponse struct
method GetOrganization (line 2862) | func (v *ListJobsByQueueResponse) GetOrganization() *ListJobsByQueueOr...
type ListJobsByStateOrganization (line 2870) | type ListJobsByStateOrganization struct
method GetJobs (line 2875) | func (v *ListJobsByStateOrganization) GetJobs() *ListJobsByStateOrgani...
type ListJobsByStateOrganizationJobsJobConnection (line 2880) | type ListJobsByStateOrganizationJobsJobConnection struct
method GetEdges (line 2886) | func (v *ListJobsByStateOrganizationJobsJobConnection) GetEdges() []*L...
method GetPageInfo (line 2891) | func (v *ListJobsByStateOrganizationJobsJobConnection) GetPageInfo() *...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge (line 2896) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge struct
method GetNode (line 2901) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge) Get...
method UnmarshalJSON (line 2905) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge) Unm...
method MarshalJSON (line 2943) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge) Mar...
method __premarshalJSON (line 2951) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge) __p...
type __premarshalListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge (line 2939) | type __premarshalListJobsByStateOrganizationJobsJobConnectionEdgesJobEdg...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2981) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob int...
function __unmarshalListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2996) | func __unmarshalListJobsByStateOrganizationJobsJobConnectionEdgesJobEdge...
function __marshalListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 3031) | func __marshalListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNo...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeBlock (line 3079) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2987) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 3084) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommand (line 3092) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2989) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 3122) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetId (line 3127) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetUuid (line 3132) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetLabel (line 3137) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetCommand (line 3142) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetState (line 3147) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetExitStatus (line 3152) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetUrl (line 3157) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetStartedAt (line 3162) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetFinishedAt (line 3167) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetCreatedAt (line 3172) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetCluster (line 3177) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetClusterQueue (line 3182) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetAgent (line 3187) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandAgent (line 3195) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method GetId (line 3206) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetName (line 3211) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetHostname (line 3216) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetMetaData (line 3221) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandCluster (line 3226) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method GetId (line 3233) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetName (line 3238) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeCommandClusterQueue (line 3243) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method GetId (line 3249) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetKey (line 3254) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeTrigger (line 3262) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2991) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 3267) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobTypeWait (line 3275) | type ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJobType...
method implementsGraphQLInterfaceListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJob (line 2993) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
method GetTypename (line 3280) | func (v *ListJobsByStateOrganizationJobsJobConnectionEdgesJobEdgeNodeJ...
type ListJobsByStateOrganizationJobsJobConnectionPageInfo (line 3288) | type ListJobsByStateOrganizationJobsJobConnectionPageInfo struct
method GetEndCursor (line 3296) | func (v *ListJobsByStateOrganizationJobsJobConnectionPageInfo) GetEndC...
method GetHasNextPage (line 3301) | func (v *ListJobsByStateOrganizationJobsJobConnectionPageInfo) GetHasN...
type ListJobsByStateResponse (line 3306) | type ListJobsByStateResponse struct
method GetOrganization (line 3312) | func (v *ListJobsByStateResponse) GetOrganization() *ListJobsByStateOr...
type PipelineCreateWebhookPipelineCreateWebhookPipelineCreateWebhookPayload (line 3320) | type PipelineCreateWebhookPipelineCreateWebhookPipelineCreateWebhookPayl...
method GetClientMutationId (line 3327) | func (v *PipelineCreateWebhookPipelineCreateWebhookPipelineCreateWebho...
method GetPipelineID (line 3332) | func (v *PipelineCreateWebhookPipelineCreateWebhookPipelineCreateWebho...
type PipelineCreateWebhookResponse (line 3337) | type PipelineCreateWebhookResponse struct
method GetPipelineCreateWebhook (line 3343) | func (v *PipelineCreateWebhookResponse) GetPipelineCreateWebhook() *Pi...
type RetryJobJobTypeCommandRetryJobTypeCommandRetryPayload (line 3351) | type RetryJobJobTypeCommandRetryJobTypeCommandRetryPayload struct
method GetJobTypeCommand (line 3356) | func (v *RetryJobJobTypeCommandRetryJobTypeCommandRetryPayload) GetJob...
type RetryJobJobTypeCommandRetryJobTypeCommandRetryPayloadJobTypeCommand (line 3364) | type RetryJobJobTypeCommandRetryJobTypeCommandRetryPayloadJobTypeCommand...
method GetId (line 3373) | func (v *RetryJobJobTypeCommandRetryJobTypeCommandRetryPayloadJobTypeC...
method GetState (line 3378) | func (v *RetryJobJobTypeCommandRetryJobTypeCommandRetryPayloadJobTypeC...
method GetUrl (line 3383) | func (v *RetryJobJobTypeCommandRetryJobTypeCommandRetryPayloadJobTypeC...
type RetryJobResponse (line 3388) | type RetryJobResponse struct
method GetJobTypeCommandRetry (line 3394) | func (v *RetryJobResponse) GetJobTypeCommandRetry() *RetryJobJobTypeCo...
type UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayload (line 3402) | type UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayload struct
method GetJobTypeBlock (line 3407) | func (v *UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayload) GetJ...
type UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTypeBlock (line 3415) | type UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTypeBlock...
method GetId (line 3426) | func (v *UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTyp...
method GetState (line 3431) | func (v *UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTyp...
method GetIsUnblockable (line 3436) | func (v *UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTyp...
method GetBuild (line 3441) | func (v *UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTyp...
type UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTypeBlockBuild (line 3449) | type UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTypeBlock...
method GetUrl (line 3455) | func (v *UnblockJobJobTypeBlockUnblockJobTypeBlockUnblockPayloadJobTyp...
type UnblockJobResponse (line 3460) | type UnblockJobResponse struct
method GetJobTypeBlockUnblock (line 3466) | func (v *UnblockJobResponse) GetJobTypeBlockUnblock() *UnblockJobJobTy...
type __CancelJobInput (line 3471) | type __CancelJobInput struct
method GetJobId (line 3476) | func (v *__CancelJobInput) GetJobId() string { return v.JobId }
type __FindClustersInput (line 3479) | type __FindClustersInput struct
method GetOrg (line 3485) | func (v *__FindClustersInput) GetOrg() string { return v.Org }
method GetCursor (line 3488) | func (v *__FindClustersInput) GetCursor() *string { return v.Cursor }
type __FindQueuesForClusterInput (line 3491) | type __FindQueuesForClusterInput struct
method GetClusterId (line 3497) | func (v *__FindQueuesForClusterInput) GetClusterId() string { return v...
method GetCursor (line 3500) | func (v *__FindQueuesForClusterInput) GetCursor() *string { return v.C...
type __FindUserByEmailInput (line 3503) | type __FindUserByEmailInput struct
method GetOrganization (line 3509) | func (v *__FindUserByEmailInput) GetOrganization() string { return v.O...
method GetEmail (line 3512) | func (v *__FindUserByEmailInput) GetEmail() string { return v.Email }
type __GetClusterQueueAgentInput (line 3515) | type __GetClusterQueueAgentInput struct
method GetOrgSlug (line 3521) | func (v *__GetClusterQueueAgentInput) GetOrgSlug() string { return v.O...
method GetQueueId (line 3524) | func (v *__GetClusterQueueAgentInput) GetQueueId() []string { return v...
type __GetClusterQueuesInput (line 3527) | type __GetClusterQueuesInput struct
method GetOrgSlug (line 3533) | func (v *__GetClusterQueuesInput) GetOrgSlug() string { return v.OrgSl...
method GetClusterId (line 3536) | func (v *__GetClusterQueuesInput) GetClusterId() string { return v.Clu...
type __GetOrganizationIDInput (line 3539) | type __GetOrganizationIDInput struct
method GetSlug (line 3544) | func (v *__GetOrganizationIDInput) GetSlug() string { return v.Slug }
type __InviteUserInput (line 3547) | type __InviteUserInput struct
method GetOrganization (line 3553) | func (v *__InviteUserInput) GetOrganization() string { return v.Organi...
method GetEmails (line 3556) | func (v *__InviteUserInput) GetEmails() []string { return v.Emails }
type __ListJobsByAgentQueryRulesInput (line 3559) | type __ListJobsByAgentQueryRulesInput struct
method GetOrg (line 3567) | func (v *__ListJobsByAgentQueryRulesInput) GetOrg() string { return v....
method GetAgentQueryRules (line 3570) | func (v *__ListJobsByAgentQueryRulesInput) GetAgentQueryRules() []stri...
method GetFirst (line 3573) | func (v *__ListJobsByAgentQueryRulesInput) GetFirst() *int { return v....
method GetAfter (line 3576) | func (v *__ListJobsByAgentQueryRulesInput) GetAfter() *string { return...
type __ListJobsByQueueInput (line 3579) | type __ListJobsByQueueInput struct
method GetOrg (line 3587) | func (v *__ListJobsByQueueInput) GetOrg() string { return v.Org }
method GetClusterQueue (line 3590) | func (v *__ListJobsByQueueInput) GetClusterQueue() []string { return v...
method GetFirst (line 3593) | func (v *__ListJobsByQueueInput) GetFirst() *int { return v.First }
method GetAfter (line 3596) | func (v *__ListJobsByQueueInput) GetAfter() *string { return v.After }
type __ListJobsByStateInput (line 3599) | type __ListJobsByStateInput struct
method GetOrg (line 3607) | func (v *__ListJobsByStateInput) GetOrg() string { return v.Org }
method GetState (line 3610) | func (v *__ListJobsByStateInput) GetState() []JobStates { return v.Sta...
method GetFirst (line 3613) | func (v *__ListJobsByStateInput) GetFirst() *int { return v.First }
method GetAfter (line 3616) | func (v *__ListJobsByStateInput) GetAfter() *string { return v.After }
type __PipelineCreateWebhookInput (line 3619) | type __PipelineCreateWebhookInput struct
method GetId (line 3624) | func (v *__PipelineCreateWebhookInput) GetId() string { return v.Id }
type __RetryJobInput (line 3627) | type __RetryJobInput struct
method GetId (line 3632) | func (v *__RetryJobInput) GetId() string { return v.Id }
type __UnblockJobInput (line 3635) | type __UnblockJobInput struct
method GetId (line 3641) | func (v *__UnblockJobInput) GetId() string { return v.Id }
method GetFields (line 3644) | func (v *__UnblockJobInput) GetFields() *string { return v.Fields }
constant CancelJob_Operation (line 3647) | CancelJob_Operation = `
function CancelJob (line 3661) | func CancelJob(
constant FindClusters_Operation (line 3687) | FindClusters_Operation = `
function FindClusters (line 3706) | func FindClusters(
constant FindQueuesForCluster_Operation (line 3734) | FindQueuesForCluster_Operation = `
function FindQueuesForCluster (line 3758) | func FindQueuesForCluster(
constant FindUserByEmail_Operation (line 3786) | FindUserByEmail_Operation = `
function FindUserByEmail (line 3802) | func FindUserByEmail(
constant GetClusterQueueAgent_Operation (line 3830) | GetClusterQueueAgent_Operation = `
function GetClusterQueueAgent (line 3851) | func GetClusterQueueAgent(
constant GetClusterQueues_Operation (line 3879) | GetClusterQueues_Operation = `
function GetClusterQueues (line 3900) | func GetClusterQueues(
constant GetOrganizationID_Operation (line 3928) | GetOrganizationID_Operation = `
function GetOrganizationID (line 3936) | func GetOrganizationID(
constant InviteUser_Operation (line 3962) | InviteUser_Operation = `
function InviteUser (line 3970) | func InviteUser(
constant ListJobsByAgentQueryRules_Operation (line 3998) | ListJobsByAgentQueryRules_Operation = `
function ListJobsByAgentQueryRules (line 4033) | func ListJobsByAgentQueryRules(
constant ListJobsByQueue_Operation (line 4065) | ListJobsByQueue_Operation = `
function ListJobsByQueue (line 4108) | func ListJobsByQueue(
constant ListJobsByState_Operation (line 4140) | ListJobsByState_Operation = `
function ListJobsByState (line 4184) | func ListJobsByState(
constant PipelineCreateWebhook_Operation (line 4216) | PipelineCreateWebhook_Operation = `
function PipelineCreateWebhook (line 4225) | func PipelineCreateWebhook(
constant RetryJob_Operation (line 4251) | RetryJob_Operation = `
function RetryJob (line 4263) | func RetryJob(
constant UnblockJob_Operation (line 4289) | UnblockJob_Operation = `
function UnblockJob (line 4304) | func UnblockJob(
FILE: internal/http/client.go
type ErrorResponse (line 15) | type ErrorResponse struct
method Error (line 24) | func (e *ErrorResponse) Error() string {
method IsNotFound (line 106) | func (e *ErrorResponse) IsNotFound() bool {
method IsUnauthorized (line 111) | func (e *ErrorResponse) IsUnauthorized() bool {
method IsForbidden (line 116) | func (e *ErrorResponse) IsForbidden() bool {
method IsBadRequest (line 121) | func (e *ErrorResponse) IsBadRequest() bool {
method IsServerError (line 126) | func (e *ErrorResponse) IsServerError() bool {
method IsTooManyRequests (line 131) | func (e *ErrorResponse) IsTooManyRequests() bool {
type Client (line 38) | type Client struct
method Get (line 86) | func (c *Client) Get(ctx context.Context, endpoint string, v interface...
method Post (line 91) | func (c *Client) Post(ctx context.Context, endpoint string, body inter...
method Put (line 96) | func (c *Client) Put(ctx context.Context, endpoint string, body interf...
method Delete (line 101) | func (c *Client) Delete(ctx context.Context, endpoint string, v interf...
method Do (line 136) | func (c *Client) Do(ctx context.Context, method, endpoint string, body...
method send (line 183) | func (c *Client) send(ctx context.Context, method, reqURL string, body...
type ClientOption (line 46) | type ClientOption
function WithBaseURL (line 49) | func WithBaseURL(baseURL string) ClientOption {
function WithUserAgent (line 56) | func WithUserAgent(userAgent string) ClientOption {
function WithHTTPClient (line 63) | func WithHTTPClient(client *http.Client) ClientOption {
function NewClient (line 70) | func NewClient(token string, opts ...ClientOption) *Client {
FILE: internal/http/client_test.go
type testResponse (line 12) | type testResponse struct
function TestClient (line 16) | func TestClient(t *testing.T) {
function TestErrorResponse (line 260) | func TestErrorResponse(t *testing.T) {
FILE: internal/http/ratelimit.go
constant DefaultMaxRateLimitRetries (line 13) | DefaultMaxRateLimitRetries = 3
constant defaultFallbackDelay (line 17) | defaultFallbackDelay = 10 * time.Second
type OnRateLimitFunc (line 22) | type OnRateLimitFunc
type RateLimitTransport (line 27) | type RateLimitTransport struct
method RoundTrip (line 59) | func (t *RateLimitTransport) RoundTrip(req *http.Request) (*http.Respo...
function NewRateLimitTransport (line 46) | func NewRateLimitTransport(transport http.RoundTripper) *RateLimitTransp...
function parseRateLimitReset (line 113) | func parseRateLimitReset(resp *http.Response) (time.Duration, bool) {
FILE: internal/http/ratelimit_test.go
function TestRateLimitTransport (line 14) | func TestRateLimitTransport(t *testing.T) {
function TestParseRateLimitReset (line 268) | func TestParseRateLimitReset(t *testing.T) {
FILE: internal/http/refresh_transport.go
type TokenSource (line 20) | type TokenSource struct
method Token (line 31) | func (ts *TokenSource) Token() string {
method SetToken (line 38) | func (ts *TokenSource) SetToken(token string) {
function NewTokenSource (line 26) | func NewTokenSource(token string) *TokenSource {
type AuthTransport (line 48) | type AuthTransport struct
method RoundTrip (line 54) | func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, ...
type RefreshTransport (line 79) | type RefreshTransport struct
method base (line 88) | func (t *RefreshTransport) base() http.RoundTripper {
method RoundTrip (line 95) | func (t *RefreshTransport) RoundTrip(req *http.Request) (*http.Respons...
method doRefresh (line 150) | func (t *RefreshTransport) doRefresh(ctx context.Context, failedToken ...
function isTerminalRefreshError (line 195) | func isTerminalRefreshError(err error) bool {
function extractBearerToken (line 203) | func extractBearerToken(header string) string {
function bufferRequestBody (line 212) | func bufferRequestBody(req *http.Request) {
FILE: internal/http/refresh_transport_test.go
function TestRefreshTransport_PassesThroughNon401 (line 16) | func TestRefreshTransport_PassesThroughNon401(t *testing.T) {
function TestRefreshTransport_NoRefreshToken_PassesThrough401 (line 53) | func TestRefreshTransport_NoRefreshToken_PassesThrough401(t *testing.T) {
function TestRefreshTransport_CompareAfterLock_SkipsRedundantRefresh (line 90) | func TestRefreshTransport_CompareAfterLock_SkipsRedundantRefresh(t *test...
function TestRefreshTransport_DoesNotDeleteRefreshTokenOnTransientError (line 145) | func TestRefreshTransport_DoesNotDeleteRefreshTokenOnTransientError(t *t...
function TestRefreshTransport_BuffersAndRetriesPostBody (line 190) | func TestRefreshTransport_BuffersAndRetriesPostBody(t *testing.T) {
function TestRefreshTransport_ConcurrentRequestsOnlyRefreshOnce (line 244) | func TestRefreshTransport_ConcurrentRequestsOnlyRefreshOnce(t *testing.T) {
function TestTokenSource_ThreadSafe (line 314) | func TestTokenSource_ThreadSafe(t *testing.T) {
function TestIsTerminalRefreshError (line 334) | func TestIsTerminalRefreshError(t *testing.T) {
FILE: internal/io/confirm.go
function Confirm (line 26) | func Confirm(f *factory.Factory, prompt string) (bool, error) {
FILE: internal/io/input.go
function HasDataAvailable (line 13) | func HasDataAvailable(reader io.Reader) bool {
FILE: internal/io/pager.go
function Pager (line 18) | func Pager(noPager bool, pagerCmd ...string) (w io.Writer, cleanup func(...
function isTTY (line 87) | func isTTY() bool {
function isLessPager (line 94) | func isLessPager(path string) bool {
function hasFlag (line 99) | func hasFlag(args []string, flags ...string) bool {
FILE: internal/io/pager_test.go
function TestPagerReturnsStdoutWhenNoPagerTrue (line 9) | func TestPagerReturnsStdoutWhenNoPagerTrue(t *testing.T) {
function TestPagerReturnsStdoutWhenNotTTY (line 18) | func TestPagerReturnsStdoutWhenNotTTY(t *testing.T) {
function TestPagerReturnsStdoutWhenPagerNotFound (line 27) | func TestPagerReturnsStdoutWhenPagerNotFound(t *testing.T) {
function TestPagerReturnsStdoutWhenPagerEnvMalformed (line 41) | func TestPagerReturnsStdoutWhenPagerEnvMalformed(t *testing.T) {
function TestPagerReturnsStdoutWhenPagerEnvEmpty (line 55) | func TestPagerReturnsStdoutWhenPagerEnvEmpty(t *testing.T) {
function TestPagerCleanupIsIdempotent (line 69) | func TestPagerCleanupIsIdempotent(t *testing.T) {
function TestPagerWithCatCommand (line 92) | func TestPagerWithCatCommand(t *testing.T) {
function TestIsLessPager (line 110) | func TestIsLessPager(t *testing.T) {
function TestHasFlag (line 158) | func TestHasFlag(t *testing.T) {
function TestPagerAddsRawFlagToLess (line 225) | func TestPagerAddsRawFlagToLess(t *testing.T) {
function TestPagerWriteAndCleanup (line 268) | func TestPagerWriteAndCleanup(t *testing.T) {
function TestPagerCleanupAfterFailedStart (line 292) | func TestPagerCleanupAfterFailedStart(t *testing.T) {
FILE: internal/io/progress.go
function ProgressBar (line 8) | func ProgressBar(completed, total, width int) string {
function ProgressLine (line 25) | func ProgressLine(label string, completed, total, succeeded, failed, bar...
FILE: internal/io/progress_test.go
function TestProgressBar (line 5) | func TestProgressBar(t *testing.T) {
function TestProgressLine (line 37) | func TestProgressLine(t *testing.T) {
FILE: internal/io/prompt.go
constant typeOrganizationMessage (line 13) | typeOrganizationMessage = "Pick an organization"
constant typePipelineMessage (line 14) | typePipelineMessage = "Select a pipeline"
function PromptForOne (line 23) | func PromptForOne(resource string, options []string, noInput bool) (stri...
function renderedLineCount (line 68) | func renderedLineCount(message string, options []string, prompt string, ...
function wrappedLineCount (line 77) | func wrappedLineCount(s string, width int) int {
function PromptForInput (line 93) | func PromptForInput(prompt, defaultVal string, noInput bool) (string, er...
FILE: internal/io/prompt_test.go
function TestWrappedLineCount (line 5) | func TestWrappedLineCount(t *testing.T) {
function TestRenderedLineCount (line 31) | func TestRenderedLineCount(t *testing.T) {
FILE: internal/io/readline.go
function ReadLine (line 15) | func ReadLine() (string, error) {
function ReadPassword (line 54) | func ReadPassword() (string, error) {
FILE: internal/io/spinner.go
function SpinWhile (line 12) | func SpinWhile(f *factory.Factory, name string, action func() error) err...
FILE: internal/io/spinner_test.go
function TestSpinWhileWithoutTTY (line 11) | func TestSpinWhileWithoutTTY(t *testing.T) {
function TestSpinWhileActionIsExecuted (line 28) | func TestSpinWhileActionIsExecuted(t *testing.T) {
function TestSpinWhileWithError (line 45) | func TestSpinWhileWithError(t *testing.T) {
function TestSpinWhileTTYDetection (line 63) | func TestSpinWhileTTYDetection(t *testing.T) {
function TestSpinWhileQuiet (line 86) | func TestSpinWhileQuiet(t *testing.T) {
FILE: internal/io/terminal.go
constant clearPreviousLineANSI (line 11) | clearPreviousLineANSI = "\x1b[1A\r\x1b[2K"
function isTerminal (line 13) | func isTerminal(f *os.File) bool {
function terminalWidth (line 17) | func terminalWidth(f *os.File) int {
function clearPreviousLines (line 25) | func clearPreviousLines(f *os.File, lines int) {
FILE: internal/job/view.go
type Job (line 8) | type Job
method Summarise (line 16) | func (j Job) Summarise() string {
function JobSummary (line 11) | func JobSummary(job Job) string {
FILE: internal/pipeline/pipeline.go
type Pipeline (line 4) | type Pipeline struct
FILE: internal/pipeline/resolver/cli.go
function ResolveFromPositionalArgument (line 13) | func ResolveFromPositionalArgument(args []string, index int, conf *confi...
function parsePipelineArg (line 41) | func parsePipelineArg(arg string, conf *config.Config) (org, pipeline st...
FILE: internal/pipeline/resolver/cli_test.go
function TestParsePipelineArg (line 12) | func TestParsePipelineArg(t *testing.T) {
FILE: internal/pipeline/resolver/config.go
function ResolveFromConfig (line 10) | func ResolveFromConfig(conf *config.Config, picker PipelinePicker) Pipel...
FILE: internal/pipeline/resolver/config_test.go
function TestResolvePipelineFromConfig (line 12) | func TestResolvePipelineFromConfig(t *testing.T) {
FILE: internal/pipeline/resolver/flag.go
function ResolveFromFlag (line 11) | func ResolveFromFlag(flag string, conf *config.Config) PipelineResolverFn {
FILE: internal/pipeline/resolver/flag_test.go
function TestResolveFromFlag (line 12) | func TestResolveFromFlag(t *testing.T) {
FILE: internal/pipeline/resolver/picker.go
type PipelinePicker (line 15) | type PipelinePicker
function PassthruPicker (line 17) | func PassthruPicker(p []pipeline.Pipeline) *pipeline.Pipeline {
function PickOneWithFactory (line 23) | func PickOneWithFactory(f *factory.Factory) PipelinePicker {
function CachedPicker (line 60) | func CachedPicker(conf *config.Config, picker PipelinePicker) PipelinePi...
FILE: internal/pipeline/resolver/picker_test.go
type savedConfig (line 14) | type savedConfig struct
function readSavedConfig (line 19) | func readSavedConfig(t *testing.T, fs afero.Fs) savedConfig {
function TestPickers (line 38) | func TestPickers(t *testing.T) {
FILE: internal/pipeline/resolver/repository.go
function ResolveFromRepository (line 20) | func ResolveFromRepository(f *factory.Factory, picker PipelinePicker) Pi...
function ResolveFromRepositoryInOrg (line 26) | func ResolveFromRepositoryInOrg(f *factory.Factory, picker PipelinePicke...
function resolveFromRepositoryWithOrg (line 30) | func resolveFromRepositoryWithOrg(f *factory.Factory, picker PipelinePic...
function resolveFromRepository (line 52) | func resolveFromRepository(ctx context.Context, f *factory.Factory, org ...
function filterPipelines (line 66) | func filterPipelines(ctx context.Context, repoURLs []string, org string,...
function getRepoURLs (line 102) | func getRepoURLs(r *git.Repository) ([]string, error) {
function getRepoURLsFromGit (line 118) | func getRepoURLsFromGit(ctx context.Context) ([]string, error) {
FILE: internal/pipeline/resolver/repository_test.go
function TestResolvePipelinesFromPath (line 17) | func TestResolvePipelinesFromPath(t *testing.T) {
function TestResolvePipelinesFromGitFallback (line 99) | func TestResolvePipelinesFromGitFallback(t *testing.T) {
function testRepository (line 126) | func testRepository(t *testing.T, remoteURLs ...string) *git.Repository {
function testFactory (line 145) | func testFactory(t *testing.T, serverURL string, org string, repo *git.R...
function mockHTTPServer (line 162) | func mockHTTPServer(response string) *httptest.Server {
FILE: internal/pipeline/resolver/resolver.go
type PipelineResolverFn (line 13) | type PipelineResolverFn
type AggregateResolver (line 15) | type AggregateResolver
method Resolve (line 22) | func (pr AggregateResolver) Resolve(ctx context.Context) (*pipeline.Pi...
function NewAggregateResolver (line 38) | func NewAggregateResolver(resolvers ...PipelineResolverFn) AggregateReso...
function errorResolver (line 43) | func errorResolver(context.Context) (*pipeline.Pipeline, error) {
function WithOrg (line 49) | func WithOrg(org string, resolve PipelineResolverFn) PipelineResolverFn {
FILE: internal/pipeline/resolver/resolver_test.go
function TestAggregateResolver (line 11) | func TestAggregateResolver(t *testing.T) {
function TestWithOrg (line 45) | func TestWithOrg(t *testing.T) {
FILE: internal/preflight/branch_build.go
type BranchBuild (line 15) | type BranchBuild struct
method IsCompleted (line 23) | func (bb BranchBuild) IsCompleted() bool {
function ListRemotePreflightBranches (line 31) | func ListRemotePreflightBranches(dir string, debug bool) ([]BranchBuild,...
function LookupRemotePreflightBranch (line 37) | func LookupRemotePreflightBranch(dir, uuid string, debug bool) (*BranchB...
function lsRemotePreflightBranches (line 50) | func lsRemotePreflightBranches(dir, pattern string, debug bool) ([]Branc...
constant maxResolveBuildPages (line 83) | maxResolveBuildPages = 10
constant resolveBuildsPerPage (line 84) | resolveBuildsPerPage = 100
constant maxResolveBuildQueryLength (line 85) | maxResolveBuildQueryLength = 6000
function ResolveBuilds (line 90) | func ResolveBuilds(ctx context.Context, client *buildkite.Client, org, p...
function resolveBuildBranchBatches (line 132) | func resolveBuildBranchBatches(branches []BranchBuild) [][]string {
function resolveBuildQueryLength (line 156) | func resolveBuildQueryLength(branches []string) int {
FILE: internal/preflight/branch_build_test.go
function TestResolveBuilds_BatchesRequestsToAvoidLongQuery (line 15) | func TestResolveBuilds_BatchesRequestsToAvoidLongQuery(t *testing.T) {
FILE: internal/preflight/cleanup.go
function Cleanup (line 10) | func Cleanup(dir string, ref string, debug bool) error {
function CleanupRefs (line 25) | func CleanupRefs(dir string, refs []string, debug bool) error {
FILE: internal/preflight/cleanup_test.go
function TestBranchBuild_IsCompleted (line 10) | func TestBranchBuild_IsCompleted(t *testing.T) {
function TestCleanup (line 36) | func TestCleanup(t *testing.T) {
function TestCleanup_AlreadyDeleted (line 62) | func TestCleanup_AlreadyDeleted(t *testing.T) {
FILE: internal/preflight/exit_policy.go
type ExitPolicy (line 11) | type ExitPolicy
method UnmarshalText (line 18) | func (p *ExitPolicy) UnmarshalText(text []byte) error {
constant ExitOnBuildFailing (line 14) | ExitOnBuildFailing ExitPolicy = iota
constant ExitOnBuildTerminal (line 15) | ExitOnBuildTerminal
function EffectiveExitPolicy (line 32) | func EffectiveExitPolicy(policies []ExitPolicy) ExitPolicy {
function ValidateExitPolicies (line 39) | func ValidateExitPolicies(policies []ExitPolicy, watch bool) error {
FILE: internal/preflight/git.go
function gitCmdContext (line 13) | func gitCmdContext(ctx context.Context, dir string, env []string, args ....
function gitRun (line 21) | func gitRun(dir string, env []string, debug bool, args ...string) error {
function gitRunContext (line 26) | func gitRunContext(ctx context.Context, dir string, env []string, debug ...
function gitOutput (line 41) | func gitOutput(dir string, env []string, debug bool, args ...string) (st...
function gitOutputContext (line 46) | func gitOutputContext(ctx context.Context, dir string, env []string, deb...
function RepositoryRoot (line 64) | func RepositoryRoot(dir string, debug bool) (string, error) {
type SourceContext (line 69) | type SourceContext struct
function ResolveSourceContext (line 75) | func ResolveSourceContext(dir string, debug bool) (SourceContext, error) {
function tempIndexEnv (line 92) | func tempIndexEnv(path string) []string {
FILE: internal/preflight/run_summary.go
type SummaryOptions (line 12) | type SummaryOptions struct
type SummaryResult (line 16) | type SummaryResult struct
type SummaryTests (line 20) | type SummaryTests struct
type SummaryTestRun (line 25) | type SummaryTestRun struct
type SummaryTestFailure (line 34) | type SummaryTestFailure struct
type SummaryFailureDetail (line 45) | type SummaryFailureDetail struct
type RunSummaryService (line 50) | type RunSummaryService struct
method Get (line 101) | func (s *RunSummaryService) Get(ctx context.Context, org, buildID stri...
type RunSummaryGetOptions (line 54) | type RunSummaryGetOptions struct
type RunSummaryResponse (line 60) | type RunSummaryResponse struct
method SummaryResult (line 134) | func (r RunSummaryResponse) SummaryResult() SummaryResult {
type RunSummaryTests (line 64) | type RunSummaryTests struct
type RunSummaryRun (line 69) | type RunSummaryRun struct
type RunSummarySuite (line 76) | type RunSummarySuite struct
type RunSummaryFailure (line 82) | type RunSummaryFailure struct
method summaryFailure (line 156) | func (f RunSummaryFailure) summaryFailure() SummaryTestFailure {
type RunSummaryLatestFail (line 92) | type RunSummaryLatestFail struct
function NewRunSummaryService (line 97) | func NewRunSummaryService(client *buildkite.Client) *RunSummaryService {
FILE: internal/preflight/run_summary_test.go
function TestRunSummaryResponse_SummaryResult_PreservesRunsByRunID (line 5) | func TestRunSummaryResponse_SummaryResult_PreservesRunsByRunID(t *testin...
FILE: internal/preflight/snapshot.go
type FileChange (line 13) | type FileChange struct
method StatusSymbol (line 34) | func (f FileChange) StatusSymbol() string {
type SnapshotResult (line 19) | type SnapshotResult struct
method ShortCommit (line 26) | func (r SnapshotResult) ShortCommit() string {
type snapshotConfig (line 45) | type snapshotConfig struct
type SnapshotOption (line 50) | type SnapshotOption
function WithDebug (line 53) | func WithDebug() SnapshotOption {
function Snapshot (line 60) | func Snapshot(dir string, preflightID uuid.UUID, opts ...SnapshotOption)...
function SnapshotContext (line 66) | func SnapshotContext(ctx context.Context, dir string, preflightID uuid.U...
function diffFiles (line 137) | func diffFiles(dir string, env []string, debug bool) ([]FileChange, erro...
function diffFilesContext (line 141) | func diffFilesContext(ctx context.Context, dir string, env []string, deb...
FILE: internal/preflight/snapshot_test.go
function initTestRepo (line 19) | func initTestRepo(t *testing.T) string {
function runGit (line 49) | func runGit(t *testing.T, dir string, args ...string) string {
function TestSnapshot_CommittedChanges (line 63) | func TestSnapshot_CommittedChanges(t *testing.T) {
function TestSnapshotContext_CancelsPush (line 97) | func TestSnapshotContext_CancelsPush(t *testing.T) {
function TestSnapshot_UntrackedFiles (line 162) | func TestSnapshot_UntrackedFiles(t *testing.T) {
function TestSnapshot_DoesNotModifyRealIndex (line 183) | func TestSnapshot_DoesNotModifyRealIndex(t *testing.T) {
function TestSnapshot_UniquePreflightIDs (line 206) | func TestSnapshot_UniquePreflightIDs(t *testing.T) {
function TestSnapshotResult_ShortCommit (line 241) | func TestSnapshotResult_ShortCommit(t *testing.T) {
function setupDiffEnv (line 282) | func setupDiffEnv(t *testing.T, worktree string) []string {
function TestDiffFiles (line 305) | func TestDiffFiles(t *testing.T) {
function TestSnapshot_CleanWorktree (line 436) | func TestSnapshot_CleanWorktree(t *testing.T) {
FILE: internal/secret/view.go
function SecretViewTable (line 9) | func SecretViewTable(secrets ...buildkite.ClusterSecret) string {
FILE: internal/util/util.go
function GenerateGraphQLID (line 12) | func GenerateGraphQLID(prefix, uuid string) string {
function OpenInWebBrowser (line 21) | func OpenInWebBrowser(openInWeb bool, webUrl string) error {
FILE: internal/validation/errors.go
type ValidationErrors (line 8) | type ValidationErrors
method Error (line 19) | func (e ValidationErrors) Error() string {
type ValidationError (line 10) | type ValidationError struct
method Error (line 15) | func (e *ValidationError) Error() string {
FILE: internal/validation/rule.go
type Rule (line 3) | type Rule interface
FILE: internal/validation/validator.go
type Validator (line 9) | type Validator struct
method AddRule (line 19) | func (v *Validator) AddRule(field string, rule Rule) {
method Validate (line 24) | func (v *Validator) Validate(fields map[string]interface{}) error {
function New (line 13) | func New() *Validator {
type RequiredRule (line 46) | type RequiredRule struct
method Validate (line 48) | func (r RequiredRule) Validate(value interface{}) error {
type SlugRule (line 58) | type SlugRule struct
method Validate (line 60) | func (r SlugRule) Validate(value interface{}) error {
type UUIDRule (line 73) | type UUIDRule struct
method Validate (line 75) | func (r UUIDRule) Validate(value interface{}) error {
type MinValueRule (line 88) | type MinValueRule struct
method Validate (line 92) | func (r MinValueRule) Validate(value interface{}) error {
FILE: internal/validation/validator_test.go
function TestRequiredRule (line 8) | func TestRequiredRule(t *testing.T) {
function TestSlugRule (line 79) | func TestSlugRule(t *testing.T) {
function TestMinValueRule (line 138) | func TestMinValueRule(t *testing.T) {
function TestValidator (line 190) | func TestValidator(t *testing.T) {
function TestUUIDRule (line 276) | func TestUUIDRule(t *testing.T) {
FILE: main.go
type CLI (line 41) | type CLI struct
type VersionCmd (line 73) | type VersionCmd struct
type AuthCmd (line 76) | type AuthCmd struct
type AgentCmd (line 83) | type AgentCmd struct
type ApiCmd (line 92) | type ApiCmd struct
type ArtifactsCmd (line 95) | type ArtifactsCmd struct
type BuildCmd (line 99) | type BuildCmd struct
type ClusterCmd (line 108) | type ClusterCmd struct
type ConfigureCmd (line 115) | type ConfigureCmd struct
type JobCmd (line 118) | type JobCmd struct
type MaintainerCmd (line 126) | type MaintainerCmd struct
type OrganizationCmd (line 131) | type OrganizationCmd struct
type PackageCmd (line 134) | type PackageCmd struct
type PipelineCmd (line 137) | type PipelineCmd struct
type PreflightCmd (line 145) | type PreflightCmd struct
method Help (line 175) | func (c PreflightCmd) Help() string {
type QueueCmd (line 149) | type QueueCmd struct
type SecretCmd (line 158) | type SecretCmd struct
type SkillCmd (line 165) | type SkillCmd struct
type UserCmd (line 170) | type UserCmd struct
function handleError (line 179) | func handleError(err error) {
function newKongParser (line 183) | func newKongParser(cli *CLI, options ...kong.Option) (*kong.Kong, error) {
function renderHelp (line 199) | func renderHelp(args []string) (string, error) {
function renderPreflightHelp (line 220) | func renderPreflightHelp() (string, error) {
function isPreflightHelpRequest (line 241) | func isPreflightHelpRequest(args []string) bool {
function applyExperiments (line 253) | func applyExperiments(parser *kong.Kong, conf *config.Config) {
function main (line 262) | func main() {
function run (line 266) | func run() int {
FILE: main_test.go
function unsetEnv (line 13) | func unsetEnv(t *testing.T, key string) {
function TestApplyExperiments (line 34) | func TestApplyExperiments(t *testing.T) {
FILE: pkg/analytics/analytics.go
type Client (line 23) | type Client struct
method SetOrg (line 65) | func (c *Client) SetOrg(org string) {
method TrackCommand (line 72) | func (c *Client) TrackCommand(subcommand string, fullArgs []string, pr...
method Close (line 97) | func (c *Client) Close() {
function Init (line 30) | func Init(version string, enabled bool) *Client {
function getUserID (line 104) | func getUserID() string {
function ParseSubcommand (line 118) | func ParseSubcommand(kongCommand string) string {
FILE: pkg/analytics/logger.go
type noopLogger (line 5) | type noopLogger struct
method Debugf (line 7) | func (noopLogger) Debugf(format string, args ...interface{}) {}
method Logf (line 9) | func (noopLogger) Logf(format string, args ...interface{}) {}
method Warnf (line 11) | func (noopLogger) Warnf(format string, args ...interface{}) {}
method Errorf (line 13) | func (noopLogger) Errorf(format string, args ...interface{}) {}
FILE: pkg/cmd/factory/factory.go
type Factory (line 24) | type Factory struct
type FactoryOpt (line 38) | type FactoryOpt
type factoryConfig (line 40) | type factoryConfig struct
function WithDebug (line 48) | func WithDebug(debug bool) FactoryOpt {
function WithOrgOverride (line 57) | func WithOrgOverride(org string) FactoryOpt {
function WithTransport (line 65) | func WithTransport(t http.RoundTripper) FactoryOpt {
function WithUserAgentSuffix (line 72) | func WithUserAgentSuffix(suffix string) FactoryOpt {
type debugTransport (line 79) | type debugTransport struct
method RoundTrip (line 86) | func (d *debugTransport) RoundTrip(req *http.Request) (*http.Response,...
function redactBody (line 134) | func redactBody(dump string) string {
function redactHeaders (line 146) | func redactHeaders(headers http.Header) {
type gqlHTTPClient (line 161) | type gqlHTTPClient struct
method Do (line 176) | func (a *gqlHTTPClient) Do(req *http.Request) (*http.Response, error) {
function init (line 165) | func init() {
function buildUserAgent (line 169) | func buildUserAgent(suffix string) string {
function New (line 182) | func New(opts ...FactoryOpt) (*Factory, error) {
FILE: pkg/cmd/factory/factory_test.go
function TestRedactHeaders (line 13) | func TestRedactHeaders(t *testing.T) {
function TestRedactHeadersMultipleValues (line 61) | func TestRedactHeadersMultipleValues(t *testing.T) {
function TestDebugTransportPreservesRequestBody (line 80) | func TestDebugTransportPreservesRequestBody(t *testing.T) {
function TestDebugTransportHandlesNilBody (line 132) | func TestDebugTransportHandlesNilBody(t *testing.T) {
function TestBuildUserAgent (line 158) | func TestBuildUserAgent(t *testing.T) {
function TestNewUserAgent (line 180) | func TestNewUserAgent(t *testing.T) {
FILE: pkg/cmd/validation/config.go
function ValidateConfiguration (line 19) | func ValidateConfiguration(conf *config.Config, commandPath string) error {
function ValidateConfigurationForOrg (line 25) | func ValidateConfigurationForOrg(conf *config.Config, commandPath, org s...
function validateConfiguration (line 29) | func validateConfiguration(conf *config.Config, commandPath, orgOverride...
FILE: pkg/cmd/validation/config_test.go
function TestValidateConfiguration_ExemptCommands (line 13) | func TestValidateConfiguration_ExemptCommands(t *testing.T) {
function TestValidateConfiguration_MissingValues (line 31) | func TestValidateConfiguration_MissingValues(t *testing.T) {
function newTestConfig (line 83) | func newTestConfig(t *testing.T) *config.Config {
function captureStandardStreams (line 91) | func captureStandardStreams(t *testing.T, fn func()) (stdout, stderr str...
FILE: pkg/keyring/keyring.go
constant serviceName (line 13) | serviceName = "buildkite-cli"
constant refreshServiceName (line 14) | refreshServiceName = "buildkite-cli-refresh"
type Keyring (line 23) | type Keyring struct
method Set (line 36) | func (k *Keyring) Set(org, token string) error {
method Get (line 44) | func (k *Keyring) Get(org string) (string, error) {
method Delete (line 52) | func (k *Keyring) Delete(org string) error {
method SetRefreshToken (line 60) | func (k *Keyring) SetRefreshToken(org, token string) error {
method GetRefreshToken (line 68) | func (k *Keyring) GetRefreshToken(org string) (string, error) {
method DeleteRefreshToken (line 76) | func (k *Keyring) DeleteRefreshToken(org string) error {
method IsAvailable (line 84) | func (k *Keyring) IsAvailable() bool {
function New (line 29) | func New() *Keyring {
function MockForTesting (line 90) | func MockForTesting() {
function ResetForTesting (line 100) | func ResetForTesting() {
function isKeyringAvailable (line 106) | func isKeyringAvailable() bool {
FILE: pkg/keyring/keyring_test.go
function setEnv (line 10) | func setEnv(t *testing.T, key, value string) {
function TestIsKeyringAvailable (line 29) | func TestIsKeyringAvailable(t *testing.T) {
function TestNoKeyringGet (line 67) | func TestNoKeyringGet(t *testing.T) {
function TestNoKeyringSet (line 82) | func TestNoKeyringSet(t *testing.T) {
function TestNoKeyringDelete (line 93) | func TestNoKeyringDelete(t *testing.T) {
FILE: pkg/oauth/oauth.go
constant DefaultHost (line 21) | DefaultHost = "buildkite.com"
function ResolveScopes (line 108) | func ResolveScopes(input string) string {
type Config (line 140) | type Config struct
type CallbackResult (line 150) | type CallbackResult struct
type TokenResponse (line 157) | type TokenResponse struct
type Flow (line 168) | type Flow struct
method AuthorizationURL (line 224) | func (f *Flow) AuthorizationURL() string {
method WaitForCallback (line 247) | func (f *Flow) WaitForCallback(ctx context.Context) (*CallbackResult, ...
method ExchangeCode (line 326) | func (f *Flow) ExchangeCode(ctx context.Context, code string) (*TokenR...
method Close (line 431) | func (f *Flow) Close() error {
function NewFlow (line 176) | func NewFlow(cfg *Config) (*Flow, error) {
function RefreshAccessToken (line 374) | func RefreshAccessToken(ctx context.Context, host, clientID, refreshToke...
function generateCodeVerifier (line 439) | func generateCodeVerifier() (string, error) {
function generateCodeChallenge (line 448) | func generateCodeChallenge(verifier string) string {
function generateState (line 454) | func generateState() (string, error) {
FILE: pkg/oauth/oauth_test.go
function TestResolveScopes (line 9) | func TestResolveScopes(t *testing.T) {
function TestNewFlow_DefaultsToAllScopes (line 62) | func TestNewFlow_DefaultsToAllScopes(t *testing.T) {
function TestAuthorizationURL_IncludesOrganizationSlug (line 88) | func TestAuthorizationURL_IncludesOrganizationSlug(t *testing.T) {
function TestAuthorizationURL_IncludesOrganizationUUID (line 116) | func TestAuthorizationURL_IncludesOrganizationUUID(t *testing.T) {
function TestAuthorizationURL_UsesProvidedScopes (line 146) | func TestAuthorizationURL_UsesProvidedScopes(t *testing.T) {
FILE: pkg/oauth/refresh_test.go
function TestRefreshAccessToken_Success (line 10) | func TestRefreshAccessToken_Success(t *testing.T) {
function TestRefreshAccessToken_ErrorResponse (line 71) | func TestRefreshAccessToken_ErrorResponse(t *testing.T) {
FILE: pkg/output/color.go
function ColorEnabled (line 17) | func ColorEnabled() bool {
FILE: pkg/output/flags.go
type OutputFlags (line 6) | type OutputFlags struct
method AfterApply (line 14) | func (o *OutputFlags) AfterApply() error {
FILE: pkg/output/flags_test.go
function TestOutputFlags_AfterApply (line 5) | func TestOutputFlags_AfterApply(t *testing.T) {
FILE: pkg/output/output.go
type Format (line 12) | type Format
constant FormatJSON (line 16) | FormatJSON Format = "json"
constant FormatYAML (line 18) | FormatYAML Format = "yaml"
constant FormatText (line 20) | FormatText Format = "text"
constant DefaultFormat (line 21) | DefaultFormat Format = FormatJSON
function ResolveFormat (line 26) | func ResolveFormat(flagValue, configValue string) Format {
type Formatter (line 37) | type Formatter interface
function Write (line 43) | func Write(w io.Writer, v interface{}, format Format) error {
function WriteTextOrStructured (line 58) | func WriteTextOrStructured(w io.Writer, format Format, structuredValue i...
function writeJSON (line 67) | func writeJSON(w io.Writer, v interface{}) error {
function writeYAML (line 73) | func writeYAML(w io.Writer, v interface{}) error {
function writeText (line 79) | func writeText(w io.Writer, v interface{}) error {
FILE: pkg/output/output_test.go
function TestWriteTextOrStructured (line 9) | func TestWriteTextOrStructured(t *testing.T) {
FILE: pkg/output/table.go
constant ansiReset (line 18) | ansiReset = "\033[0m"
constant ansiBold (line 19) | ansiBold = "\033[1m"
constant ansiDim (line 20) | ansiDim = "\033[2m"
constant ansiItalic (line 21) | ansiItalic = "\033[3m"
constant ansiUnderline (line 22) | ansiUnderline = "\033[4m"
constant ansiDimUnder (line 23) | ansiDimUnder = "\033[2;4m"
constant ansiStrikeThrough (line 24) | ansiStrikeThrough = "\033[9m"
constant colSeparator (line 25) | colSeparator = " "
constant minColumnWidth (line 26) | minColumnWidth = 3
constant ellipsisWidth (line 27) | ellipsisWidth = 3
constant defaultTableWidth (line 28) | defaultTableWidth = 120
function Table (line 34) | func Table(headers []string, rows [][]string, columnStyles map[string]st...
function displayWidth (line 136) | func displayWidth(s string) int {
function writePadded (line 141) | func writePadded(builder *strings.Builder, s string, width int) {
function truncateToWidth (line 149) | func truncateToWidth(s string, width int) string {
function trimToWidth (line 166) | func trimToWidth(s string, width int) string {
function clampColumnWidths (line 215) | func clampColumnWidths(colWidths []int, colCount, separatorWidth, maxWid...
function detectedTableWidth (line 331) | func detectedTableWidth() int {
FILE: pkg/output/table_test.go
function TestTableTruncatesWhenWidthExceeded (line 9) | func TestTableTruncatesWhenWidthExceeded(t *testing.T) {
function TestTableProportionalClampPreservesShortColumn (line 29) | func TestTableProportionalClampPreservesShortColumn(t *testing.T) {
function TestTableRespectsNoTruncationWhenWidthIsLarge (line 53) | func TestTableRespectsNoTruncationWhenWidthIsLarge(t *testing.T) {
function TestTableFitsWhenMaxWidthSmallerThanColumnCount (line 72) | func TestTableFitsWhenMaxWidthSmallerThanColumnCount(t *testing.T) {
function TestTableFitsWhenSeparatorsExceedMaxWidth (line 93) | func TestTableFitsWhenSeparatorsExceedMaxWidth(t *testing.T) {
function TestTrimToWidthPreservesANSICodes (line 114) | func TestTrimToWidthPreservesANSICodes(t *testing.T) {
function TestTableHandlesComplexUnicode (line 189) | func TestTableHandlesComplexUnicode(t *testing.T) {
function TestTrimToWidthWithComplexUnicode (line 353) | func TestTrimToWidthWithComplexUnicode(t *testing.T) {
FILE: pkg/output/value.go
function ValueOrDash (line 5) | func ValueOrDash(s string) string {
FILE: pkg/output/viewable.go
type Viewable (line 10) | type Viewable struct
method TextOutput (line 16) | func (v Viewable[T]) TextOutput() string {
method MarshalJSON (line 21) | func (v Viewable[T]) MarshalJSON() ([]byte, error) {
method MarshalYAML (line 26) | func (v Viewable[T]) MarshalYAML() (interface{}, error) {
FILE: pkg/output/viewable_test.go
function TestViewable_TextOutput (line 10) | func TestViewable_TextOutput(t *testing.T) {
function TestViewable_MarshalJSON (line 32) | func TestViewable_MarshalJSON(t *testing.T) {
function TestViewable_MarshalYAML (line 60) | func TestViewable_MarshalYAML(t *testing.T) {
Condensed preview — 272 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,594K chars).
[
{
"path": ".buildkite/hooks/pre-command",
"chars": 397,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\n\ncheckout_path=\"${BUILDKITE_BUILD_CHECKOUT_PATH:-$(pwd)}\"\ncache_root=\"${checkout_p"
},
{
"path": ".buildkite/pipeline.release.yml",
"chars": 1720,
"preview": "agents:\n queue: hosted\n\ncache: \".buildkite/cache-volume\"\n\nsteps:\n - label: \":terminal: build ({{matrix}})\"\n key: bu"
},
{
"path": ".buildkite/pipeline.yml",
"chars": 2777,
"preview": "agents:\n queue: hosted\n\ncache: \".buildkite/cache-volume\"\n\nsteps:\n - name: \":golangci-lint: lint\"\n key: lint\n com"
},
{
"path": ".buildkite/release.sh",
"chars": 926,
"preview": "#!/usr/bin/env bash\n\n#\n# This script is used to build a release of the CLI and publish it to multiple registries on Buil"
},
{
"path": ".buildkite/tag.sh",
"chars": 1526,
"preview": "#!/usr/bin/env bash\n\n#\n# This script calculates the next semantic version and pushes a tag\n#\n\nset -euo pipefail\n\nRELEASE"
},
{
"path": ".buildkite/upload-packages.sh",
"chars": 1496,
"preview": "#!/bin/env bash\n\n#\n# This script is used to upload packages to Buildkite registries\n#\n\nset -uo pipefail\n\nif [[ -z \"${1}\""
},
{
"path": ".dockerignore",
"chars": 495,
"preview": "# Git files\n.git\n.github\n.gitignore\n\n# Documentation\n*.md\ndocs/\nimages/\nLICENSE.md\nCHANGELOG.md\nCONTRIBUTING.md\nAGENT.md"
},
{
"path": ".github/CODEOWNERS",
"chars": 44,
"preview": "* @buildkite/support @buildkite/engineering\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.yml",
"chars": 1400,
"preview": "name: 🐛 Bug Report\ndescription: File a bug report for the Buildkite CLI\ntitle: \"[Bug]: \"\nlabels: [\"bug\", \"triage\"]\nproje"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 315,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Buildkite Community Forum\n url: https://forum.buildkite.communit"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.yml",
"chars": 1004,
"preview": "name: 💡 Feature Request\ndescription: Suggest an idea for this project.\ntitle: \"💡 feat: <title>\"\nlabels: [Enhancement]\nbo"
},
{
"path": ".github/pull_request_template.md",
"chars": 1172,
"preview": "### Description\n\n<!--\n- What problem are you trying to solve, and how are you solving it?\n- What alternatives did you co"
},
{
"path": ".gitignore",
"chars": 87,
"preview": "*.DS_STORE\ndist/\nbuildkite.yaml\n.bk.yaml\nbuild-logs-*\nmise.local.toml\n.mise.local.toml\n"
},
{
"path": ".golangci.yaml",
"chars": 546,
"preview": "version: \"2\"\nlinters:\n enable:\n - nolintlint\n - tparallel\n exclusions:\n generated: lax\n presets:\n - c"
},
{
"path": ".goreleaser.yaml",
"chars": 3856,
"preview": "project_name: bk\nversion: 2\n\nrelease:\n name_template: Buildkite CLI {{.Version}}\n draft: true\n replace_existing_draft"
},
{
"path": ".graphqlrc.yml",
"chars": 23,
"preview": "schema: schema.graphql\n"
},
{
"path": "AGENT.md",
"chars": 595,
"preview": "This project is the Buildkite CLI (`bk`)\n\n## Commands\n- Bootstrap: `mise install`\n- Hooks: `mise run hooks`\n- Format: `m"
},
{
"path": "CONTRIBUTING.md",
"chars": 2125,
"preview": "# Contributing\n\nWe welcome contributions from the community to make Buildkite CLI, `bk`, project even better.\n\n## Gettin"
},
{
"path": "Dockerfile",
"chars": 369,
"preview": "FROM golang:1.26-alpine AS base\n\nRUN apk add --no-cache git ca-certificates\n\nWORKDIR /base\n\nCOPY go.mod go.sum ./\n\nRUN g"
},
{
"path": "LICENSE.md",
"chars": 1079,
"preview": "MIT License\n\nCopyright (c) 2014-2023 Buildkite Pty Ltd\n\nPermission is hereby granted, free of charge, to any person obta"
},
{
"path": "README.md",
"chars": 1308,
"preview": "# bk - The Buildkite CLI\n\n[\n\nfunc Tes"
},
{
"path": "cmd/agent/install.go",
"chars": 4615,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\""
},
{
"path": "cmd/agent/list.go",
"chars": 6591,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"slices\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildki"
},
{
"path": "cmd/agent/list_test.go",
"chars": 13297,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"git"
},
{
"path": "cmd/agent/pause.go",
"chars": 2827,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"g"
},
{
"path": "cmd/agent/pause_test.go",
"chars": 1525,
"preview": "package agent\n\nimport (\n\t\"testing\"\n)\n\nfunc TestPauseCmdValidation(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\t"
},
{
"path": "cmd/agent/resume.go",
"chars": 1188,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"g"
},
{
"path": "cmd/agent/resume_test.go",
"chars": 517,
"preview": "package agent\n\nimport (\n\t\"testing\"\n)\n\nfunc TestResumeCmdStructure(t *testing.T) {\n\tt.Parallel()\n\n\tcmd := &ResumeCmd{\n\t\tA"
},
{
"path": "cmd/agent/run.go",
"chars": 4699,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strings\"\n\t\"syscall"
},
{
"path": "cmd/agent/stop.go",
"chars": 5564,
"preview": "package agent\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"sync\"\n\t\"syscall\"\n\n\t\"github."
},
{
"path": "cmd/agent/stop_test.go",
"chars": 5178,
"preview": "package agent\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/internal/config\"\n\tbkIO \"github.com/b"
},
{
"path": "cmd/agent/util.go",
"chars": 713,
"preview": "package agent\n\nimport (\n\t\"net/url\"\n\t\"strings\"\n\n\t\"github.com/buildkite/cli/v3/internal/config\"\n)\n\nfunc parseAgentArg(agen"
},
{
"path": "cmd/agent/view.go",
"chars": 3809,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite"
},
{
"path": "cmd/agent/view_test.go",
"chars": 1212,
"preview": "package agent\n\nimport \"testing\"\n\nfunc TestParseMetadata(t *testing.T) {\n\tcases := []struct {\n\t\tname string\n\t\tinput "
},
{
"path": "cmd/api/api.go",
"chars": 6826,
"preview": "package api\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/Kha"
},
{
"path": "cmd/api/api_test.go",
"chars": 1873,
"preview": "package api\n\nimport (\n\t\"testing\"\n)\n\nfunc TestBuildFullEndpoint(t *testing.T) {\n\tt.Parallel()\n\n\ttestcases := map[string]s"
},
{
"path": "cmd/artifacts/download.go",
"chars": 7303,
"preview": "package artifacts\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildRes"
},
{
"path": "cmd/artifacts/list.go",
"chars": 5162,
"preview": "package artifacts\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/i"
},
{
"path": "cmd/auth/login.go",
"chars": 6464,
"preview": "package auth\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildkite \"g"
},
{
"path": "cmd/auth/login_test.go",
"chars": 1112,
"preview": "package auth\n\nimport \"testing\"\n\nfunc TestOrganizationIdentifier(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struct {\n\t\tna"
},
{
"path": "cmd/auth/logout.go",
"chars": 1765,
"preview": "package auth\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"github.com/bu"
},
{
"path": "cmd/auth/status.go",
"chars": 2213,
"preview": "// Package auth handles commands related to authentication via the CLI\npackage auth\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\""
},
{
"path": "cmd/auth/switch.go",
"chars": 1797,
"preview": "package auth\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"github.com/buildkite/cli/v3/internal/config"
},
{
"path": "cmd/auth/switch_test.go",
"chars": 4034,
"preview": "package auth\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/internal/config\"\n\t\"github.com/sp"
},
{
"path": "cmd/auth/token.go",
"chars": 1015,
"preview": "package auth\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"github."
},
{
"path": "cmd/build/cancel.go",
"chars": 2868,
"preview": "package build\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildResolver \"github.com/buildkite/cli/v3/int"
},
{
"path": "cmd/build/create.go",
"chars": 7497,
"preview": "package build\n\nimport (\n\t\"bufio\"\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkit"
},
{
"path": "cmd/build/download.go",
"chars": 5360,
"preview": "package build\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bui"
},
{
"path": "cmd/build/list.go",
"chars": 15335,
"preview": "package build\n\nimport (\n\t\"context\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/mail\"\n\t\"os\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/al"
},
{
"path": "cmd/build/list_test.go",
"chars": 3115,
"preview": "package build\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/buildkite/cli/v3/pkg/output\"\n\tbuildkite \"gi"
},
{
"path": "cmd/build/rebuild.go",
"chars": 4230,
"preview": "package build\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildResolver \"github.com/buildkite/cli/v3/int"
},
{
"path": "cmd/build/view.go",
"chars": 6802,
"preview": "package build\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"sync\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildResolver \"github.com/buildk"
},
{
"path": "cmd/build/view_test.go",
"chars": 1256,
"preview": "package build\n\nimport (\n\t\"testing\"\n)\n\nfunc TestViewCmd_BuildGetOptions_WithJobStates(t *testing.T) {\n\tcmd := &ViewCmd{\n\t"
},
{
"path": "cmd/build/watch.go",
"chars": 3968,
"preview": "package build\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildResolver \"github."
},
{
"path": "cmd/cluster/cluster_test.go",
"chars": 10418,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\tbuildkite"
},
{
"path": "cmd/cluster/create.go",
"chars": 2557,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bu"
},
{
"path": "cmd/cluster/delete.go",
"chars": 1780,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bu"
},
{
"path": "cmd/cluster/list.go",
"chars": 3053,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"sync\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kon"
},
{
"path": "cmd/cluster/update.go",
"chars": 3276,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bu"
},
{
"path": "cmd/cluster/view.go",
"chars": 3171,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/alecthomas/ko"
},
{
"path": "cmd/config/config.go",
"chars": 4249,
"preview": "// Package config provides commands for managing CLI configuration\npackage config\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\t\"strconv\"\n"
},
{
"path": "cmd/config/config_test.go",
"chars": 2836,
"preview": "package config\n\nimport (\n\t\"testing\"\n)\n\nfunc TestValidateKey(t *testing.T) {\n\tt.Parallel()\n\n\tt.Run(\"valid keys\", func(t *"
},
{
"path": "cmd/config/get.go",
"chars": 1569,
"preview": "package config\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n)\n\ntype GetCmd struct {\n\tKey string `arg"
},
{
"path": "cmd/config/list.go",
"chars": 1923,
"preview": "package config\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n)\n\ntype ListCmd struct {\n\tLocal b"
},
{
"path": "cmd/config/set.go",
"chars": 1687,
"preview": "package config\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n)\n\ntype SetCmd struct {\n\tKey "
},
{
"path": "cmd/config/unset.go",
"chars": 934,
"preview": "package config\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n)\n\ntype UnsetCmd struct {\n\tKey string "
},
{
"path": "cmd/configure/configure.go",
"chars": 3915,
"preview": "package configure\n\nimport (\n\t\"bufio\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\tbkAuth \"github.co"
},
{
"path": "cmd/configure/configure_case_test.go",
"chars": 1529,
"preview": "package configure\n\nimport (\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/internal/config\"\n\t\"github.com/buildkite/cli/v3/pkg"
},
{
"path": "cmd/configure/configure_test.go",
"chars": 3209,
"preview": "package configure\n\nimport (\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/internal/config\"\n\t\"github.com/buildkite/cli/v3/pkg"
},
{
"path": "cmd/generate/generate.go",
"chars": 905,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\n\t\"github.com/Khan/genqlient/generate\"\n\t\"github.com"
},
{
"path": "cmd/init/init.go",
"chars": 1400,
"preview": "package init\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/alecthomas/kong\"\n)\n\nconst (\n\tdefaultPipelineYAML = `s"
},
{
"path": "cmd/init/init_test.go",
"chars": 664,
"preview": "package init\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestFindExistingPipelineFileWithNoFile(t *testing.T) {\n"
},
{
"path": "cmd/job/cancel.go",
"chars": 2119,
"preview": "package job\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"git"
},
{
"path": "cmd/job/cancel_test.go",
"chars": 596,
"preview": "package job\n\nimport (\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/internal/util\"\n)\n\nfunc TestCancelCmdStructure(t *testing"
},
{
"path": "cmd/job/graphql/cancel.graphql",
"chars": 178,
"preview": "mutation CancelJob($jobId: ID!) {\n jobTypeCommandCancel(input: { id: $jobId }) {\n clientMutationId\n jobTypeComman"
},
{
"path": "cmd/job/graphql/jobs.graphql",
"chars": 2882,
"preview": "query FindClusters($org: ID!, $cursor: String) {\n organization(slug: $org) {\n clusters(first: 100, after: $cursor) {"
},
{
"path": "cmd/job/graphql/retry.graphql",
"chars": 166,
"preview": "mutation RetryJob($id: ID!) {\n jobTypeCommandRetry(input: {id: $id}) {\n jobTypeCommand {\n id\n "
},
{
"path": "cmd/job/graphql/unblock.graphql",
"chars": 262,
"preview": "mutation UnblockJob($id: ID!, $fields: JSON) {\n jobTypeBlockUnblock(input: {id: $id, fields: $fields}) {\n jobT"
},
{
"path": "cmd/job/list.go",
"chars": 24421,
"preview": "package job\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/Khan/genqlient/grap"
},
{
"path": "cmd/job/list_test.go",
"chars": 1971,
"preview": "package job\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/buildkite/cli/v3/pkg/output\"\n\tbuildkite \"gith"
},
{
"path": "cmd/job/log.go",
"chars": 3338,
"preview": "package job\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"regexp\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildResolver \"github.com/buildkite/cl"
},
{
"path": "cmd/job/reprioritize.go",
"chars": 2973,
"preview": "package job\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\tbuildResolver \"github.com/buildkite/cli/v3/inter"
},
{
"path": "cmd/job/retry.go",
"chars": 1717,
"preview": "package job\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\tbkGr"
},
{
"path": "cmd/job/unblock.go",
"chars": 2981,
"preview": "package job\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bui"
},
{
"path": "cmd/job/unblock_test.go",
"chars": 1444,
"preview": "package job\n\nimport (\n\t\"testing\"\n\n\tbkGraphQL \"github.com/buildkite/cli/v3/internal/graphql\"\n)\n\nfunc TestValidateUnblockR"
},
{
"path": "cmd/maintainer/create.go",
"chars": 3351,
"preview": "package maintainer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t"
},
{
"path": "cmd/maintainer/delete.go",
"chars": 2041,
"preview": "package maintainer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com"
},
{
"path": "cmd/maintainer/list.go",
"chars": 2516,
"preview": "package maintainer\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com"
},
{
"path": "cmd/maintainer/maintainer_test.go",
"chars": 4306,
"preview": "package maintainer\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\tbuildk"
},
{
"path": "cmd/organization/list.go",
"chars": 1973,
"preview": "package organization\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"slices\"\n\t\"strconv\"\n\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\tbkIO \"git"
},
{
"path": "cmd/pipeline/convert.go",
"chars": 9750,
"preview": "package pipeline\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath"
},
{
"path": "cmd/pipeline/convert_test.go",
"chars": 9078,
"preview": "package pipeline\n\nimport (\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"slices\"\n\t\"strings\""
},
{
"path": "cmd/pipeline/copy.go",
"chars": 12065,
"preview": "package pipeline\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkit"
},
{
"path": "cmd/pipeline/create.go",
"chars": 17140,
"preview": "package pipeline\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"git"
},
{
"path": "cmd/pipeline/create_test.go",
"chars": 3354,
"preview": "package pipeline\n\nimport (\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n)\n\nfunc TestIsGitHubURL(t *testing"
},
{
"path": "cmd/pipeline/graphql/create_webhook.graphql",
"chars": 131,
"preview": "mutation PipelineCreateWebhook($id: ID!) {\n pipelineCreateWebhook(input: { id: $id }) {\n clientMutationId\n pipeli"
},
{
"path": "cmd/pipeline/list.go",
"chars": 5004,
"preview": "package pipeline\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/"
},
{
"path": "cmd/pipeline/validate.go",
"chars": 8542,
"preview": "package pipeline\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bu"
},
{
"path": "cmd/pipeline/validate_test.go",
"chars": 8905,
"preview": "package pipeline\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/goccy/go-yam"
},
{
"path": "cmd/pipeline/view.go",
"chars": 4782,
"preview": "package pipeline\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"g"
},
{
"path": "cmd/pkg/push.go",
"chars": 5168,
"preview": "package pkg\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/"
},
{
"path": "cmd/pkg/push_test.go",
"chars": 2666,
"preview": "package pkg\n\nimport (\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestPackagePushCommandArgs(t *testing.T) {\n\tt.Parall"
},
{
"path": "cmd/preflight/cleanup_cmd.go",
"chars": 4338,
"preview": "package preflight\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/google"
},
{
"path": "cmd/preflight/cleanup_cmd_test.go",
"chars": 13919,
"preview": "package preflight\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"string"
},
{
"path": "cmd/preflight/event.go",
"chars": 3509,
"preview": "package preflight\n\nimport (\n\t\"time\"\n\n\t\"github.com/buildkite/cli/v3/internal/build/watch\"\n\tinternalpreflight \"github.com/"
},
{
"path": "cmd/preflight/event_test.go",
"chars": 2534,
"preview": "package preflight\n\nimport (\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/buildkite/cli/v3/internal/build/watch\"\n\tbuildkite \"github.c"
},
{
"path": "cmd/preflight/job_presenter.go",
"chars": 3197,
"preview": "package preflight\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/buildkite/cli/v3/internal/build/watch\"\n\t\"github.com/buildkite/cli/v3/in"
},
{
"path": "cmd/preflight/job_presenter_test.go",
"chars": 7024,
"preview": "package preflight\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\nfunc Tes"
},
{
"path": "cmd/preflight/preflight.go",
"chars": 18482,
"preview": "package preflight\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strconv\"\n\t\"strings\"\n\t\"syscall\"\n"
},
{
"path": "cmd/preflight/preflight_test.go",
"chars": 63283,
"preview": "package preflight\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"os\"\n\t\"os/exec"
},
{
"path": "cmd/preflight/render.go",
"chars": 9382,
"preview": "package preflight\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\tinter"
},
{
"path": "cmd/preflight/render_test.go",
"chars": 30083,
"preview": "package preflight\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/buildkite/cl"
},
{
"path": "cmd/preflight/result.go",
"chars": 1962,
"preview": "package preflight\n\nimport (\n\t\"fmt\"\n\n\tbuildstate \"github.com/buildkite/cli/v3/internal/build/state\"\n\tbkErrors \"github.com"
},
{
"path": "cmd/preflight/result_test.go",
"chars": 4505,
"preview": "package preflight\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\tbkErrors \"github.com/buildkite/cli/v3/internal/errors\"\n\tbuildkite \"g"
},
{
"path": "cmd/preflight/test_presenter.go",
"chars": 6225,
"preview": "package preflight\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\tinternalpreflight \"github.com/buildkite/cli/v3/internal/prefligh"
},
{
"path": "cmd/preflight/test_presenter_test.go",
"chars": 1466,
"preview": "package preflight\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\tinternalpreflight \"github.com/buildkite/cli/v3/internal/preflight\"\n)"
},
{
"path": "cmd/preflight/tty.go",
"chars": 6730,
"preview": "package preflight\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/charmbracelet/bubbles/spinner\"\n\ttea \"github.com/c"
},
{
"path": "cmd/preflight/tty_test.go",
"chars": 3959,
"preview": "package preflight\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\tinternalpreflight \"github.com/buildkite/cli/v3/internal/preflight\"\n\t"
},
{
"path": "cmd/queue/create.go",
"chars": 3332,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buil"
},
{
"path": "cmd/queue/delete.go",
"chars": 1864,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buil"
},
{
"path": "cmd/queue/list.go",
"chars": 3593,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buil"
},
{
"path": "cmd/queue/pause.go",
"chars": 2552,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buil"
},
{
"path": "cmd/queue/queue_test.go",
"chars": 10485,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\tbui"
},
{
"path": "cmd/queue/resume.go",
"chars": 2510,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buil"
},
{
"path": "cmd/queue/update.go",
"chars": 3622,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buil"
},
{
"path": "cmd/queue/view.go",
"chars": 3816,
"preview": "package queue\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kong"
},
{
"path": "cmd/secret/create.go",
"chars": 3286,
"preview": "package secret\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bui"
},
{
"path": "cmd/secret/delete.go",
"chars": 1955,
"preview": "package secret\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bui"
},
{
"path": "cmd/secret/get.go",
"chars": 3329,
"preview": "package secret\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"syscall\"\n\t\"time\"\n\n\t\"github.com/alecthomas/kon"
},
{
"path": "cmd/secret/list.go",
"chars": 2182,
"preview": "package secret\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"gith"
},
{
"path": "cmd/secret/secret_test.go",
"chars": 9248,
"preview": "package secret\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\n\tbuildkite "
},
{
"path": "cmd/secret/update.go",
"chars": 4219,
"preview": "package secret\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/bui"
},
{
"path": "cmd/skill/skill.go",
"chars": 12315,
"preview": "package skill\n\nimport (\n\t\"archive/zip\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"time\"\n)\n\nconst (\n\tde"
},
{
"path": "cmd/skill/skill_test.go",
"chars": 4231,
"preview": "package skill\n\nimport (\n\t\"archive/zip\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestResolveTargetDetectsProjectAgent(t "
},
{
"path": "cmd/use/use.go",
"chars": 2219,
"preview": "package use\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/buildkite/cli/v3/internal/cli\"\n\t\"github.com/buildkite/cli/v3/internal/config\""
},
{
"path": "cmd/user/invite.go",
"chars": 2095,
"preview": "package user\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"sync\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"github.com/buildkite/cli/v3/internal/c"
},
{
"path": "cmd/version/update_check.go",
"chars": 2073,
"preview": "package version\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar releaseURL = \"https:/"
},
{
"path": "cmd/version/update_check_test.go",
"chars": 4084,
"preview": "package version\n\nimport (\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n)\n\nfunc TestCheckForUpdate_NewerVersionAvai"
},
{
"path": "cmd/version/version.go",
"chars": 418,
"preview": "package version\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\nvar Version = \"DEV\"\n\ntype VersionCmd struct{}\n\nfunc (c *VersionCmd)"
},
{
"path": "cmd/whoami/whoami.go",
"chars": 2180,
"preview": "package whoami\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"os/signal\"\n\t\"strings\"\n\t\"syscall\"\n\n\t\"github.com/alecthomas/kong\"\n\t\"git"
},
{
"path": "docs/shell-prompt-integration.md",
"chars": 3018,
"preview": "### Shell Prompt Integration\n\nThe Buildkite CLI offers a shell prompt integration that displays your current Buildkite o"
},
{
"path": "fixtures/build.json",
"chars": 2633,
"preview": "[\n {\n \"id\": \"018f7ee5-xxxx-429f-83ad-89e3b6c6c3ef\",\n \"graphql_id\": \"QnVpbGQtLS0wxxxxxxxxxxxxNTkyLTQyOWYtODNhZC04O"
},
{
"path": "fixtures/config/local.basic.yaml",
"chars": 143,
"preview": "selected_org: buildkite-test\norganizations:\n buildkite-test:\n api_token: test-token-1234\npipelines:\n - first-pipeli"
},
{
"path": "fixtures/config/user.basic.yaml",
"chars": 92,
"preview": "selected_org: buildkite-org\norganizations:\n buildkite-test:\n api_token: test-token-abcd\n"
},
{
"path": "genqlient.yaml",
"chars": 237,
"preview": "schema: schema.graphql\n\noperations:\n - internal/**/*.graphql\n - cmd/**/*.graphql\n\noptional: pointer\n\ngenerated: intern"
},
{
"path": "go.mod",
"chars": 3784,
"preview": "module github.com/buildkite/cli/v3\n\ngo 1.25.0\n\nrequire (\n\tgithub.com/alecthomas/kong v1.15.0\n\tgithub.com/anmitsu/go-shle"
},
{
"path": "go.sum",
"chars": 20810,
"preview": "dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=\ndario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobSt"
},
{
"path": "internal/agent/download.go",
"chars": 6390,
"preview": "package agent\n\nimport (\n\t\"archive/tar\"\n\t\"archive/zip\"\n\t\"compress/gzip\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"encoding/json\""
},
{
"path": "internal/agent/download_test.go",
"chars": 7905,
"preview": "package agent\n\nimport (\n\t\"archive/tar\"\n\t\"archive/zip\"\n\t\"compress/gzip\"\n\t\"crypto/sha256\"\n\t\"encoding/hex\"\n\t\"fmt\"\n\t\"net/htt"
},
{
"path": "internal/agent/platform.go",
"chars": 1683,
"preview": "package agent\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n)\n\n// DefaultBinDir returns the platform-appropriate default directory fo"
},
{
"path": "internal/agent/platform_test.go",
"chars": 1877,
"preview": "package agent\n\nimport (\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestDefaultBinDir(t *testing.T) {\n\tt.Parallel()\n\n\ttests := []struc"
},
{
"path": "internal/agent/token.go",
"chars": 1674,
"preview": "package agent\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n\tbuildk"
},
{
"path": "internal/agent/token_test.go",
"chars": 1308,
"preview": "package agent\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n)\n\nfunc TestWriteAgentConfig(t *testing.T) {\n\tt.Parallel()\n\n\td"
},
{
"path": "internal/annotation/annotation.go",
"chars": 272,
"preview": "package annotation\n\nimport \"regexp\"\n\n// StripTags removes HTML tags from a string\nfunc StripTags(html string) string {\n\t"
},
{
"path": "internal/annotation/list.go",
"chars": 780,
"preview": "package annotation\n\nimport (\n\t\"strings\"\n\n\t\"github.com/buildkite/cli/v3/pkg/output\"\n\tbuildkite \"github.com/buildkite/go-b"
},
{
"path": "internal/artifact/artifact.go",
"chars": 558,
"preview": "package artifact\n\nimport \"fmt\"\n\n// FormatBytes formats bytes into human-readable format (KB, MB, GB, etc.)\nfunc FormatBy"
},
{
"path": "internal/artifact/view.go",
"chars": 494,
"preview": "package artifact\n\nimport (\n\t\"github.com/buildkite/cli/v3/pkg/output\"\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)"
},
{
"path": "internal/build/build.go",
"chars": 97,
"preview": "package build\n\ntype Build struct {\n\tOrganization string\n\tPipeline string\n\tBuildNumber int\n}\n"
},
{
"path": "internal/build/resolver/cli.go",
"chars": 1785,
"preview": "package resolver\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/buildkite/cli/v3/internal/build\"\n\t\"gith"
},
{
"path": "internal/build/resolver/cli_test.go",
"chars": 2096,
"preview": "package resolver_test\n\nimport (\n\t\"context\"\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/internal/build/resolver\"\n\t\"github.c"
},
{
"path": "internal/build/resolver/options/options.go",
"chars": 2852,
"preview": "package options\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/buildkite/cli/v3/pkg/cmd/factory\"\n\tbu"
},
{
"path": "internal/build/resolver/options/options_test.go",
"chars": 1991,
"preview": "package options\n\nimport (\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4"
},
{
"path": "internal/build/resolver/resolver.go",
"chars": 1492,
"preview": "package resolver\n\nimport (\n\t\"context\"\n\n\t\"github.com/buildkite/cli/v3/internal/build\"\n)\n\n// BuildResolverFn is a function"
},
{
"path": "internal/build/resolver/url.go",
"chars": 925,
"preview": "package resolver\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\n\t\"github.com/buildkite/cli/v3/internal/build\"\n)\n\nfunc"
},
{
"path": "internal/build/resolver/with_options.go",
"chars": 1282,
"preview": "package resolver\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/buildkite/cli/v3/internal/build\"\n\t\"github.com/buildkite/cli/v"
},
{
"path": "internal/build/state/state.go",
"chars": 637,
"preview": "package state\n\ntype State string\n\nconst (\n\tScheduled State = \"scheduled\"\n\tRunning State = \"running\"\n\tBlocked State ="
},
{
"path": "internal/build/state/state_test.go",
"chars": 1776,
"preview": "package state\n\nimport \"testing\"\n\nfunc TestIsTerminal(t *testing.T) {\n\ttests := []struct {\n\t\tname string\n\t\tstate State\n\t"
},
{
"path": "internal/build/view/shared/summary.go",
"chars": 735,
"preview": "package shared\n\nimport (\n\t\"github.com/buildkite/cli/v3/internal/build/view\"\n\tbuildkite \"github.com/buildkite/go-buildkit"
},
{
"path": "internal/build/view/view.go",
"chars": 6384,
"preview": "package view\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/buildkite/cli/v3/internal/artifact\"\n\t\"github.com/buildkit"
},
{
"path": "internal/build/view/view_test.go",
"chars": 4235,
"preview": "package view\n\nimport (\n\t\"strings\"\n\t\"testing\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\nfunc TestBuildSummary"
},
{
"path": "internal/build/watch/job.go",
"chars": 1140,
"preview": "package watch\n\nimport (\n\t\"time\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\n// FormattedJob wraps a Buildkite "
},
{
"path": "internal/build/watch/test_tracker.go",
"chars": 1112,
"preview": "package watch\n\nimport (\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\n// TestTracker tracks which test executions"
},
{
"path": "internal/build/watch/test_tracker_test.go",
"chars": 4554,
"preview": "package watch\n\nimport (\n\t\"testing\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\nfunc TestTestTracker_Update(t *"
},
{
"path": "internal/build/watch/tracker.go",
"chars": 5219,
"preview": "package watch\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\t\"strings\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\n// trackedJob ho"
},
{
"path": "internal/build/watch/tracker_test.go",
"chars": 21375,
"preview": "package watch\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\t\"time\"\n\n\tbuildkite \"github.com/buildkite/go-buildkite/v4\"\n)\n\nfunc TestJobTrac"
},
{
"path": "internal/build/watch/watch.go",
"chars": 4701,
"preview": "package watch\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"time\"\n\n\tbuildstate \"github.com/buildkite/cli/v3/intern"
},
{
"path": "internal/build/watch/watch_test.go",
"chars": 11170,
"preview": "package watch\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"testing\"\n\t\"t"
},
{
"path": "internal/cli/context.go",
"chars": 532,
"preview": "package cli\n\ntype GlobalFlags interface {\n\tSkipConfirmation() bool\n\tDisableInput() bool\n\tIsQuiet() bool\n\tDisablePager() "
},
{
"path": "internal/cluster/list_queues.graphql",
"chars": 657,
"preview": "query GetClusterQueues($orgSlug: ID!, $clusterId: ID!) {\n organization(slug: $orgSlug) {\n cluster(id: $clusterId) {\n"
},
{
"path": "internal/cluster/query.go",
"chars": 1742,
"preview": "package cluster\n\nimport (\n\t\"context\"\n\t\"sync\"\n\n\t\"github.com/buildkite/cli/v3/internal/graphql\"\n\t\"github.com/buildkite/cli"
},
{
"path": "internal/cluster/view.go",
"chars": 1969,
"preview": "package cluster\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/buildkite/cli/v3/pkg/output\"\n\tbuildkite \"github.com/bu"
},
{
"path": "internal/config/config.go",
"chars": 14337,
"preview": "// Package config contains the configuration for the bk CLI\n//\n// Configuration can come from files or environment varia"
},
{
"path": "internal/config/config_test.go",
"chars": 11986,
"preview": "package config\n\nimport (\n\t\"os\"\n\t\"path/filepath\"\n\t\"testing\"\n\n\t\"github.com/buildkite/cli/v3/pkg/keyring\"\n\t\"github.com/spf1"
},
{
"path": "internal/emoji/emoji.go",
"chars": 2057,
"preview": "package emoji\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/buildkite/termoji\"\n)\n\nvar (\n\tonce sync.Once\n\trend"
},
{
"path": "internal/emoji/emoji_test.go",
"chars": 1807,
"preview": "package emoji\n\nimport (\n\t\"testing\"\n)\n\nfunc TestRender_standardEmoji(t *testing.T) {\n\tgot := Render(\":checkered_flag: Fea"
},
{
"path": "internal/errors/README.md",
"chars": 2810,
"preview": "# Error Handling Package\n\nThis package provides standardized error handling for the Buildkite CLI. It handles different "
},
{
"path": "internal/errors/api.go",
"chars": 4257,
"preview": "package errors\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"strings\"\n\n\thttpClient \"github.com/buildkite/cli/v3/intern"
},
{
"path": "internal/errors/api_test.go",
"chars": 5699,
"preview": "package errors\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n\n\thttpClient \"github.com/buildkite/cli/v3/internal/http\"\n)\n\nfunc Te"
},
{
"path": "internal/errors/errors.go",
"chars": 9717,
"preview": "package errors\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// Standard error types that can be used to categorize errors\nva"
},
{
"path": "internal/errors/errors_test.go",
"chars": 7196,
"preview": "package errors\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestErrorInterface(t *testing.T) {\n\tt.Parallel()"
},
{
"path": "internal/errors/handler.go",
"chars": 6484,
"preview": "package errors\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n)\n\n// Exit codes for different error types\nconst (\n\tExitCodeSucces"
},
{
"path": "internal/errors/handler_test.go",
"chars": 7428,
"preview": "package errors\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"strings\"\n\t\"testing\"\n)\n\n// stripANSI removes ANSI color codes from a string fo"
},
{
"path": "internal/graphql/generated.go",
"chars": 176221,
"preview": "// Code generated by github.com/Khan/genqlient, DO NOT EDIT.\n\npackage graphql\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fm"
},
{
"path": "internal/http/README.md",
"chars": 1838,
"preview": "# HTTP Client Package\n\nThis package provides a common HTTP client with standardized headers and error handling for Build"
},
{
"path": "internal/http/client.go",
"chars": 6072,
"preview": "package http\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n)\n\n// ErrorRe"
},
{
"path": "internal/http/client_test.go",
"chars": 8791,
"preview": "package http\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n)\n\ntype testRespons"
},
{
"path": "internal/http/ratelimit.go",
"chars": 3456,
"preview": "package http\n\nimport (\n\t\"io\"\n\t\"net/http\"\n\t\"strconv\"\n\t\"time\"\n)\n\nconst (\n\t// DefaultMaxRateLimitRetries is the default num"
},
{
"path": "internal/http/ratelimit_test.go",
"chars": 8069,
"preview": "package http\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"strings\"\n\t\"sync/atomic\"\n\t\"testing\"\n\t\"time\"\n)\n"
},
{
"path": "internal/http/refresh_transport.go",
"chars": 6695,
"preview": "package http\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/buildkite/cli/v3/pkg/k"
}
]
// ... and 72 more files (download for full content)
About this extraction
This page contains the full source code of the buildkite/cli GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 272 files (1.4 MB), approximately 390.7k tokens, and a symbol index with 1940 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.