Documentation ¶
Index ¶
- Constants
- Variables
- func CreateLogger(cfg interface{}) logger.Logger
- func DefaultConfigFilePaths() (paths []string)
- func DefaultShell() string
- func HandleGlobalFlags(l logger.Logger, cfg interface{}) func()
- func HandleProfileFlag(l logger.Logger, cfg interface{}) func()
- func Profile(l logger.Logger, mode string) func()
- func UnsetConfigFromEnvironment(c *cli.Context) error
- type AgentStartConfig
- type AnnotateConfig
- type ArtifactDownloadConfig
- type ArtifactSearchConfig
- type ArtifactShasumConfig
- type ArtifactUploadConfig
- type BootstrapConfig
- type MetaDataExistsConfig
- type MetaDataGetConfig
- type MetaDataKeysConfig
- type MetaDataSetConfig
- type PipelineUploadConfig
- type StepGetConfig
- type StepUpdateConfig
Constants ¶
View Source
const (
DefaultEndpoint = "https://agent.buildkite.com/v3"
)
Variables ¶
View Source
var AgentAccessTokenFlag = cli.StringFlag{
Name: "agent-access-token",
Value: "",
Usage: "The access token used to identify the agent",
EnvVar: "BUILDKITE_AGENT_ACCESS_TOKEN",
}
View Source
var AgentRegisterTokenFlag = cli.StringFlag{
Name: "token",
Value: "",
Usage: "Your account agent token",
EnvVar: "BUILDKITE_AGENT_TOKEN",
}
View Source
var AgentStartCommand = cli.Command{ Name: "start", Usage: "Starts a Buildkite agent", Description: StartDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "config", Value: "", Usage: "Path to a configuration file", EnvVar: "BUILDKITE_AGENT_CONFIG", }, cli.StringFlag{ Name: "name", Value: "", Usage: "The name of the agent", EnvVar: "BUILDKITE_AGENT_NAME", }, cli.StringFlag{ Name: "priority", Value: "", Usage: "The priority of the agent (higher priorities are assigned work first)", EnvVar: "BUILDKITE_AGENT_PRIORITY", }, cli.StringFlag{ Name: "acquire-job", Value: "", Usage: "Start this agent and only run the specified job, disconnecting after it's finished", EnvVar: "BUILDKITE_AGENT_ACQUIRE_JOB", }, cli.BoolFlag{ Name: "disconnect-after-job", Usage: "Disconnect the agent after running a job", EnvVar: "BUILDKITE_AGENT_DISCONNECT_AFTER_JOB", }, cli.IntFlag{ Name: "disconnect-after-idle-timeout", Value: 0, Usage: "If no jobs have come in for the specified number of seconds, disconnect the agent", EnvVar: "BUILDKITE_AGENT_DISCONNECT_AFTER_IDLE_TIMEOUT", }, cli.IntFlag{ Name: "cancel-grace-period", Value: 10, Usage: "The number of seconds a canceled or timed out job is given to gracefully terminate and upload its artifacts", EnvVar: "BUILDKITE_CANCEL_GRACE_PERIOD", }, cli.StringFlag{ Name: "shell", Value: DefaultShell(), Usage: "The shell command used to interpret build commands, e.g /bin/bash -e -c", EnvVar: "BUILDKITE_SHELL", }, cli.StringSliceFlag{ Name: "tags", Value: &cli.StringSlice{}, Usage: "A comma-separated list of tags for the agent (e.g. \"linux\" or \"mac,xcode=8\")", EnvVar: "BUILDKITE_AGENT_TAGS", }, cli.BoolFlag{ Name: "tags-from-host", Usage: "Include tags from the host (hostname, machine-id, os)", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_HOST", }, cli.StringSliceFlag{ Name: "tags-from-ec2-meta-data", Value: &cli.StringSlice{}, Usage: "Include the default set of host EC2 meta-data as tags (instance-id, instance-type, and ami-id)", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_EC2_META_DATA", }, cli.StringSliceFlag{ Name: "tags-from-ec2-meta-data-paths", Value: &cli.StringSlice{}, Usage: "Include additional tags fetched from EC2 meta-data via tag & path suffix pairs, e.g \"tag_name=path/to/value\"", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_EC2_META_DATA_PATHS", }, cli.BoolFlag{ Name: "tags-from-ec2-tags", Usage: "Include the host's EC2 tags as tags", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_EC2_TAGS", }, cli.StringSliceFlag{ Name: "tags-from-gcp-meta-data", Value: &cli.StringSlice{}, Usage: "Include the default set of host Google Cloud instance meta-data as tags (instance-id, machine-type, preemptible, project-id, region, and zone)", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_GCP_META_DATA", }, cli.StringSliceFlag{ Name: "tags-from-gcp-meta-data-paths", Value: &cli.StringSlice{}, Usage: "Include additional tags fetched from Google Cloud instance meta-data via tag & path suffix pairs, e.g \"tag_name=path/to/value\"", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_GCP_META_DATA_PATHS", }, cli.BoolFlag{ Name: "tags-from-gcp-labels", Usage: "Include the host's Google Cloud instance labels as tags", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_GCP_LABELS", }, cli.DurationFlag{ Name: "wait-for-ec2-tags-timeout", Usage: "The amount of time to wait for tags from EC2 before proceeding", EnvVar: "BUILDKITE_AGENT_WAIT_FOR_EC2_TAGS_TIMEOUT", Value: time.Second * 10, }, cli.DurationFlag{ Name: "wait-for-gcp-labels-timeout", Usage: "The amount of time to wait for labels from GCP before proceeding", EnvVar: "BUILDKITE_AGENT_WAIT_FOR_GCP_LABELS_TIMEOUT", Value: time.Second * 10, }, cli.StringFlag{ Name: "git-clone-flags", Value: "-v", Usage: "Flags to pass to the \"git clone\" command", EnvVar: "BUILDKITE_GIT_CLONE_FLAGS", }, cli.StringFlag{ Name: "git-clean-flags", Value: "-ffxdq", Usage: "Flags to pass to \"git clean\" command", EnvVar: "BUILDKITE_GIT_CLEAN_FLAGS", }, cli.StringFlag{ Name: "git-fetch-flags", Value: "-v --prune", Usage: "Flags to pass to \"git fetch\" command", EnvVar: "BUILDKITE_GIT_FETCH_FLAGS", }, cli.StringFlag{ Name: "git-clone-mirror-flags", Value: "-v --mirror", Usage: "Flags to pass to the \"git clone\" command when used for mirroring", EnvVar: "BUILDKITE_GIT_CLONE_MIRROR_FLAGS", }, cli.StringFlag{ Name: "git-mirrors-path", Value: "", Usage: "Path to where mirrors of git repositories are stored", EnvVar: "BUILDKITE_GIT_MIRRORS_PATH", }, cli.IntFlag{ Name: "git-mirrors-lock-timeout", Value: 300, Usage: "Seconds to lock a git mirror during clone, should exceed your longest checkout", EnvVar: "BUILDKITE_GIT_MIRRORS_LOCK_TIMEOUT", }, cli.StringFlag{ Name: "bootstrap-script", Value: "", Usage: "The command that is executed for bootstrapping a job, defaults to the bootstrap sub-command of this binary", EnvVar: "BUILDKITE_BOOTSTRAP_SCRIPT_PATH", }, cli.StringFlag{ Name: "build-path", Value: "", Usage: "Path to where the builds will run from", EnvVar: "BUILDKITE_BUILD_PATH", }, cli.StringFlag{ Name: "hooks-path", Value: "", Usage: "Directory where the hook scripts are found", EnvVar: "BUILDKITE_HOOKS_PATH", }, cli.StringFlag{ Name: "plugins-path", Value: "", Usage: "Directory where the plugins are saved to", EnvVar: "BUILDKITE_PLUGINS_PATH", }, cli.BoolFlag{ Name: "timestamp-lines", Usage: "Prepend timestamps on each line of output.", EnvVar: "BUILDKITE_TIMESTAMP_LINES", }, cli.StringFlag{ Name: "health-check-addr", Usage: "Start an HTTP server on this addr:port that returns whether the agent is healthy, disabled by default", EnvVar: "BUILDKITE_AGENT_HEALTH_CHECK_ADDR", }, cli.BoolFlag{ Name: "no-pty", Usage: "Do not run jobs within a pseudo terminal", EnvVar: "BUILDKITE_NO_PTY", }, cli.BoolFlag{ Name: "no-ssh-keyscan", Usage: "Don't automatically run ssh-keyscan before checkout", EnvVar: "BUILDKITE_NO_SSH_KEYSCAN", }, cli.BoolFlag{ Name: "no-command-eval", Usage: "Don't allow this agent to run arbitrary console commands, including plugins", EnvVar: "BUILDKITE_NO_COMMAND_EVAL", }, cli.BoolFlag{ Name: "no-plugins", Usage: "Don't allow this agent to load plugins", EnvVar: "BUILDKITE_NO_PLUGINS", }, cli.BoolTFlag{ Name: "no-plugin-validation", Usage: "Don't validate plugin configuration and requirements", EnvVar: "BUILDKITE_NO_PLUGIN_VALIDATION", }, cli.BoolFlag{ Name: "no-local-hooks", Usage: "Don't allow local hooks to be run from checked out repositories", EnvVar: "BUILDKITE_NO_LOCAL_HOOKS", }, cli.BoolFlag{ Name: "no-git-submodules", Usage: "Don't automatically checkout git submodules", EnvVar: "BUILDKITE_NO_GIT_SUBMODULES,BUILDKITE_DISABLE_GIT_SUBMODULES", }, cli.BoolFlag{ Name: "metrics-datadog", Usage: "Send metrics to DogStatsD for Datadog", EnvVar: "BUILDKITE_METRICS_DATADOG", }, cli.StringFlag{ Name: "metrics-datadog-host", Usage: "The dogstatsd instance to send metrics to via udp", EnvVar: "BUILDKITE_METRICS_DATADOG_HOST", Value: "127.0.0.1:8125", }, cli.StringFlag{ Name: "log-format", Usage: "The format to use for the logger output", EnvVar: "BUILDKITE_LOG_FORMAT", Value: "text", }, cli.IntFlag{ Name: "spawn", Usage: "The number of agents to spawn in parallel", Value: 1, EnvVar: "BUILDKITE_AGENT_SPAWN", }, cli.StringFlag{ Name: "cancel-signal", Usage: "The signal to use for cancellation", EnvVar: "BUILDKITE_CANCEL_SIGNAL", Value: "SIGTERM", }, cli.StringSliceFlag{ Name: "redacted-vars", Usage: "Pattern of environment variable names containing sensitive values", EnvVar: "BUILDKITE_REDACTED_VARS", Value: &cli.StringSlice{"*_PASSWORD", "*_SECRET", "*_TOKEN"}, }, AgentRegisterTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, cli.StringSliceFlag{ Name: "meta-data", Value: &cli.StringSlice{}, Hidden: true, EnvVar: "BUILDKITE_AGENT_META_DATA", }, cli.BoolFlag{ Name: "meta-data-ec2", Hidden: true, EnvVar: "BUILDKITE_AGENT_META_DATA_EC2", }, cli.BoolFlag{ Name: "meta-data-ec2-tags", Hidden: true, EnvVar: "BUILDKITE_AGENT_TAGS_FROM_EC2_TAGS", }, cli.BoolFlag{ Name: "meta-data-gcp", Hidden: true, EnvVar: "BUILDKITE_AGENT_META_DATA_GCP", }, cli.BoolFlag{ Name: "no-automatic-ssh-fingerprint-verification", Hidden: true, EnvVar: "BUILDKITE_NO_AUTOMATIC_SSH_FINGERPRINT_VERIFICATION", }, cli.BoolFlag{ Name: "tags-from-ec2", Usage: "Include the host's EC2 meta-data as tags (instance-id, instance-type, and ami-id)", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_EC2", }, cli.BoolFlag{ Name: "tags-from-gcp", Usage: "Include the host's Google Cloud instance meta-data as tags (instance-id, machine-type, preemptible, project-id, region, and zone)", EnvVar: "BUILDKITE_AGENT_TAGS_FROM_GCP", }, cli.IntFlag{ Name: "disconnect-after-job-timeout", Hidden: true, Usage: "When --disconnect-after-job is specified, the number of seconds to wait for a job before shutting down", EnvVar: "BUILDKITE_AGENT_DISCONNECT_AFTER_JOB_TIMEOUT", }, }, Action: func(c *cli.Context) { cfg := AgentStartConfig{} loader := cliconfig.Loader{ CLI: c, Config: &cfg, DefaultConfigFilePaths: DefaultConfigFilePaths(), } warnings, err := loader.Load() if err != nil { fmt.Printf("%s", err) os.Exit(1) } l := CreateLogger(cfg) for _, warning := range warnings { l.Warn("%s", warning) } done := HandleGlobalFlags(l, cfg) defer done() err = UnsetConfigFromEnvironment(c) if err != nil { fmt.Printf("%s", err) os.Exit(1) } if experiments.IsEnabled(`git-mirrors`) { if cfg.GitMirrorsPath == `` { l.Fatal("Must provide a git-mirrors-path in your configuration for git-mirrors experiment") } } if runtime.GOOS == "windows" { cfg.NoPTY = true } if cfg.BootstrapScript == "" { cfg.BootstrapScript = fmt.Sprintf("%s bootstrap", shellwords.Quote(os.Args[0])) } if c.IsSet("no-plugins") && cfg.NoPlugins == false { msg := `Plugins have been specifically enabled, despite %s being enabled. ` + `Plugins can execute arbitrary hooks and commands, make sure you are ` + `whitelisting your plugins in ` + `your environment hook.` switch { case cfg.NoCommandEval: l.Warn(msg, `no-command-eval`) case cfg.NoLocalHooks: l.Warn(msg, `no-local-hooks`) } } if (cfg.NoCommandEval || cfg.NoLocalHooks) && !c.IsSet("no-plugins") { cfg.NoPlugins = true } if cfg.Shell == "" { cfg.Shell = DefaultShell() } if cfg.DisconnectAfterJobTimeout > 0 { cfg.DisconnectAfterIdleTimeout = cfg.DisconnectAfterJobTimeout } var ec2TagTimeout time.Duration if t := cfg.WaitForEC2TagsTimeout; t != "" { var err error ec2TagTimeout, err = time.ParseDuration(t) if err != nil { l.Fatal("Failed to parse ec2 tag timeout: %v", err) } } var gcpLabelsTimeout time.Duration if t := cfg.WaitForGCPLabelsTimeout; t != "" { var err error gcpLabelsTimeout, err = time.ParseDuration(t) if err != nil { l.Fatal("Failed to parse gcp labels timeout: %v", err) } } mc := metrics.NewCollector(l, metrics.CollectorConfig{ Datadog: cfg.MetricsDatadog, DatadogHost: cfg.MetricsDatadogHost, }) agentConf := agent.AgentConfiguration{ BootstrapScript: cfg.BootstrapScript, BuildPath: cfg.BuildPath, GitMirrorsPath: cfg.GitMirrorsPath, GitMirrorsLockTimeout: cfg.GitMirrorsLockTimeout, HooksPath: cfg.HooksPath, PluginsPath: cfg.PluginsPath, GitCloneFlags: cfg.GitCloneFlags, GitCloneMirrorFlags: cfg.GitCloneMirrorFlags, GitCleanFlags: cfg.GitCleanFlags, GitFetchFlags: cfg.GitFetchFlags, GitSubmodules: !cfg.NoGitSubmodules, SSHKeyscan: !cfg.NoSSHKeyscan, CommandEval: !cfg.NoCommandEval, PluginsEnabled: !cfg.NoPlugins, PluginValidation: !cfg.NoPluginValidation, LocalHooksEnabled: !cfg.NoLocalHooks, RunInPty: !cfg.NoPTY, TimestampLines: cfg.TimestampLines, DisconnectAfterJob: cfg.DisconnectAfterJob, DisconnectAfterIdleTimeout: cfg.DisconnectAfterIdleTimeout, CancelGracePeriod: cfg.CancelGracePeriod, Shell: cfg.Shell, RedactedVars: cfg.RedactedVars, AcquireJob: cfg.AcquireJob, } if loader.File != nil { agentConf.ConfigPath = loader.File.Path } if cfg.LogFormat == `text` { welcomeMessage := "\n" + "%s _ _ _ _ _ _ _ _\n" + " | | (_) | | | | (_) | | |\n" + " | |__ _ _ _| | __| | | ___| |_ ___ __ _ __ _ ___ _ __ | |_\n" + " | '_ \\| | | | | |/ _` | |/ / | __/ _ \\ / _` |/ _` |/ _ \\ '_ \\| __|\n" + " | |_) | |_| | | | (_| | <| | || __/ | (_| | (_| | __/ | | | |_\n" + " |_.__/ \\__,_|_|_|\\__,_|_|\\_\\_|\\__\\___| \\__,_|\\__, |\\___|_| |_|\\__|\n" + " __/ |\n" + " https://buildkite.com/agent |___/\n%s\n" if !cfg.NoColor { fmt.Fprintf(os.Stderr, welcomeMessage, "\x1b[38;5;48m", "\x1b[0m") } else { fmt.Fprintf(os.Stderr, welcomeMessage, "", "") } } l.Notice("Starting buildkite-agent v%s with PID: %s", agent.Version(), fmt.Sprintf("%d", os.Getpid())) l.Notice("The agent source code can be found here: https://github.com/buildkite/agent/v3") l.Notice("For questions and support, email us at: hello@buildkite.com") if agentConf.ConfigPath != "" { l.WithFields(logger.StringField(`path`, agentConf.ConfigPath)).Info("Configuration loaded") } l.Debug("Bootstrap command: %s", agentConf.BootstrapScript) l.Debug("Build path: %s", agentConf.BuildPath) l.Debug("Hooks directory: %s", agentConf.HooksPath) l.Debug("Plugins directory: %s", agentConf.PluginsPath) if !agentConf.SSHKeyscan { l.Info("Automatic ssh-keyscan has been disabled") } if !agentConf.CommandEval { l.Info("Evaluating console commands has been disabled") } if !agentConf.PluginsEnabled { l.Info("Plugins have been disabled") } if !agentConf.RunInPty { l.Info("Running builds within a pseudoterminal (PTY) has been disabled") } if agentConf.DisconnectAfterJob { l.Info("Agents will disconnect after a job run has completed") } if agentConf.DisconnectAfterIdleTimeout > 0 { l.Info("Agents will disconnect after %d seconds of inactivity", agentConf.DisconnectAfterIdleTimeout) } cancelSig, err := process.ParseSignal(cfg.CancelSignal) if err != nil { l.Fatal("Failed to parse cancel-signal: %v", err) } client := api.NewClient(l, loadAPIClientConfig(cfg, `Token`)) registerReq := api.AgentRegisterRequest{ Name: cfg.Name, Priority: cfg.Priority, ScriptEvalEnabled: !cfg.NoCommandEval, Tags: agent.FetchTags(l, agent.FetchTagsConfig{ Tags: cfg.Tags, TagsFromEC2MetaData: (cfg.TagsFromEC2MetaData || cfg.TagsFromEC2), TagsFromEC2MetaDataPaths: cfg.TagsFromEC2MetaDataPaths, TagsFromEC2Tags: cfg.TagsFromEC2Tags, TagsFromGCPMetaData: (cfg.TagsFromGCPMetaData || cfg.TagsFromGCP), TagsFromGCPMetaDataPaths: cfg.TagsFromGCPMetaDataPaths, TagsFromGCPLabels: cfg.TagsFromGCPLabels, TagsFromHost: cfg.TagsFromHost, WaitForEC2TagsTimeout: ec2TagTimeout, WaitForGCPLabelsTimeout: gcpLabelsTimeout, }), IgnoreInDispatches: cfg.AcquireJob != "", } if cfg.Spawn > 1 && cfg.AcquireJob != "" { l.Fatal("You can't spawn multiple agents and acquire a job at the same time") } var workers []*agent.AgentWorker for i := 1; i <= cfg.Spawn; i++ { if cfg.Spawn == 1 { l.Info("Registering agent with Buildkite...") } else { l.Info("Registering agent %d of %d with Buildkite...", i, cfg.Spawn) } ag, err := agent.Register(l, client, registerReq) if err != nil { l.Fatal("%s", err) } workers = append(workers, agent.NewAgentWorker( l.WithFields(logger.StringField(`agent`, ag.Name)), ag, mc, client, agent.AgentWorkerConfig{ AgentConfiguration: agentConf, CancelSignal: cancelSig, Debug: cfg.Debug, DebugHTTP: cfg.DebugHTTP, SpawnIndex: i, })) } pool := agent.NewAgentPool(workers) signals := handlePoolSignals(l, pool) defer close(signals) l.Info("Starting %d Agent(s)", cfg.Spawn) l.Info("You can press Ctrl-C to stop the agents") if cfg.HealthCheckAddr != "" { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) } else { fmt.Fprintf(w, "OK: Buildkite agent is running") } }) go func() { l.Notice("Starting HTTP health check server on %v", cfg.HealthCheckAddr) err := http.ListenAndServe(cfg.HealthCheckAddr, nil) if err != nil { l.Error("Could not start health check server: %v", err) } }() } if err := pool.Start(); err != nil { l.Fatal("%s", err) } }, }
View Source
var AnnotateCommand = cli.Command{ Name: "annotate", Usage: "Annotate the build page within the Buildkite UI with text from within a Buildkite job", Description: AnnotateHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "context", Usage: "The context of the annotation used to differentiate this annotation from others", EnvVar: "BUILDKITE_ANNOTATION_CONTEXT", }, cli.StringFlag{ Name: "style", Usage: "The style of the annotation (`success`, `info`, `warning` or `error`)", EnvVar: "BUILDKITE_ANNOTATION_STYLE", }, cli.BoolFlag{ Name: "append", Usage: "Append to the body of an existing annotation", EnvVar: "BUILDKITE_ANNOTATION_APPEND", }, cli.StringFlag{ Name: "job", Value: "", Usage: "Which job should the annotation come from", EnvVar: "BUILDKITE_JOB_ID", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := AnnotateConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() var body string var err error if cfg.Body != "" { body = cfg.Body } else if stdin.IsReadable() { l.Info("Reading annotation body from STDIN") stdin, err := ioutil.ReadAll(os.Stdin) if err != nil { l.Fatal("Failed to read from STDIN: %s", err) } body = string(stdin[:]) } client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) annotation := &api.Annotation{ Body: body, Style: cfg.Style, Context: cfg.Context, Append: cfg.Append, } err = retry.Do(func(s *retry.Stats) error { resp, err := client.Annotate(cfg.Job, annotation) if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404 || resp.StatusCode == 400) { s.Break() return err } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 5, Interval: 1 * time.Second, Jitter: true}) if err != nil { l.Fatal("Failed to annotate build: %s", err) } l.Debug("Successfully annotated build") }, }
View Source
var AnnotateHelpDescription = `` /* 1292-byte string literal not displayed */
View Source
var ArtifactDownloadCommand = cli.Command{ Name: "download", Usage: "Downloads artifacts from Buildkite to the local machine", Description: DownloadHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "step", Value: "", Usage: "Scope the search to a particular step by using either its name or job ID", }, cli.StringFlag{ Name: "build", Value: "", EnvVar: "BUILDKITE_BUILD_ID", Usage: "The build that the artifacts were uploaded to", }, cli.BoolFlag{ Name: "include-retried-jobs", EnvVar: "BUILDKITE_AGENT_INCLUDE_RETRIED_JOBS", Usage: "Include artifacts from retried jobs in the search", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := ArtifactDownloadConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) downloader := agent.NewArtifactDownloader(l, client, agent.ArtifactDownloaderConfig{ Query: cfg.Query, Destination: cfg.Destination, BuildID: cfg.Build, Step: cfg.Step, IncludeRetriedJobs: cfg.IncludeRetriedJobs, DebugHTTP: cfg.DebugHTTP, }) if err := downloader.Download(); err != nil { l.Fatal("Failed to download artifacts: %s", err) } }, }
View Source
var ArtifactSearchCommand = cli.Command{ Name: "search", Usage: "Searches artifacts in Buildkite", Description: SearchHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "step", Value: "", Usage: "Scope the search to a particular step by using either its name or job ID", }, cli.StringFlag{ Name: "build", Value: "", EnvVar: "BUILDKITE_BUILD_ID", Usage: "The build that the artifacts were uploaded to", }, cli.BoolFlag{ Name: "include-retried-jobs", EnvVar: "BUILDKITE_AGENT_INCLUDE_RETRIED_JOBS", Usage: "Include artifacts from retried jobs in the search", }, cli.StringFlag{ Name: "format", Value: "%j %p %c\n", Usage: `Output formatting of results. Defaults to "%j %p %c\n" (Job ID, path, created at time). The following directives are available: %i UUID of the artifact %p Artifact path %c Artifact creation time (an ISO 8601 / RFC-3339 formatted UTC timestamp) %j UUID of the job that uploaded the artifact, helpful for subsequent artifact downloads %s File size of the artifact in bytes %S SHA1 checksum of the artifact %u Download URL for the artifact, though consider using 'buildkite-agent artifact download' instead `, }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) error { cfg := ArtifactSearchConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) searcher := agent.NewArtifactSearcher(l, client, cfg.Build) artifacts, err := searcher.Search(cfg.Query, cfg.Step, cfg.IncludeRetriedJobs, true) if err != nil { return err } if len(artifacts) == 0 { l.Fatal(fmt.Sprintf("No matches found for %q", cfg.Query)) } for _, artifact := range artifacts { r := strings.NewReplacer( "%p", artifact.Path, "%c", artifact.CreatedAt.Format(time.RFC3339), "%j", artifact.JobID, "%s", strconv.FormatInt(artifact.FileSize, 10), "%S", artifact.Sha1Sum, "%u", artifact.URL, "%i", artifact.ID, ) fmt.Print(r.Replace(cfg.PrintFormat)) } return nil }, }
View Source
var ArtifactShasumCommand = cli.Command{ Name: "shasum", Usage: "Prints the SHA-1 checksum for the artifact provided to STDOUT", Description: ShasumHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "step", Value: "", Usage: "Scope the search to a particular step by using either its name of job ID", }, cli.StringFlag{ Name: "build", Value: "", EnvVar: "BUILDKITE_BUILD_ID", Usage: "The build that the artifacts were uploaded to", }, cli.BoolFlag{ Name: "include-retried-jobs", EnvVar: "BUILDKITE_AGENT_INCLUDE_RETRIED_JOBS", Usage: "Include artifacts from retried jobs in the search", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := ArtifactShasumConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) searcher := agent.NewArtifactSearcher(l, client, cfg.Build) artifacts, err := searcher.Search(cfg.Query, cfg.Step, cfg.IncludeRetriedJobs, false) if err != nil { l.Fatal("Failed to find artifacts: %s", err) } artifactsFoundLength := len(artifacts) if artifactsFoundLength == 0 { l.Fatal("No artifacts found for downloading") } else if artifactsFoundLength > 1 { l.Fatal("Multiple artifacts were found. Try being more specific with the search or scope by step") } else { l.Debug("Artifact \"%s\" found", artifacts[0].Path) fmt.Printf("%s\n", artifacts[0].Sha1Sum) } }, }
View Source
var ArtifactUploadCommand = cli.Command{ Name: "upload", Usage: "Uploads files to a job as artifacts", Description: UploadHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "job", Value: "", Usage: "Which job should the artifacts be uploaded to", EnvVar: "BUILDKITE_JOB_ID", }, cli.StringFlag{ Name: "content-type", Value: "", Usage: "A specific Content-Type to set for the artifacts (otherwise detected)", EnvVar: "BUILDKITE_ARTIFACT_CONTENT_TYPE", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := ArtifactUploadConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) uploader := agent.NewArtifactUploader(l, client, agent.ArtifactUploaderConfig{ JobID: cfg.Job, Paths: cfg.UploadPaths, Destination: cfg.Destination, ContentType: cfg.ContentType, DebugHTTP: cfg.DebugHTTP, }) if err := uploader.Upload(); err != nil { l.Fatal("Failed to upload artifacts: %s", err) } }, }
View Source
var BootstrapCommand = cli.Command{ Name: "bootstrap", Usage: "Run a Buildkite job locally", Description: BootstrapHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "command", Value: "", Usage: "The command to run", EnvVar: "BUILDKITE_COMMAND", }, cli.StringFlag{ Name: "job", Value: "", Usage: "The ID of the job being run", EnvVar: "BUILDKITE_JOB_ID", }, cli.StringFlag{ Name: "repository", Value: "", Usage: "The repository to clone and run the job from", EnvVar: "BUILDKITE_REPO", }, cli.StringFlag{ Name: "commit", Value: "", Usage: "The commit to checkout in the repository", EnvVar: "BUILDKITE_COMMIT", }, cli.StringFlag{ Name: "branch", Value: "", Usage: "The branch the commit is in", EnvVar: "BUILDKITE_BRANCH", }, cli.StringFlag{ Name: "tag", Value: "", Usage: "The tag the commit", EnvVar: "BUILDKITE_TAG", }, cli.StringFlag{ Name: "refspec", Value: "", Usage: "Optional refspec to override git fetch", EnvVar: "BUILDKITE_REFSPEC", }, cli.StringFlag{ Name: "plugins", Value: "", Usage: "The plugins for the job", EnvVar: "BUILDKITE_PLUGINS", }, cli.StringFlag{ Name: "pullrequest", Value: "", Usage: "The number/id of the pull request this commit belonged to", EnvVar: "BUILDKITE_PULL_REQUEST", }, cli.StringFlag{ Name: "agent", Value: "", Usage: "The name of the agent running the job", EnvVar: "BUILDKITE_AGENT_NAME", }, cli.StringFlag{ Name: "organization", Value: "", Usage: "The slug of the organization that the job is a part of", EnvVar: "BUILDKITE_ORGANIZATION_SLUG", }, cli.StringFlag{ Name: "pipeline", Value: "", Usage: "The slug of the pipeline that the job is a part of", EnvVar: "BUILDKITE_PIPELINE_SLUG", }, cli.StringFlag{ Name: "pipeline-provider", Value: "", Usage: "The id of the SCM provider that the repository is hosted on", EnvVar: "BUILDKITE_PIPELINE_PROVIDER", }, cli.StringFlag{ Name: "artifact-upload-paths", Value: "", Usage: "Paths to files to automatically upload at the end of a job", EnvVar: "BUILDKITE_ARTIFACT_PATHS", }, cli.StringFlag{ Name: "artifact-upload-destination", Value: "", Usage: "A custom location to upload artifact paths to (i.e. s3://my-custom-bucket)", EnvVar: "BUILDKITE_ARTIFACT_UPLOAD_DESTINATION", }, cli.BoolFlag{ Name: "clean-checkout", Usage: "Whether or not the bootstrap should remove the existing repository before running the command", EnvVar: "BUILDKITE_CLEAN_CHECKOUT", }, cli.StringFlag{ Name: "git-clone-flags", Value: "-v", Usage: "Flags to pass to \"git clone\" command", EnvVar: "BUILDKITE_GIT_CLONE_FLAGS", }, cli.StringFlag{ Name: "git-clone-mirror-flags", Value: "-v --mirror", Usage: "Flags to pass to \"git clone\" command when mirroring", EnvVar: "BUILDKITE_GIT_CLONE_MIRROR_FLAGS", }, cli.StringFlag{ Name: "git-clean-flags", Value: "-ffxdq", Usage: "Flags to pass to \"git clean\" command", EnvVar: "BUILDKITE_GIT_CLEAN_FLAGS", }, cli.StringFlag{ Name: "git-fetch-flags", Value: "", Usage: "Flags to pass to \"git fetch\" command", EnvVar: "BUILDKITE_GIT_FETCH_FLAGS", }, cli.StringFlag{ Name: "git-mirrors-path", Value: "", Usage: "Path to where mirrors of git repositories are stored", EnvVar: "BUILDKITE_GIT_MIRRORS_PATH", }, cli.IntFlag{ Name: "git-mirrors-lock-timeout", Value: 300, Usage: "Seconds to lock a git mirror during clone, should exceed your longest checkout", EnvVar: "BUILDKITE_GIT_MIRRORS_LOCK_TIMEOUT", }, cli.StringFlag{ Name: "bin-path", Value: "", Usage: "Directory where the buildkite-agent binary lives", EnvVar: "BUILDKITE_BIN_PATH", }, cli.StringFlag{ Name: "build-path", Value: "", Usage: "Directory where builds will be created", EnvVar: "BUILDKITE_BUILD_PATH", }, cli.StringFlag{ Name: "hooks-path", Value: "", Usage: "Directory where the hook scripts are found", EnvVar: "BUILDKITE_HOOKS_PATH", }, cli.StringFlag{ Name: "plugins-path", Value: "", Usage: "Directory where the plugins are saved to", EnvVar: "BUILDKITE_PLUGINS_PATH", }, cli.BoolTFlag{ Name: "command-eval", Usage: "Allow running of arbitrary commands", EnvVar: "BUILDKITE_COMMAND_EVAL", }, cli.BoolTFlag{ Name: "plugins-enabled", Usage: "Allow plugins to be run", EnvVar: "BUILDKITE_PLUGINS_ENABLED", }, cli.BoolFlag{ Name: "plugin-validation", Usage: "Validate plugin configuration", EnvVar: "BUILDKITE_PLUGIN_VALIDATION", }, cli.BoolTFlag{ Name: "local-hooks-enabled", Usage: "Allow local hooks to be run", EnvVar: "BUILDKITE_LOCAL_HOOKS_ENABLED", }, cli.BoolTFlag{ Name: "ssh-keyscan", Usage: "Automatically run ssh-keyscan before checkout", EnvVar: "BUILDKITE_SSH_KEYSCAN", }, cli.BoolTFlag{ Name: "git-submodules", Usage: "Enable git submodules", EnvVar: "BUILDKITE_GIT_SUBMODULES", }, cli.BoolTFlag{ Name: "pty", Usage: "Run jobs within a pseudo terminal", EnvVar: "BUILDKITE_PTY", }, cli.StringFlag{ Name: "shell", Usage: "The shell to use to interpret build commands", EnvVar: "BUILDKITE_SHELL", Value: DefaultShell(), }, cli.StringSliceFlag{ Name: "phases", Usage: "The specific phases to execute. The order they're defined is irrelevant.", EnvVar: "BUILDKITE_BOOTSTRAP_PHASES", }, cli.StringSliceFlag{ Name: "redacted-vars", Usage: "Pattern of environment variable names containing sensitive values", EnvVar: "BUILDKITE_REDACTED_VARS", }, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := BootstrapConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } for _, name := range cfg.Experiments { experiments.Enable(name) } if cfg.Debug { l.SetLevel(logger.DEBUG) } done := HandleProfileFlag(l, cfg) defer done() runInPty := cfg.PTY if runtime.GOOS == "windows" { runInPty = false } for _, phase := range cfg.Phases { switch phase { case "plugin", "checkout", "command": default: l.Fatal("Invalid phase %q", phase) } } bootstrap := bootstrap.New(bootstrap.Config{ Command: cfg.Command, JobID: cfg.JobID, Repository: cfg.Repository, Commit: cfg.Commit, Branch: cfg.Branch, Tag: cfg.Tag, RefSpec: cfg.RefSpec, Plugins: cfg.Plugins, GitSubmodules: cfg.GitSubmodules, PullRequest: cfg.PullRequest, GitCloneFlags: cfg.GitCloneFlags, GitFetchFlags: cfg.GitFetchFlags, GitCloneMirrorFlags: cfg.GitCloneMirrorFlags, GitCleanFlags: cfg.GitCleanFlags, AgentName: cfg.AgentName, PipelineProvider: cfg.PipelineProvider, PipelineSlug: cfg.PipelineSlug, OrganizationSlug: cfg.OrganizationSlug, AutomaticArtifactUploadPaths: cfg.AutomaticArtifactUploadPaths, ArtifactUploadDestination: cfg.ArtifactUploadDestination, CleanCheckout: cfg.CleanCheckout, BuildPath: cfg.BuildPath, GitMirrorsPath: cfg.GitMirrorsPath, GitMirrorsLockTimeout: cfg.GitMirrorsLockTimeout, BinPath: cfg.BinPath, HooksPath: cfg.HooksPath, PluginsPath: cfg.PluginsPath, PluginValidation: cfg.PluginValidation, Debug: cfg.Debug, RunInPty: runInPty, CommandEval: cfg.CommandEval, PluginsEnabled: cfg.PluginsEnabled, LocalHooksEnabled: cfg.LocalHooksEnabled, SSHKeyscan: cfg.SSHKeyscan, Shell: cfg.Shell, Phases: cfg.Phases, RedactedVars: cfg.RedactedVars, }) ctx, cancel := context.WithCancel(context.Background()) defer cancel() signals := make(chan os.Signal, 1) signal.Notify(signals, os.Interrupt, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) defer signal.Stop(signals) var ( cancelled bool received os.Signal signalMu sync.Mutex ) go func() { sig := <-signals signalMu.Lock() defer signalMu.Unlock() bootstrap.Cancel() cancelled = true received = sig signal.Stop(signals) }() exitCode := bootstrap.Run(ctx) signalMu.Lock() defer signalMu.Unlock() if cancelled && runtime.GOOS != `windows` { p, err := os.FindProcess(os.Getpid()) if err != nil { l.Error("Failed to find current process: %v", err) } l.Debug("Terminating bootstrap after cancellation with %v", received) err = p.Signal(received) if err != nil { l.Error("Failed to signal self: %v", err) } } os.Exit(exitCode) }, }
View Source
var BootstrapHelpDescription = `` /* 1025-byte string literal not displayed */
View Source
var DebugFlag = cli.BoolFlag{
Name: "debug",
Usage: "Enable debug mode",
EnvVar: "BUILDKITE_AGENT_DEBUG",
}
View Source
var DebugHTTPFlag = cli.BoolFlag{
Name: "debug-http",
Usage: "Enable HTTP debug mode, which dumps all request and response bodies to the log",
EnvVar: "BUILDKITE_AGENT_DEBUG_HTTP",
}
View Source
var DownloadHelpDescription = `` /* 1020-byte string literal not displayed */
View Source
var EndpointFlag = cli.StringFlag{ Name: "endpoint", Value: DefaultEndpoint, Usage: "The Agent API endpoint", EnvVar: "BUILDKITE_AGENT_ENDPOINT", }
View Source
var ExperimentsFlag = cli.StringSliceFlag{ Name: "experiment", Value: &cli.StringSlice{}, Usage: "Enable experimental features within the buildkite-agent", EnvVar: "BUILDKITE_AGENT_EXPERIMENT", }
View Source
var MetaDataExistsCommand = cli.Command{ Name: "exists", Usage: "Check to see if the meta data key exists for a build", Description: MetaDataExistsHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "job", Value: "", Usage: "Which job's build should the meta-data be checked for", EnvVar: "BUILDKITE_JOB_ID", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := MetaDataExistsConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) // Find the meta data value var err error var exists *api.MetaDataExists var resp *api.Response err = retry.Do(func(s *retry.Stats) error { exists, resp, err = client.ExistsMetaData(cfg.Job, cfg.Key) if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404) { s.Break() } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 10, Interval: 5 * time.Second}) if err != nil { l.Fatal("Failed to see if meta-data exists: %s", err) } if !exists.Exists { os.Exit(100) } }, }
View Source
var MetaDataExistsHelpDescription = `` /* 265-byte string literal not displayed */
View Source
var MetaDataGetCommand = cli.Command{ Name: "get", Usage: "Get data from a build", Description: MetaDataGetHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "default", Value: "", Usage: "If the meta-data value doesn't exist return this instead", }, cli.StringFlag{ Name: "job", Value: "", Usage: "Which job's build should the meta-data be retrieved from", EnvVar: "BUILDKITE_JOB_ID", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := MetaDataGetConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) // Find the meta data value var metaData *api.MetaData var err error var resp *api.Response err = retry.Do(func(s *retry.Stats) error { metaData, resp, err = client.GetMetaData(cfg.Job, cfg.Key) if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404 || resp.StatusCode == 400) { s.Break() return err } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 10, Interval: 5 * time.Second}) if err != nil { if resp.StatusCode == 404 && c.IsSet("default") { l.Warn("No meta-data value exists with key `%s`, returning the supplied default \"%s\"", cfg.Key, cfg.Default) fmt.Print(cfg.Default) return } else { l.Fatal("Failed to get meta-data: %s", err) } } fmt.Print(metaData.Value) }, }
View Source
var MetaDataGetHelpDescription = `` /* 171-byte string literal not displayed */
View Source
var MetaDataKeysCommand = cli.Command{ Name: "keys", Usage: "Lists all meta-data keys that have been previously set", Description: MetaDataKeysHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "job", Value: "", Usage: "Which job's build should the meta-data be checked for", EnvVar: "BUILDKITE_JOB_ID", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := MetaDataKeysConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) // Find the meta data keys var err error var keys []string var resp *api.Response err = retry.Do(func(s *retry.Stats) error { keys, resp, err = client.MetaDataKeys(cfg.Job) if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404) { s.Break() } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 10, Interval: 5 * time.Second}) if err != nil { l.Fatal("Failed to find meta-data keys: %s", err) } for _, key := range keys { fmt.Printf("%s\n", key) } }, }
View Source
var MetaDataKeysHelpDescription = `` /* 243-byte string literal not displayed */
View Source
var MetaDataSetCommand = cli.Command{ Name: "set", Usage: "Set data on a build", Description: MetaDataSetHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "job", Value: "", Usage: "Which job's build should the meta-data be set on", EnvVar: "BUILDKITE_JOB_ID", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := MetaDataSetConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() if len(c.Args()) < 2 { l.Info("Reading meta-data value from STDIN") input, err := ioutil.ReadAll(os.Stdin) if err != nil { l.Fatal("Failed to read from STDIN: %s", err) } cfg.Value = string(input) } client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) metaData := &api.MetaData{ Key: cfg.Key, Value: cfg.Value, } err := retry.Do(func(s *retry.Stats) error { resp, err := client.SetMetaData(cfg.Job, metaData) if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404) { s.Break() } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 10, Interval: 5 * time.Second}) if err != nil { l.Fatal("Failed to set meta-data: %s", err) } }, }
View Source
var MetaDataSetHelpDescription = `` /* 442-byte string literal not displayed */
View Source
var NoColorFlag = cli.BoolFlag{
Name: "no-color",
Usage: "Don't show colors in logging",
EnvVar: "BUILDKITE_AGENT_NO_COLOR",
}
View Source
var NoHTTP2Flag = cli.BoolFlag{
Name: "no-http2",
Usage: "Disable HTTP2 when communicating with the Agent API.",
EnvVar: "BUILDKITE_NO_HTTP2",
}
View Source
var PipelineUploadCommand = cli.Command{ Name: "upload", Usage: "Uploads a description of a build pipeline adds it to the currently running build after the current job.", Description: PipelineUploadHelpDescription, Flags: []cli.Flag{ cli.BoolFlag{ Name: "replace", Usage: "Replace the rest of the existing pipeline with the steps uploaded. Jobs that are already running are not removed.", EnvVar: "BUILDKITE_PIPELINE_REPLACE", }, cli.StringFlag{ Name: "job", Value: "", Usage: "The job that is making the changes to its build", EnvVar: "BUILDKITE_JOB_ID", }, cli.BoolFlag{ Name: "dry-run", Usage: "Rather than uploading the pipeline, it will be echoed to stdout", EnvVar: "BUILDKITE_PIPELINE_UPLOAD_DRY_RUN", }, cli.BoolFlag{ Name: "no-interpolation", Usage: "Skip variable interpolation the pipeline when uploaded", EnvVar: "BUILDKITE_PIPELINE_NO_INTERPOLATION", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := PipelineUploadConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() // Find the pipeline file either from STDIN or the first // argument var input []byte var err error var filename string if cfg.FilePath != "" { l.Info("Reading pipeline config from \"%s\"", cfg.FilePath) filename = filepath.Base(cfg.FilePath) input, err = ioutil.ReadFile(cfg.FilePath) if err != nil { l.Fatal("Failed to read file: %s", err) } } else if stdin.IsReadable() { l.Info("Reading pipeline config from STDIN") input, err = ioutil.ReadAll(os.Stdin) if err != nil { l.Fatal("Failed to read from STDIN: %s", err) } } else { l.Info("Searching for pipeline config...") paths := []string{ "buildkite.yml", "buildkite.yaml", "buildkite.json", filepath.FromSlash(".buildkite/pipeline.yml"), filepath.FromSlash(".buildkite/pipeline.yaml"), filepath.FromSlash(".buildkite/pipeline.json"), filepath.FromSlash("buildkite/pipeline.yml"), filepath.FromSlash("buildkite/pipeline.yaml"), filepath.FromSlash("buildkite/pipeline.json"), } exists := []string{} for _, path := range paths { if _, err := os.Stat(path); err == nil { exists = append(exists, path) } } if len(exists) > 1 { l.Fatal("Found multiple configuration files: %s. Please only have 1 configuration file present.", strings.Join(exists, ", ")) } else if len(exists) == 0 { l.Fatal("Could not find a default pipeline configuration file. See `buildkite-agent pipeline upload --help` for more information.") } found := exists[0] l.Info("Found config file \"%s\"", found) filename = path.Base(found) input, err = ioutil.ReadFile(found) if err != nil { l.Fatal("Failed to read file \"%s\" (%s)", found, err) } } if len(input) == 0 { l.Fatal("Config file is empty") } environ := env.FromSlice(os.Environ()) if commitRef, ok := environ.Get(`BUILDKITE_COMMIT`); ok { cmdOut, err := exec.Command(`git`, `rev-parse`, commitRef).Output() if err != nil { l.Warn("Error running git rev-parse %q: %v", commitRef, err) } else { trimmedCmdOut := strings.TrimSpace(string(cmdOut)) l.Info("Updating BUILDKITE_COMMIT to %q", trimmedCmdOut) environ.Set(`BUILDKITE_COMMIT`, trimmedCmdOut) } } result, err := agent.PipelineParser{ Env: environ, Filename: filename, Pipeline: input, NoInterpolation: cfg.NoInterpolation, }.Parse() if err != nil { src := filename if src == "" { src = "(stdin)" } l.Fatal("Pipeline parsing of \"%s\" failed (%s)", src, err) } if cfg.DryRun { enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") if err := enc.Encode(result); err != nil { l.Fatal("%#v", err) } return } if cfg.Job == "" { l.Fatal("Missing job parameter. Usually this is set in the environment for a Buildkite job via BUILDKITE_JOB_ID.") } if cfg.AgentAccessToken == "" { l.Fatal("Missing agent-access-token parameter. Usually this is set in the environment for a Buildkite job via BUILDKITE_AGENT_ACCESS_TOKEN.") } client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) uuid := api.NewUUID() err = retry.Do(func(s *retry.Stats) error { _, err = client.UploadPipeline(cfg.Job, &api.Pipeline{UUID: uuid, Pipeline: result, Replace: cfg.Replace}) if err != nil { l.Warn("%s (%s)", err, s) if apierr, ok := err.(*api.ErrorResponse); ok && apierr.Response.StatusCode == 422 { l.Error("Unrecoverable error, skipping retries") s.Break() } } return err }, &retry.Config{Maximum: 60, Interval: 5 * time.Second}) if err != nil { l.Fatal("Failed to upload and process pipeline: %s", err) } l.Info("Successfully uploaded and parsed pipeline config") }, }
View Source
var PipelineUploadHelpDescription = `` /* 841-byte string literal not displayed */
View Source
var ProfileFlag = cli.StringFlag{
Name: "profile",
Usage: "Enable a profiling mode, either cpu, memory, mutex or block",
EnvVar: "BUILDKITE_AGENT_PROFILE",
}
View Source
var SearchHelpDescription = `` /* 1102-byte string literal not displayed */
View Source
var ShasumHelpDescription = `` /* 937-byte string literal not displayed */
View Source
var StartDescription = `` /* 450-byte string literal not displayed */
View Source
var StepGetCommand = cli.Command{ Name: "get", Usage: "Get the value of an attribute", Description: StepGetHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "step", Value: "", Usage: "The step to get. Can be either its ID (BUILDKITE_STEP_ID) or key (BUILDKITE_STEP_KEY)", EnvVar: "BUILDKITE_STEP_ID", }, cli.StringFlag{ Name: "build", Value: "", Usage: "The build to look for the step in. Only required when targeting a step using its key (BUILDKITE_STEP_KEY)", EnvVar: "BUILDKITE_BUILD_ID", }, cli.StringFlag{ Name: "format", Value: "", Usage: "The format to output the attribute value in (currently only JSON is supported)", EnvVar: "BUILDKITE_STEP_GET_FORMAT", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := StepGetConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) stepExportRequest := &api.StepExportRequest{ Build: cfg.Build, Attribute: cfg.Attribute, Format: cfg.Format, } // Find the step attribute var err error var resp *api.Response var stepExportResponse *api.StepExportResponse err = retry.Do(func(s *retry.Stats) error { stepExportResponse, resp, err = client.StepExport(cfg.StepOrKey, stepExportRequest) if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404 || resp.StatusCode == 400) { s.Break() return err } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 10, Interval: 5 * time.Second}) if err != nil { l.Fatal("Failed to get step: %s", err) } fmt.Print(stepExportResponse.Output) }, }
View Source
var StepGetHelpDescription = `` /* 604-byte string literal not displayed */
View Source
var StepUpdateCommand = cli.Command{ Name: "update", Usage: "Change the value of an attribute", Description: StepUpdateHelpDescription, Flags: []cli.Flag{ cli.StringFlag{ Name: "step", Value: "", Usage: "The step to update. Can be either its ID (BUILDKITE_STEP_ID) or key (BUILDKITE_STEP_KEY)", EnvVar: "BUILDKITE_STEP_ID", }, cli.StringFlag{ Name: "build", Value: "", Usage: "The build to look for the step in. Only required when targeting a step using its key (BUILDKITE_STEP_KEY)", EnvVar: "BUILDKITE_BUILD_ID", }, cli.BoolFlag{ Name: "append", Usage: "Append to current attribute instead of replacing it", EnvVar: "BUILDKITE_STEP_UPDATE_APPEND", }, AgentAccessTokenFlag, EndpointFlag, NoHTTP2Flag, DebugHTTPFlag, NoColorFlag, DebugFlag, ExperimentsFlag, ProfileFlag, }, Action: func(c *cli.Context) { cfg := StepUpdateConfig{} l := CreateLogger(&cfg) if err := cliconfig.Load(c, l, &cfg); err != nil { l.Fatal("%s", err) } done := HandleGlobalFlags(l, cfg) defer done() if len(c.Args()) < 2 { l.Info("Reading value from STDIN") input, err := ioutil.ReadAll(os.Stdin) if err != nil { l.Fatal("Failed to read from STDIN: %s", err) } cfg.Value = string(input) } client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`)) idempotencyUUID := api.NewUUID() update := &api.StepUpdate{ IdempotencyUUID: idempotencyUUID, Build: cfg.Build, Attribute: cfg.Attribute, Value: cfg.Value, Append: cfg.Append, } err := retry.Do(func(s *retry.Stats) error { resp, err := client.StepUpdate(cfg.StepOrKey, update) if resp != nil && (resp.StatusCode == 400 || resp.StatusCode == 401 || resp.StatusCode == 404) { s.Break() } if err != nil { l.Warn("%s (%s)", err, s) } return err }, &retry.Config{Maximum: 10, Interval: 5 * time.Second}) if err != nil { l.Fatal("Failed to change step: %s", err) } }, }
View Source
var StepUpdateHelpDescription = `` /* 405-byte string literal not displayed */
View Source
var UploadHelpDescription = `` /* 1628-byte string literal not displayed */
Functions ¶
func CreateLogger ¶
func DefaultConfigFilePaths ¶
func DefaultConfigFilePaths() (paths []string)
func DefaultShell ¶
func DefaultShell() string
func HandleGlobalFlags ¶
func HandleProfileFlag ¶
Types ¶
type AgentStartConfig ¶
type AgentStartConfig struct { Config string `cli:"config"` Name string `cli:"name"` Priority string `cli:"priority"` AcquireJob string `cli:"acquire-job"` DisconnectAfterJob bool `cli:"disconnect-after-job"` DisconnectAfterIdleTimeout int `cli:"disconnect-after-idle-timeout"` BootstrapScript string `cli:"bootstrap-script" normalize:"commandpath"` CancelGracePeriod int `cli:"cancel-grace-period"` BuildPath string `cli:"build-path" normalize:"filepath" validate:"required"` HooksPath string `cli:"hooks-path" normalize:"filepath"` PluginsPath string `cli:"plugins-path" normalize:"filepath"` Shell string `cli:"shell"` Tags []string `cli:"tags" normalize:"list"` TagsFromEC2MetaData bool `cli:"tags-from-ec2-meta-data"` TagsFromEC2MetaDataPaths []string `cli:"tags-from-ec2-meta-data-paths" normalize:"list"` TagsFromEC2Tags bool `cli:"tags-from-ec2-tags"` TagsFromGCPMetaData bool `cli:"tags-from-gcp-meta-data"` TagsFromGCPMetaDataPaths []string `cli:"tags-from-gcp-meta-data-paths" normalize:"list"` TagsFromGCPLabels bool `cli:"tags-from-gcp-labels"` TagsFromHost bool `cli:"tags-from-host"` WaitForEC2TagsTimeout string `cli:"wait-for-ec2-tags-timeout"` WaitForGCPLabelsTimeout string `cli:"wait-for-gcp-labels-timeout"` GitCloneFlags string `cli:"git-clone-flags"` GitCloneMirrorFlags string `cli:"git-clone-mirror-flags"` GitCleanFlags string `cli:"git-clean-flags"` GitFetchFlags string `cli:"git-fetch-flags"` GitMirrorsPath string `cli:"git-mirrors-path" normalize:"filepath"` GitMirrorsLockTimeout int `cli:"git-mirrors-lock-timeout"` NoGitSubmodules bool `cli:"no-git-submodules"` NoSSHKeyscan bool `cli:"no-ssh-keyscan"` NoCommandEval bool `cli:"no-command-eval"` NoLocalHooks bool `cli:"no-local-hooks"` NoPlugins bool `cli:"no-plugins"` NoPluginValidation bool `cli:"no-plugin-validation"` NoPTY bool `cli:"no-pty"` TimestampLines bool `cli:"timestamp-lines"` HealthCheckAddr string `cli:"health-check-addr"` MetricsDatadog bool `cli:"metrics-datadog"` MetricsDatadogHost string `cli:"metrics-datadog-host"` Spawn int `cli:"spawn"` LogFormat string `cli:"log-format"` CancelSignal string `cli:"cancel-signal"` RedactedVars []string `cli:"redacted-vars" normalize:"list"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` Token string `cli:"token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` // Deprecated NoSSHFingerprintVerification bool `cli:"no-automatic-ssh-fingerprint-verification" deprecated-and-renamed-to:"NoSSHKeyscan"` MetaData []string `cli:"meta-data" deprecated-and-renamed-to:"Tags"` MetaDataEC2 bool `cli:"meta-data-ec2" deprecated-and-renamed-to:"TagsFromEC2"` MetaDataEC2Tags bool `cli:"meta-data-ec2-tags" deprecated-and-renamed-to:"TagsFromEC2Tags"` MetaDataGCP bool `cli:"meta-data-gcp" deprecated-and-renamed-to:"TagsFromGCP"` TagsFromEC2 bool `cli:"tags-from-ec2" deprecated-and-renamed-to:"TagsFromEC2MetaData"` TagsFromGCP bool `cli:"tags-from-gcp" deprecated-and-renamed-to:"TagsFromGCPMetaData"` DisconnectAfterJobTimeout int `cli:"disconnect-after-job-timeout" deprecated:"Use disconnect-after-idle-timeout instead"` }
type AnnotateConfig ¶
type AnnotateConfig struct { Body string `cli:"arg:0" label:"annotation body"` Style string `cli:"style"` Context string `cli:"context"` Append bool `cli:"append"` Job string `cli:"job" validate:"required"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type ArtifactDownloadConfig ¶
type ArtifactDownloadConfig struct { Query string `cli:"arg:0" label:"artifact search query" validate:"required"` Destination string `cli:"arg:1" label:"artifact download path" validate:"required"` Step string `cli:"step"` Build string `cli:"build" validate:"required"` IncludeRetriedJobs bool `cli:"include-retried-jobs"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type ArtifactSearchConfig ¶ added in v3.23.0
type ArtifactSearchConfig struct { Query string `cli:"arg:0" label:"artifact search query" validate:"required"` Step string `cli:"step"` Build string `cli:"build" validate:"required"` IncludeRetriedJobs bool `cli:"include-retried-jobs"` PrintFormat string `cli:"format"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type ArtifactShasumConfig ¶
type ArtifactShasumConfig struct { Query string `cli:"arg:0" label:"artifact search query" validate:"required"` Step string `cli:"step"` Build string `cli:"build" validate:"required"` IncludeRetriedJobs bool `cli:"include-retried-jobs"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type ArtifactUploadConfig ¶
type ArtifactUploadConfig struct { UploadPaths string `cli:"arg:0" label:"upload paths" validate:"required"` Destination string `cli:"arg:1" label:"destination" env:"BUILDKITE_ARTIFACT_UPLOAD_DESTINATION"` Job string `cli:"job" validate:"required"` ContentType string `cli:"content-type"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type BootstrapConfig ¶
type BootstrapConfig struct { Command string `cli:"command"` JobID string `cli:"job" validate:"required"` Repository string `cli:"repository" validate:"required"` Commit string `cli:"commit" validate:"required"` Branch string `cli:"branch" validate:"required"` Tag string `cli:"tag"` RefSpec string `cli:"refspec"` Plugins string `cli:"plugins"` PullRequest string `cli:"pullrequest"` GitSubmodules bool `cli:"git-submodules"` SSHKeyscan bool `cli:"ssh-keyscan"` AgentName string `cli:"agent" validate:"required"` OrganizationSlug string `cli:"organization" validate:"required"` PipelineSlug string `cli:"pipeline" validate:"required"` PipelineProvider string `cli:"pipeline-provider" validate:"required"` AutomaticArtifactUploadPaths string `cli:"artifact-upload-paths"` ArtifactUploadDestination string `cli:"artifact-upload-destination"` CleanCheckout bool `cli:"clean-checkout"` GitCloneFlags string `cli:"git-clone-flags"` GitFetchFlags string `cli:"git-fetch-flags"` GitCloneMirrorFlags string `cli:"git-clone-mirror-flags"` GitCleanFlags string `cli:"git-clean-flags"` GitMirrorsPath string `cli:"git-mirrors-path" normalize:"filepath"` GitMirrorsLockTimeout int `cli:"git-mirrors-lock-timeout"` BinPath string `cli:"bin-path" normalize:"filepath"` BuildPath string `cli:"build-path" normalize:"filepath"` HooksPath string `cli:"hooks-path" normalize:"filepath"` PluginsPath string `cli:"plugins-path" normalize:"filepath"` CommandEval bool `cli:"command-eval"` PluginsEnabled bool `cli:"plugins-enabled"` PluginValidation bool `cli:"plugin-validation"` LocalHooksEnabled bool `cli:"local-hooks-enabled"` PTY bool `cli:"pty"` Debug bool `cli:"debug"` Shell string `cli:"shell"` Experiments []string `cli:"experiment" normalize:"list"` Phases []string `cli:"phases" normalize:"list"` Profile string `cli:"profile"` RedactedVars []string `cli:"redacted-vars" normalize:"list"` }
type MetaDataExistsConfig ¶
type MetaDataExistsConfig struct { Key string `cli:"arg:0" label:"meta-data key" validate:"required"` Job string `cli:"job" validate:"required"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type MetaDataGetConfig ¶
type MetaDataGetConfig struct { Key string `cli:"arg:0" label:"meta-data key" validate:"required"` Default string `cli:"default"` Job string `cli:"job" validate:"required"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type MetaDataKeysConfig ¶
type MetaDataKeysConfig struct { Job string `cli:"job" validate:"required"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type MetaDataSetConfig ¶
type MetaDataSetConfig struct { Key string `cli:"arg:0" label:"meta-data key" validate:"required"` Value string `cli:"arg:1" label:"meta-data value"` Job string `cli:"job" validate:"required"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type PipelineUploadConfig ¶
type PipelineUploadConfig struct { FilePath string `cli:"arg:0" label:"upload paths"` Replace bool `cli:"replace"` Job string `cli:"job"` DryRun bool `cli:"dry-run"` NoInterpolation bool `cli:"no-interpolation"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type StepGetConfig ¶
type StepGetConfig struct { Attribute string `cli:"arg:0" label:"step attribute"` StepOrKey string `cli:"step" validate:"required"` Build string `cli:"build"` Format string `cli:"format"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
type StepUpdateConfig ¶
type StepUpdateConfig struct { Attribute string `cli:"arg:0" label:"attribute" validate:"required"` Value string `cli:"arg:1" label:"value"` Append bool `cli:"append"` StepOrKey string `cli:"step" validate:"required"` Build string `cli:"build"` // Global flags Debug bool `cli:"debug"` NoColor bool `cli:"no-color"` Experiments []string `cli:"experiment" normalize:"list"` Profile string `cli:"profile"` // API config DebugHTTP bool `cli:"debug-http"` AgentAccessToken string `cli:"agent-access-token" validate:"required"` Endpoint string `cli:"endpoint" validate:"required"` NoHTTP2 bool `cli:"no-http2"` }
Click to show internal directories.
Click to hide internal directories.