diff --git a/CHANGELOG.md b/CHANGELOG.md index 1143c042..144de44e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## Unreleased +* SUP-1448: Pipeline Templates integration [#165](https://github.com/buildkite/go-buildkite/pull/165) ([james2791](https://github.com/james2791)) ## [v3.8.0](https://github.com/buildkite/go-buildkite/compare/v3.7.0...v3.8.0) (2023-11-02) * SUP-1537: Annotations create endpoint interaction [#163](https://github.com/buildkite/go-buildkite/pull/163) ([james2791](https://github.com/james2791)) diff --git a/buildkite/buildkite.go b/buildkite/buildkite.go index 06aa0b87..99605286 100644 --- a/buildkite/buildkite.go +++ b/buildkite/buildkite.go @@ -41,23 +41,24 @@ type Client struct { UserAgent string // Services used for talking to different parts of the buildkite API. - AccessTokens *AccessTokensService - Agents *AgentsService - Annotations *AnnotationsService - Artifacts *ArtifactsService - Builds *BuildsService - Clusters *ClustersService - ClusterQueues *ClusterQueuesService - ClusterTokens *ClusterTokensService - FlakyTests *FlakyTestsService - Jobs *JobsService - Organizations *OrganizationsService - Pipelines *PipelinesService - User *UserService - Teams *TeamsService - Tests *TestsService - TestRuns *TestRunsService - TestSuites *TestSuitesService + AccessTokens *AccessTokensService + Agents *AgentsService + Annotations *AnnotationsService + Artifacts *ArtifactsService + Builds *BuildsService + Clusters *ClustersService + ClusterQueues *ClusterQueuesService + ClusterTokens *ClusterTokensService + FlakyTests *FlakyTestsService + Jobs *JobsService + Organizations *OrganizationsService + Pipelines *PipelinesService + PipelineTemplates *PipelineTemplatesService + User *UserService + Teams *TeamsService + Tests *TestsService + TestRuns *TestRunsService + TestSuites *TestSuitesService } // ListOptions specifies the optional parameters to various List methods that @@ -92,6 +93,7 @@ func NewClient(httpClient *http.Client) *Client { c.Jobs = &JobsService{c} c.Organizations = &OrganizationsService{c} c.Pipelines = &PipelinesService{c} + c.PipelineTemplates = &PipelineTemplatesService{c} c.User = &UserService{c} c.Teams = &TeamsService{c} c.Tests = &TestsService{c} diff --git a/buildkite/pipeline_templates.go b/buildkite/pipeline_templates.go new file mode 100644 index 00000000..3e86428a --- /dev/null +++ b/buildkite/pipeline_templates.go @@ -0,0 +1,158 @@ +package buildkite + +import ( + "errors" + "fmt" +) + +// PipelineTemplatesService handles communication with pipeline template related +// methods of the Buildkite API. +// +// Buildkite API docs: +type PipelineTemplatesService struct { + client *Client +} + +type PipelineTemplate struct { + UUID *string `json:"uuid,omitempty" yaml:"uuid,omitempty"` + GraphQLID *string `json:"graphql_id,omitempty" yaml:"graphql_id,omitempty"` + Name *string `json:"name,omitempty" yaml:"name,omitempty"` + Description *string `json:"description,omitempty" yaml:"description,omitempty"` + Configuration *string `json:"configuration,omitempty" yaml:"configuration,omitempty"` + Available *bool `json:"available,omitempty" yaml:"available,omitempty"` + URL *string `json:"url,omitempty" yaml:"url,omitempty"` + WebURL *string `json:"web_url,omitempty" yaml:"web_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty" yaml:"created_at,omitempty"` + CreatedBy *PipelineTemplateCreator `json:"created_by,omitempty" yaml:"created_by,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty" yaml:"updated_at,omitempty"` + UpdatedBy *PipelineTemplateCreator `json:"updated_by,omitempty" yaml:"updated_by,omitempty"` +} + +type PipelineTemplateCreateUpdate struct { + Name *string `json:"name,omitempty" yaml:"name,omitempty"` + Configuration *string `json:"configuration,omitempty" yaml:"configuration,omitempty"` + Description *string `json:"description,omitempty" yaml:"description,omitempty"` + Available *bool `json:"available,omitempty" yaml:"available,omitempty"` +} + +type PipelineTemplateCreator struct { + ID *string `json:"id,omitempty" yaml:"id,omitempty"` + GraphQLID *string `json:"graphql_id,omitempty" yaml:"graphql_id,omitempty"` + Name *string `json:"name,omitempty" yaml:"name,omitempty"` + Email *string `json:"email,omitempty" yaml:"email,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty" yaml:"avatar_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty" yaml:"created_at,omitempty"` +} + +type PipelineTemplateListOptions struct { + ListOptions +} + +func (pts *PipelineTemplatesService) List(org string, opt *PipelineTemplateListOptions) ([]PipelineTemplate, *Response, error) { + + u := fmt.Sprintf("v2/organizations/%s/pipeline-templates", org) + + u, err := addOptions(u, opt) + + if err != nil { + return nil, nil, err + } + + req, err := pts.client.NewRequest("GET", u, nil) + + if err != nil { + return nil, nil, err + } + + templates := new([]PipelineTemplate) + + resp, err := pts.client.Do(req, templates) + + if err != nil { + return nil, resp, err + } + + return *templates, resp, err +} + +func (pts *PipelineTemplatesService) Get(org, templateUUID string) (*PipelineTemplate, *Response, error) { + + u := fmt.Sprintf("v2/organizations/%s/pipeline-templates/%s", org, templateUUID) + + req, err := pts.client.NewRequest("GET", u, nil) + + if err != nil { + return nil, nil, err + } + + template := new(PipelineTemplate) + + resp, err := pts.client.Do(req, template) + + if err != nil { + return nil, resp, err + } + + return template, resp, err +} + +func (pts *PipelineTemplatesService) Create(org string, ptc *PipelineTemplateCreateUpdate) (*PipelineTemplate, *Response, error) { + + if ptc == nil { + return nil, nil, errors.New("PipelineTemplateCreateUpdate struct instance must not be nil") + } + + u := fmt.Sprintf("v2/organizations/%s/pipeline-templates", org) + + req, err := pts.client.NewRequest("POST", u, ptc) + + if err != nil { + return nil, nil, err + } + + template := new(PipelineTemplate) + + resp, err := pts.client.Do(req, template) + + if err != nil { + return nil, resp, err + } + + return template, resp, err +} + +func (pts *PipelineTemplatesService) Update(org, templateUUID string, ptu *PipelineTemplateCreateUpdate) (*Response, error) { + + if ptu == nil { + return nil, errors.New("PipelineTemplateCreateUpdate struct instance must not be nil") + } + + u := fmt.Sprintf("v2/organizations/%s/pipeline-templates/%s", org, templateUUID) + + req, err := pts.client.NewRequest("PATCH", u, ptu) + + if err != nil { + return nil, nil + } + + resp, err := pts.client.Do(req, ptu) + + if err != nil { + return resp, err + } + + return resp, err +} + +func (pts *PipelineTemplatesService) Delete(org, templateUUID string) (*Response, error) { + + u := fmt.Sprintf("v2/organizations/%s/pipeline-templates/%s", org, templateUUID) + + req, err := pts.client.NewRequest("DELETE", u, nil) + + if err != nil { + return nil, err + } + + return pts.client.Do(req, nil) +} diff --git a/buildkite/pipeline_templates_test.go b/buildkite/pipeline_templates_test.go new file mode 100644 index 00000000..1dfb7c6d --- /dev/null +++ b/buildkite/pipeline_templates_test.go @@ -0,0 +1,361 @@ +package buildkite + +import ( + "encoding/json" + "fmt" + "net/http" + "reflect" + "testing" + "time" +) + +func TestPipelineTemplatesService_List(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/organizations/my-great-org/pipeline-templates", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, + ` + [ + { + "uuid": "90333dc7-b86a-4485-98c3-9419a5dbc52e", + "graphql_id": "UGlwZWxpbmVUZW1wbG5lLS0tOTAzMzNkYzctYjg2YS00NDg1LTk4YzMtOTQxOWE1ZGJjNTJl==", + "name": "Pipeline Upload Template", + "description": "Pipeline template with basic YAML pipeline upload", + "configuration": "steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload\"\n", + "available": true, + "created_at": "2023-08-11T01:22:05.650Z", + "created_by": { + "id": "7da07e25-0383-4aff-a7cf-14d1a9aa098f", + "graphql_id": "VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg==", + "name": "Joe Smith", + "email": "jsmith@example.com", + "avatar_url": "https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4", + "created_at": "2023-02-20T03:00:05.824Z" + }, + "updated_at": "2023-08-11T01:22:05.650Z", + "updated_by": { + "id": "7da07e25-0383-4aff-a7cf-14d1a9aa098f", + "graphql_id": "VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg==", + "name": "Joe Smith", + "email": "jsmith@example.com", + "avatar_url": "https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4", + "created_at": "2023-02-20T03:00:05.824Z" + }, + "url": "https://api.buildkite.com/v2/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e", + "web_url": "https://buildkite.com/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e" + }, + { + "uuid": "6a25cc85-9fa2-4a00-b66c-bfe377bc5f78", + "graphql_id": "UGlwZWxpbmVUZW1wbG5lLS0tNmEyNWNjODUtOWZhMi00YTAwLWI2NmMtYmZlMzc3YmM1Zjc4==", + "name": "Pipeline-Dev Upload Template", + "description": "Pipeline template uploading buildkite-dev.yml", + "configuration": "steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-dev.yml\"\n", + "available": true, + "created_at": "2023-08-11T02:24:33.602Z", + "created_by": { + "id": "7da07e25-0383-4aff-a7cf-14d1a9aa098f", + "graphql_id": "VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg==", + "name": "Joe Smith", + "email": "jsmith@example.com", + "avatar_url": "https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4", + "created_at": "2023-02-20T03:00:05.824Z" + }, + "updated_at": "2023-08-11T02:24:33.602Z", + "updated_by": { + "id": "7da07e25-0383-4aff-a7cf-14d1a9aa098f", + "graphql_id": "VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg==", + "name": "Joe Smith", + "email": "jsmith@example.com", + "avatar_url": "https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4", + "created_at": "2023-02-20T03:00:05.824Z" + }, + "url": "https://api.buildkite.com/v2/organizations/my-great-org/pipeline-templates/6a25cc85-9fa2-4a00-b66c-bfe377bc5f78", + "web_url": "https://buildkite.com/organizations/my-great-org/pipeline-templates/6a25cc85-9fa2-4a00-b66c-bfe377bc5f78" + } + ]`) + }) + + pipelineTemplates, _, err := client.PipelineTemplates.List("my-great-org", nil) + + if err != nil { + t.Errorf("TestPipelineTemplates.List returned error: %v", err) + } + + basicTemplateCreatedAt, err := time.Parse(BuildKiteDateFormat, "2023-08-11T01:22:05.650Z") + devTemplateCreatedAt, err := time.Parse(BuildKiteDateFormat, "2023-08-11T02:24:33.602Z") + userCreatedAt, err := time.Parse(BuildKiteDateFormat, "2023-02-20T03:00:05.824Z") + + pipelineTemplateCreator := &PipelineTemplateCreator{ + ID: String("7da07e25-0383-4aff-a7cf-14d1a9aa098f"), + GraphQLID: String("VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg=="), + Name: String("Joe Smith"), + Email: String("jsmith@example.com"), + AvatarURL: String("https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4"), + CreatedAt: NewTimestamp(userCreatedAt), + } + + want := []PipelineTemplate{ + { + UUID: String("90333dc7-b86a-4485-98c3-9419a5dbc52e"), + GraphQLID: String("UGlwZWxpbmVUZW1wbG5lLS0tOTAzMzNkYzctYjg2YS00NDg1LTk4YzMtOTQxOWE1ZGJjNTJl=="), + Name: String("Pipeline Upload Template"), + Description: String("Pipeline template with basic YAML pipeline upload"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload\"\n"), + Available: Bool(true), + CreatedAt: NewTimestamp(basicTemplateCreatedAt), + CreatedBy: pipelineTemplateCreator, + UpdatedAt: NewTimestamp(basicTemplateCreatedAt), + UpdatedBy: pipelineTemplateCreator, + URL: String("https://api.buildkite.com/v2/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e"), + WebURL: String("https://buildkite.com/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e"), + }, + { + UUID: String("6a25cc85-9fa2-4a00-b66c-bfe377bc5f78"), + GraphQLID: String("UGlwZWxpbmVUZW1wbG5lLS0tNmEyNWNjODUtOWZhMi00YTAwLWI2NmMtYmZlMzc3YmM1Zjc4=="), + Name: String("Pipeline-Dev Upload Template"), + Description: String("Pipeline template uploading buildkite-dev.yml"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-dev.yml\"\n"), + Available: Bool(true), + CreatedAt: NewTimestamp(devTemplateCreatedAt), + CreatedBy: pipelineTemplateCreator, + UpdatedAt: NewTimestamp(devTemplateCreatedAt), + UpdatedBy: pipelineTemplateCreator, + URL: String("https://api.buildkite.com/v2/organizations/my-great-org/pipeline-templates/6a25cc85-9fa2-4a00-b66c-bfe377bc5f78"), + WebURL: String("https://buildkite.com/organizations/my-great-org/pipeline-templates/6a25cc85-9fa2-4a00-b66c-bfe377bc5f78"), + }, + } + + if !reflect.DeepEqual(pipelineTemplates, want) { + t.Errorf("TestPipelineTemplates.List returned %+v, want %+v", pipelineTemplates, want) + } +} + +func TestPipelineTemplatesService_Get(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, + ` + { + "uuid": "90333dc7-b86a-4485-98c3-9419a5dbc52e", + "graphql_id": "UGlwZWxpbmVUZW1wbG5lLS0tOTAzMzNkYzctYjg2YS00NDg1LTk4YzMtOTQxOWE1ZGJjNTJl==", + "name": "Pipeline Upload Template", + "description": "Pipeline template with basic YAML pipeline upload", + "configuration": "steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload\"\n", + "available": true, + "created_at": "2023-08-11T01:22:05.650Z", + "created_by": { + "id": "7da07e25-0383-4aff-a7cf-14d1a9aa098f", + "graphql_id": "VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg==", + "name": "Joe Smith", + "email": "jsmith@example.com", + "avatar_url": "https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4", + "created_at": "2023-02-20T03:00:05.824Z" + }, + "updated_at": "2023-08-11T01:22:05.650Z", + "updated_by": { + "id": "7da07e25-0383-4aff-a7cf-14d1a9aa098f", + "graphql_id": "VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg==", + "name": "Joe Smith", + "email": "jsmith@example.com", + "avatar_url": "https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4", + "created_at": "2023-02-20T03:00:05.824Z" + }, + "url": "https://api.buildkite.com/v2/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e", + "web_url": "https://buildkite.com/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e" + }`) + }) + + pipelineTemplate, _, err := client.PipelineTemplates.Get("my-great-org", "90333dc7-b86a-4485-98c3-9419a5dbc52e") + + if err != nil { + t.Errorf("TestPipelineTemplates.Get returned error: %v", err) + } + + basicTemplateCreatedAt, err := time.Parse(BuildKiteDateFormat, "2023-08-11T01:22:05.650Z") + userCreatedAt, err := time.Parse(BuildKiteDateFormat, "2023-02-20T03:00:05.824Z") + + pipelineTemplateCreator := &PipelineTemplateCreator{ + ID: String("7da07e25-0383-4aff-a7cf-14d1a9aa098f"), + GraphQLID: String("VXNlci0tLTdkYTA3ZTI1LTAzODMtNGFmZi1hN2NmLTE0ZDFhOWFhMDk4Zg=="), + Name: String("Joe Smith"), + Email: String("jsmith@example.com"), + AvatarURL: String("https://www.gravatar.com/avatar/593nf93m405mf744n3kg9456jjph9grt4"), + CreatedAt: NewTimestamp(userCreatedAt), + } + + want := &PipelineTemplate{ + UUID: String("90333dc7-b86a-4485-98c3-9419a5dbc52e"), + GraphQLID: String("UGlwZWxpbmVUZW1wbG5lLS0tOTAzMzNkYzctYjg2YS00NDg1LTk4YzMtOTQxOWE1ZGJjNTJl=="), + Name: String("Pipeline Upload Template"), + Description: String("Pipeline template with basic YAML pipeline upload"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload\"\n"), + Available: Bool(true), + CreatedAt: NewTimestamp(basicTemplateCreatedAt), + CreatedBy: pipelineTemplateCreator, + UpdatedAt: NewTimestamp(basicTemplateCreatedAt), + UpdatedBy: pipelineTemplateCreator, + URL: String("https://api.buildkite.com/v2/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e"), + WebURL: String("https://buildkite.com/organizations/my-great-org/pipeline-templates/90333dc7-b86a-4485-98c3-9419a5dbc52e"), + } + + if !reflect.DeepEqual(pipelineTemplate, want) { + t.Errorf("TestPipelineTemplates.Get returned %+v, want %+v", pipelineTemplate, want) + } +} + +func TestPipelineTemplatesService_Create(t *testing.T) { + setup() + defer teardown() + + input := &PipelineTemplateCreateUpdate{ + Name: String("Production Pipeline uploader"), + Description: String("Production pipeline upload template"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n"), + Available: Bool(true), + } + + mux.HandleFunc("/v2/organizations/my-great-org/pipeline-templates", func(w http.ResponseWriter, r *http.Request) { + v := new(PipelineTemplateCreateUpdate) + json.NewDecoder(r.Body).Decode(&v) + + testMethod(t, r, "POST") + + if !reflect.DeepEqual(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, + ` + { + "uuid": "08ac0872-e3bd-41d2-b0f8-7822bb43ad41", + "graphql_id": "UGlwZWxpbmVUZW1wbG5lLS0tMDhhYzA4NzItZTNiZC00MWQyLWIwZjgtNzgyMmJiNDNhZDQxIA==", + "name" : "Production Pipeline template", + "description": "Production pipeline upload template", + "configuration": "steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n", + "available": true + }`) + }) + + pipelineTemplate, _, err := client.PipelineTemplates.Create("my-great-org", input) + + if err != nil { + t.Errorf("TestPipelineTemplates.Create returned error: %v", err) + } + + want := &PipelineTemplate{ + UUID: String("08ac0872-e3bd-41d2-b0f8-7822bb43ad41"), + GraphQLID: String("UGlwZWxpbmVUZW1wbG5lLS0tMDhhYzA4NzItZTNiZC00MWQyLWIwZjgtNzgyMmJiNDNhZDQxIA=="), + Name: String("Production Pipeline template"), + Description: String("Production pipeline upload template"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n"), + Available: Bool(true), + } + + if !reflect.DeepEqual(pipelineTemplate, want) { + t.Errorf("TestPipelineTemplates.Create returned %+v, want %+v", pipelineTemplate, want) + } +} + +func TestPipelineTemplatesService_Update(t *testing.T) { + setup() + defer teardown() + + input := &PipelineTemplateCreateUpdate{ + Name: String("Production Pipeline uploader"), + Description: String("Production pipeline upload template"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n"), + Available: Bool(true), + } + + mux.HandleFunc("/v2/organizations/my-great-org/pipeline-templates", func(w http.ResponseWriter, r *http.Request) { + v := new(PipelineTemplateCreateUpdate) + json.NewDecoder(r.Body).Decode(&v) + + testMethod(t, r, "POST") + + if !reflect.DeepEqual(v, input) { + t.Errorf("Request body = %+v, want %+v", v, input) + } + + fmt.Fprint(w, + ` + { + "uuid": "b8c2e171-1c7d-47a4-a4d1-a20d691f51d0", + "graphql_id": "UGlwZWxpbmVUZW1wbG5lLS0tYjhjMmUxNzEtMWM3ZC00N2E0LWE0ZDEtYTIwZDY5MWY1MWQw==", + "name" : "Production Pipeline template", + "description": "Production pipeline upload template", + "configuration": "steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n", + "available": true + }`) + }) + + pipelineTemplate, _, err := client.PipelineTemplates.Create("my-great-org", input) + + if err != nil { + t.Errorf("TestPipelineTemplates.Update returned error: %v", err) + } + + // Lets update the description of the pipeline template + pipelineTemplate.Description = String("A pipeline template for uploading a production pipeline YAML (pipeline-production.yml)") + + mux.HandleFunc("/v2/organizations/my-great-org/pipeline-templates/b8c2e171-1c7d-47a4-a4d1-a20d691f51d0", func(w http.ResponseWriter, r *http.Request) { + v := new(PipelineTemplateCreateUpdate) + json.NewDecoder(r.Body).Decode(&v) + + testMethod(t, r, "PATCH") + + fmt.Fprint(w, + ` + { + "uuid": "b8c2e171-1c7d-47a4-a4d1-a20d691f51d0", + "graphql_id": "UGlwZWxpbmVUZW1wbG5lLS0tYjhjMmUxNzEtMWM3ZC00N2E0LWE0ZDEtYTIwZDY5MWY1MWQw==", + "name" : "Production Pipeline template", + "description": "A pipeline template for uploading a production pipeline YAML (pipeline-production.yml)", + "configuration": "steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n", + "available": true + }`) + }) + + pipelineTemplateUpdate := PipelineTemplateCreateUpdate{ + Description: String("A pipeline template for uploading a production pipeline YAML (pipeline-production.yml)"), + } + + _, err = client.PipelineTemplates.Update("my-great-org", "b8c2e171-1c7d-47a4-a4d1-a20d691f51d0", &pipelineTemplateUpdate) + + if err != nil { + t.Errorf("TestPipelineTemplates.Update returned error: %v", err) + } + + want := &PipelineTemplate{ + UUID: String("b8c2e171-1c7d-47a4-a4d1-a20d691f51d0"), + GraphQLID: String("UGlwZWxpbmVUZW1wbG5lLS0tYjhjMmUxNzEtMWM3ZC00N2E0LWE0ZDEtYTIwZDY5MWY1MWQw=="), + Name: String("Production Pipeline template"), + Description: String("A pipeline template for uploading a production pipeline YAML (pipeline-production.yml)"), + Configuration: String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n"), + Available: Bool(true), + } + + if !reflect.DeepEqual(pipelineTemplate, want) { + t.Errorf("TestPipelineTemplates.Update returned %+v, want %+v", pipelineTemplate, want) + } +} + +func TestPipelineTemplatesService_Delete(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/organizations/my-great-org/pipeline-templates/19dbd05a-96d7-430f-bac0-14b791558562", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "DELETE") + }) + + _, err := client.PipelineTemplates.Delete("my-great-org", "19dbd05a-96d7-430f-bac0-14b791558562") + + if err != nil { + t.Errorf("TestPipelineTemplates.Delete returned error: %v", err) + } +} diff --git a/examples/pipeline_templates/create/main.go b/examples/pipeline_templates/create/main.go new file mode 100644 index 00000000..dc0bb79a --- /dev/null +++ b/examples/pipeline_templates/create/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + + "github.com/buildkite/go-buildkite/v3/buildkite" + + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + apiToken = kingpin.Flag("token", "API token").Required().String() + org = kingpin.Flag("org", "Orginization slug").Required().String() + debug = kingpin.Flag("debug", "Enable debugging").Bool() +) + +func main() { + kingpin.Parse() + + config, err := buildkite.NewTokenConfig(*apiToken, *debug) + + if err != nil { + log.Fatalf("client config failed: %s", err) + } + + client := buildkite.NewClient(config.Client()) + + pipelineTemplateCreate := buildkite.PipelineTemplateCreateUpdate{ + Name: buildkite.String("Production Pipeline uploader"), + Description: buildkite.String("Production pipeline upload template"), + Configuration: buildkite.String("steps:\n - label: \":pipeline:\"\n command: \"buildkite-agent pipeline upload .buildkite/pipeline-production.yml\"\n"), + Available: buildkite.Bool(true), + } + + pipelineTemplate, _, err := client.PipelineTemplates.Create(*org, &pipelineTemplateCreate) + + if err != nil { + log.Fatalf("Creating pipeline template failed: %s", err) + } + + data, err := json.MarshalIndent(pipelineTemplate, "", "\t") + + if err != nil { + log.Fatalf("json encode failed: %s", err) + } + + fmt.Fprintf(os.Stdout, "%s", string(data)) +} diff --git a/examples/pipeline_templates/delete/main.go b/examples/pipeline_templates/delete/main.go new file mode 100644 index 00000000..1cb64757 --- /dev/null +++ b/examples/pipeline_templates/delete/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "fmt" + "log" + + "github.com/buildkite/go-buildkite/v3/buildkite" + + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + apiToken = kingpin.Flag("token", "API token").Required().String() + org = kingpin.Flag("org", "Orginization slug").Required().String() + templateUUID = kingpin.Flag("templateUUID", "Cluster UUID").Required().String() + debug = kingpin.Flag("debug", "Enable debugging").Bool() +) + +func main() { + kingpin.Parse() + + config, err := buildkite.NewTokenConfig(*apiToken, *debug) + + if err != nil { + log.Fatalf("client config failed: %s", err) + } + + client := buildkite.NewClient(config.Client()) + + resp, err := client.PipelineTemplates.Delete(*org, *templateUUID) + + if err != nil { + log.Fatalf("Deleting pipeline template %s failed: %s", *templateUUID, err) + } + + fmt.Println(resp.StatusCode) +} diff --git a/examples/pipeline_templates/get/main.go b/examples/pipeline_templates/get/main.go new file mode 100644 index 00000000..3416abea --- /dev/null +++ b/examples/pipeline_templates/get/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + + "github.com/buildkite/go-buildkite/v3/buildkite" + + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + apiToken = kingpin.Flag("token", "API token").Required().String() + org = kingpin.Flag("org", "Orginization slug").Required().String() + templateUUID = kingpin.Flag("templateUUID", "Cluster UUID").Required().String() + debug = kingpin.Flag("debug", "Enable debugging").Bool() +) + +func main() { + kingpin.Parse() + + config, err := buildkite.NewTokenConfig(*apiToken, *debug) + + if err != nil { + log.Fatalf("client config failed: %s", err) + } + + client := buildkite.NewClient(config.Client()) + + pipelineTemplate, _, err := client.PipelineTemplates.Get(*org, *templateUUID) + + if err != nil { + log.Fatalf("Getting pipeline template %s failed: %s", *templateUUID, err) + } + + data, err := json.MarshalIndent(pipelineTemplate, "", "\t") + + if err != nil { + log.Fatalf("json encode failed: %s", err) + } + + fmt.Fprintf(os.Stdout, "%s", string(data)) +} diff --git a/examples/pipeline_templates/list/main.go b/examples/pipeline_templates/list/main.go new file mode 100644 index 00000000..8f0b8b72 --- /dev/null +++ b/examples/pipeline_templates/list/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + + "github.com/buildkite/go-buildkite/v3/buildkite" + + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + apiToken = kingpin.Flag("token", "API token").Required().String() + org = kingpin.Flag("org", "Orginization slug").Required().String() + debug = kingpin.Flag("debug", "Enable debugging").Bool() +) + +func main() { + kingpin.Parse() + + config, err := buildkite.NewTokenConfig(*apiToken, *debug) + + if err != nil { + log.Fatalf("client config failed: %s", err) + } + + client := buildkite.NewClient(config.Client()) + + pipelineTemplates, _, err := client.PipelineTemplates.List(*org, nil) + + if err != nil { + log.Fatalf("listing pipeline templates failed: %s", err) + } + + data, err := json.MarshalIndent(pipelineTemplates, "", "\t") + + if err != nil { + log.Fatalf("json encode failed: %s", err) + } + + fmt.Fprintf(os.Stdout, "%s", string(data)) +} diff --git a/examples/pipeline_templates/update/main.go b/examples/pipeline_templates/update/main.go new file mode 100644 index 00000000..c2e3682a --- /dev/null +++ b/examples/pipeline_templates/update/main.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + "log" + + "github.com/buildkite/go-buildkite/v3/buildkite" + + "gopkg.in/alecthomas/kingpin.v2" +) + +var ( + apiToken = kingpin.Flag("token", "API token").Required().String() + org = kingpin.Flag("org", "Orginization slug").Required().String() + templateUUID = kingpin.Flag("templateUUID", "Cluster UUID").Required().String() + debug = kingpin.Flag("debug", "Enable debugging").Bool() +) + +func main() { + kingpin.Parse() + + config, err := buildkite.NewTokenConfig(*apiToken, *debug) + + if err != nil { + log.Fatalf("client config failed: %s", err) + } + + client := buildkite.NewClient(config.Client()) + + pipelineTemplateUpdate := buildkite.PipelineTemplateCreateUpdate{ + Description: buildkite.String("Production pipeline template uploader"), + } + + resp, err := client.PipelineTemplates.Update(*org, *templateUUID, &pipelineTemplateUpdate) + + if err != nil { + log.Fatalf("Updating cluster %s failed: %s", *templateUUID, err) + } + + fmt.Println(resp.StatusCode) +}