Skip to content

Commit

Permalink
Merge pull request #145 from buildkite/SUP-1321-UpdatePipeline
Browse files Browse the repository at this point in the history
SUP-1321: Pipeline updates utilising dedicated PipelineUpdate struct
  • Loading branch information
james2791 authored Aug 11, 2023
2 parents 521ca40 + 6c9b48e commit 425f8af
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 55 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Unreleased
* Support build.failing events [#141](https://github.com/buildkite/go-buildkite/pull/141) ([mcncl](https://github.com/mcncl))
* SUP-1314: Test Analytics Integration [#142](https://github.com/buildkite/go-buildkite/pull/142) ([james2791](https://github.com/james2791))
* SUP-1321: Pipeline updates with PATCH friendly struct input [#143](https://github.com/buildkite/go-buildkite/pull/143) ([james2791](https://github.com/james2791))
* SUP-1321: Pipeline updates utilising dedicated PipelineUpdate struct [#145](https://github.com/buildkite/go-buildkite/pull/145) ([james2791](https://github.com/james2791))

### Notice
As part of this release, the properties that can be set when updating a pipeline using the [PipelinesService](https://github.com/buildkite/go-buildkite/blob/main/buildkite/pipelines.go) have changed to reflect the permitted request body properties in the pipeline update [REST API endpoint](https://buildkite.com/docs/apis/rest-api/pipelines#update-a-pipeline).
Expand Down
6 changes: 6 additions & 0 deletions buildkite/buildkite.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,9 @@ func String(v string) *string {
*p = v
return p
}

func Bool(v bool) *bool {
p := new(bool)
*p = v
return p
}
74 changes: 52 additions & 22 deletions buildkite/pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package buildkite

import (
"encoding/json"
"errors"
"fmt"
)

Expand Down Expand Up @@ -39,20 +40,20 @@ type CreatePipeline struct {

type UpdatePipeline struct {
// Either configuration needs to be specified as a yaml string or steps (based on what the pipeline uses)
Configuration string `json:"configuration,omitempty" yaml:"configuration,omitempty"`
Steps []Step `json:"steps,omitempty" yaml:"steps,omitempty"`
Configuration string `json:"configuration,omitempty" yaml:"configuration,omitempty"`
Steps []*Step `json:"steps,omitempty" yaml:"steps,omitempty"`

Name string `json:"name,omitempty" yaml:"name,omitempty"`
Repository string `json:"repository,omitempty" yaml:"repository,omitempty"`
DefaultBranch string `json:"default_branch,omitempty" yaml:"default_branch,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
Name *string `json:"name,omitempty" yaml:"name,omitempty"`
Repository *string `json:"repository,omitempty" yaml:"repository,omitempty"`
DefaultBranch *string `json:"default_branch,omitempty" yaml:"default_branch,omitempty"`
Description *string `json:"description,omitempty" yaml:"description,omitempty"`
ProviderSettings ProviderSettings `json:"provider_settings,omitempty" yaml:"provider_settings,omitempty"`
BranchConfiguration string `json:"branch_configuration,omitempty" yaml:"branch_configuration,omitempty"`
SkipQueuedBranchBuilds bool `json:"skip_queued_branch_builds,omitempty" yaml:"skip_queued_branch_builds,omitempty"`
SkipQueuedBranchBuildsFilter string `json:"skip_queued_branch_builds_filter,omitempty" yaml:"skip_queued_branch_builds_filter,omitempty"`
CancelRunningBranchBuilds bool `json:"cancel_running_branch_builds,omitempty" yaml:"cancel_running_branch_builds,omitempty"`
CancelRunningBranchBuildsFilter string `json:"cancel_running_branch_builds_filter,omitempty" yaml:"cancel_running_branch_builds_filter,omitempty"`
ClusterID string `json:"cluster_id,omitempty" yaml:"cluster_id,omitempty"`
BranchConfiguration *string `json:"branch_configuration,omitempty" yaml:"branch_configuration,omitempty"`
SkipQueuedBranchBuilds *bool `json:"skip_queued_branch_builds,omitempty" yaml:"skip_queued_branch_builds,omitempty"`
SkipQueuedBranchBuildsFilter *string `json:"skip_queued_branch_builds_filter,omitempty" yaml:"skip_queued_branch_builds_filter,omitempty"`
CancelRunningBranchBuilds *bool `json:"cancel_running_branch_builds,omitempty" yaml:"cancel_running_branch_builds,omitempty"`
CancelRunningBranchBuildsFilter *string `json:"cancel_running_branch_builds_filter,omitempty" yaml:"cancel_running_branch_builds_filter,omitempty"`
ClusterID *string `json:"cluster_id,omitempty" yaml:"cluster_id,omitempty"`
Visibility *string `json:"visibility,omitempty" yaml:"visibility,omitempty"`
}

Expand Down Expand Up @@ -232,25 +233,27 @@ func (ps *PipelinesService) Delete(org string, slug string) (*Response, error) {
// Update - Updates a pipeline.
//
// buildkite API docs: https://buildkite.com/docs/rest-api/pipelines#update-a-pipeline
func (ps *PipelinesService) Update(org, slug string, p *UpdatePipeline) (*Pipeline, *Response, error) {
func (ps *PipelinesService) Update(org string, p *Pipeline) (*Response, error) {
if p == nil {
return nil, errors.New("Pipeline must not be nil")
}

u := fmt.Sprintf("v2/organizations/%s/pipelines/%s", org, slug)
u := fmt.Sprintf("v2/organizations/%s/pipelines/%s", org, *p.Slug)

pu := generateUpdatePipelineInstance(*p)

req, err := ps.client.NewRequest("PATCH", u, p)
req, err := ps.client.NewRequest("PATCH", u, pu)

if err != nil {
return nil, nil, err
return nil, err
}

pipeline := new(Pipeline)

resp, err := ps.client.Do(req, pipeline)

resp, err := ps.client.Do(req, p)
if err != nil {
return nil, resp, err
return resp, err
}

return pipeline, resp, err
return resp, err
}

// AddWebhook - Adds webhook in github for pipeline.
Expand Down Expand Up @@ -297,3 +300,30 @@ func (ps *PipelinesService) Unarchive(org string, slug string) (*Response, error

return ps.client.Do(req, nil)
}

func generateUpdatePipelineInstance(p Pipeline) UpdatePipeline {

// Create a UpdatePipeline struct to use for updating
updatePipeline := UpdatePipeline{
Name: p.Name,
Repository: p.Repository,
DefaultBranch: p.DefaultBranch,
Description: p.Description,
BranchConfiguration: p.BranchConfiguration,
SkipQueuedBranchBuilds: p.SkipQueuedBranchBuilds,
SkipQueuedBranchBuildsFilter: p.SkipQueuedBranchBuildsFilter,
CancelRunningBranchBuilds: p.CancelRunningBranchBuilds,
CancelRunningBranchBuildsFilter: p.CancelRunningBranchBuildsFilter,
ClusterID: p.ClusterID,
Visibility: p.Visibility,
Configuration: p.Configuration,
Steps: p.Steps,
}

// If Pipeline Provider has been defined, set ProviderSettings
if p.Provider != nil {
updatePipeline.ProviderSettings = p.Provider.Settings
}

return updatePipeline
}
44 changes: 25 additions & 19 deletions buildkite/pipelines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ func TestPipelinesService_Update(t *testing.T) {
},
},
},
DefaultBranch: *String("main"),
}

mux.HandleFunc("/v2/organizations/my-great-org/pipelines", func(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -263,44 +262,50 @@ func TestPipelinesService_Update(t *testing.T) {
}
}
],
"default_branch":"main"
"slug": "my-great-repo"
}`)
})

pipeline, _, err := client.Pipelines.Create("my-great-org", input)

if err != nil {
t.Errorf("Pipelines.Create returned error: %v", err)
}

// Update pipeline
update := &UpdatePipeline{
DefaultBranch: *String("develop"),
}
pipeline.Name = String("derp")

mux.HandleFunc("/v2/organizations/my-great-org/pipelines/my-great-repo", func(w http.ResponseWriter, r *http.Request) {
v := new(CreatePipeline)
json.NewDecoder(r.Body).Decode(&v)

testMethod(t, r, "PATCH")

fmt.Fprint(w,
`
{
"default_branch": "develop"
}`)
fmt.Fprint(w, `{
"name":"derp",
"repository":"my-great-repo",
"steps": [
{
"type": "script",
"name": "Build :package:",
"command": "script/release.sh",
"plugins": {
"my-org/docker#v3.3.0": {
"image": "node",
"workdir": "/app"
}
}
}
],
"slug": "my-great-repo",
"visibility": "public"
}`)
})

updatedPipeline, _, err := client.Pipelines.Update("my-great-org", "my-great-repo", update)

// Update pipeline with the patched default branch
pipeline.DefaultBranch = updatedPipeline.DefaultBranch

_, err = client.Pipelines.Update("my-great-org", pipeline)
if err != nil {
t.Errorf("Pipelines.Update returned error: %v", err)
}

want := &Pipeline{Name: String("my-great-pipeline"),
want := &Pipeline{Name: String("derp"),
Repository: String("my-great-repo"),
Steps: []*Step{
{
Expand All @@ -315,7 +320,8 @@ func TestPipelinesService_Update(t *testing.T) {
},
},
},
DefaultBranch: String("develop"),
Slug: String("my-great-repo"),
Visibility: String("public"),
}

if !reflect.DeepEqual(pipeline, want) {
Expand Down
24 changes: 11 additions & 13 deletions examples/pipelines/update/main.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package main

import (
"encoding/json"
"fmt"
"log"
"os"

"github.com/buildkite/go-buildkite/v3/buildkite"

Expand All @@ -14,7 +12,6 @@ import (
var (
apiToken = kingpin.Flag("token", "API token").Required().String()
org = kingpin.Flag("org", "Orginization slug").Required().String()
slug = kingpin.Flag("slug", "Pipeline slug").Required().String()
debug = kingpin.Flag("debug", "Enable debugging").Bool()
)

Expand All @@ -29,21 +26,22 @@ func main() {

client := buildkite.NewClient(config.Client())

updatePipeline := buildkite.UpdatePipeline{
Description: *buildkite.String("This ia a deployment pipeline"),
pipeline := buildkite.Pipeline{
Slug: buildkite.String("my-great-repo"),
Description: buildkite.String("This ia a great pipeline!"),
Provider: &buildkite.Provider{
Settings: &buildkite.GitHubSettings{
TriggerMode: buildkite.String("fork"),
BuildPullRequests: buildkite.Bool(false),
},
},
}

pipeline, _, err := client.Pipelines.Update(*org, *slug, &updatePipeline)
resp, err := client.Pipelines.Update(*org, &pipeline)

if err != nil {
log.Fatalf("Updating pipeline failed: %s", err)
}

data, err := json.MarshalIndent(pipeline, "", "\t")

if err != nil {
log.Fatalf("json encode failed: %s", err)
}

fmt.Fprintf(os.Stdout, "%s", string(data))
fmt.Println(resp.StatusCode)
}

0 comments on commit 425f8af

Please sign in to comment.