Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a command to allow removal of existing annotations #1364

Merged
merged 4 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions agent/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type APIClient interface {
AcceptJob(*api.Job) (*api.Job, *api.Response, error)
AcquireJob(string) (*api.Job, *api.Response, error)
Annotate(string, *api.Annotation) (*api.Response, error)
AnnotationRemove(string, string) (*api.Response, error)
Config() api.Config
Connect() (*api.Response, error)
CreateArtifacts(string, *api.ArtifactBatch) (*api.ArtifactBatchCreateResponse, *api.Response, error)
Expand Down
12 changes: 12 additions & 0 deletions api/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,15 @@ func (c *Client) Annotate(jobId string, annotation *Annotation) (*Response, erro

return c.doRequest(req, nil)
}

// Remove an annotation from a build
func (c *Client) AnnotationRemove(jobId string, context string) (*Response, error) {
u := fmt.Sprintf("jobs/%s/annotations/%s", jobId, context)

req, err := c.newRequest("DELETE", u, nil)
if err != nil {
return nil, err
}

return c.doRequest(req, nil)
}
121 changes: 121 additions & 0 deletions clicommand/annotation_remove.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package clicommand

import (
"time"

"github.com/buildkite/agent/v3/api"
"github.com/buildkite/agent/v3/cliconfig"
"github.com/buildkite/agent/v3/retry"
"github.com/urfave/cli"
)

var AnnotationRemoveHelpDescription = `Usage:

buildkite-agent annotation remove [arguments...]

Description:

Remove an existing annotation which was previously published using the
buildkite-agent annotate command.

Or if you leave context blank, it will use the default context.
ticky marked this conversation as resolved.
Show resolved Hide resolved

Example:

$ buildkite-agent annotation remove
$ buildkite-agent annotation remove --context "remove-me"`

type AnnotationRemoveConfig struct {
Context string `cli:"context" 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"`
}

var AnnotationRemoveCommand = cli.Command{
Name: "remove",
Usage: "Remove an existing annotation from a Buildkite build",
Description: AnnotationRemoveHelpDescription,
Flags: []cli.Flag{
cli.StringFlag{
Name: "context",
Value: "default",
Usage: "The context of the annotation used to differentiate this annotation from others",
EnvVar: "BUILDKITE_ANNOTATION_CONTEXT",
},
cli.StringFlag{
Name: "job",
Value: "",
Usage: "Which job should the annotation come from",
ticky marked this conversation as resolved.
Show resolved Hide resolved
EnvVar: "BUILDKITE_JOB_ID",
},

// API Flags
AgentAccessTokenFlag,
EndpointFlag,
NoHTTP2Flag,
DebugHTTPFlag,

// Global flags
NoColorFlag,
DebugFlag,
ExperimentsFlag,
ProfileFlag,
},
Action: func(c *cli.Context) {
// The configuration will be loaded into this struct
cfg := AnnotationRemoveConfig{}

l := CreateLogger(&cfg)

// Load the configuration
if err := cliconfig.Load(c, l, &cfg); err != nil {
l.Fatal("%s", err)
}

// Setup any global configuration options
done := HandleGlobalFlags(l, cfg)
defer done()

var err error

// Create the API client
client := api.NewClient(l, loadAPIClientConfig(cfg, `AgentAccessToken`))

// Retry the removal a few times before giving up
err = retry.Do(func(s *retry.Stats) error {
// Attempt to remove the annotation
resp, err := client.AnnotationRemove(cfg.Job, cfg.Context)

// Don't bother retrying if the response was one of these statuses
if resp != nil && (resp.StatusCode == 401 || resp.StatusCode == 404 || resp.StatusCode == 400) {
s.Break()
return err
}

// Show the unexpected error
if err != nil {
l.Warn("%s (%s)", err, s)
}

return err
}, &retry.Config{Maximum: 5, Interval: 1 * time.Second, Jitter: true})

// Show a fatal error if we gave up trying to create the annotation
if err != nil {
l.Fatal("Failed to remove annotation: %s", err)
}

l.Debug("Successfully removed annotation")
},
}
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ func main() {
app.Commands = []cli.Command{
clicommand.AgentStartCommand,
clicommand.AnnotateCommand,
{
Name: "annotation",
Usage: "Make changes an annotation on the currently running build",
Subcommands: []cli.Command{
clicommand.AnnotationRemoveCommand,
},
},
{
Name: "artifact",
Usage: "Upload/download artifacts from Buildkite jobs",
Expand Down