add DeployOptions and PipelineStartOptions

This commit is contained in:
Robert Kaussow 2024-04-27 21:02:33 +02:00
parent 5e23887930
commit 9767201c73
No known key found for this signature in database
GPG key ID: 4E692A2EAECC03C0
6 changed files with 205 additions and 26 deletions

View file

@ -112,9 +112,12 @@ func deploy(c *cli.Context) error {
return fmt.Errorf("please specify the target environment (i.e. production)")
}
params := internal.ParseKeyPair(c.StringSlice("param"))
opt := woodpecker.DeployOptions{
DeployTo: env,
Params: internal.ParseKeyPair(c.StringSlice("param")),
}
deploy, err := client.Deploy(repoID, number, env, params)
deploy, err := client.Deploy(repoID, number, opt)
if err != nil {
return err
}

View file

@ -22,6 +22,7 @@ import (
"github.com/urfave/cli/v2"
"go.woodpecker-ci.org/woodpecker/v2/cli/internal"
"go.woodpecker-ci.org/woodpecker/v2/woodpecker-go/woodpecker"
)
var pipelineStartCmd = &cli.Command{
@ -68,9 +69,11 @@ func pipelineStart(c *cli.Context) (err error) {
}
}
params := internal.ParseKeyPair(c.StringSlice("param"))
opt := woodpecker.PipelineStartOptions{
Params: internal.ParseKeyPair(c.StringSlice("param")),
}
pipeline, err := client.PipelineStart(repoID, number, params)
pipeline, err := client.PipelineStart(repoID, number, opt)
if err != nil {
return err
}

View file

@ -92,7 +92,7 @@ type Client interface {
PipelineCreate(repoID int64, opts *PipelineOptions) (*Pipeline, error)
// PipelineStart re-starts a stopped pipeline.
PipelineStart(repoID, num int64, params map[string]string) (*Pipeline, error)
PipelineStart(repoID, num int64, opt PipelineStartOptions) (*Pipeline, error)
// PipelineStop stops the given pipeline.
PipelineStop(repoID, pipeline int64) error
@ -111,7 +111,7 @@ type Client interface {
// Deploy triggers a deployment for an existing pipeline using the specified
// target environment.
Deploy(repoID, pipeline int64, env string, params map[string]string) (*Pipeline, error)
Deploy(repoID, pipeline int64, opt DeployOptions) (*Pipeline, error)
// LogsPurge purges the pipeline logs for the specified pipeline.
LogsPurge(repoID, pipeline int64) error

View file

@ -34,6 +34,15 @@ type PipelineListOptions struct {
After time.Time
}
type DeployOptions struct {
DeployTo string // override the target deploy value
Params map[string]string // custom parameters to be injected into the step environment. Format: KEY=value
}
type PipelineStartOptions struct {
Params map[string]string // custom parameters to be injected into the step environment. Format: KEY=value
}
// QueryEncode returns the URL query parameters for the PipelineListOptions.
func (opt *PipelineListOptions) QueryEncode() string {
query := opt.getURLQuery()
@ -46,6 +55,22 @@ func (opt *PipelineListOptions) QueryEncode() string {
return query.Encode()
}
// QueryEncode returns the URL query parameters for the DeployOptions.
func (opt *DeployOptions) QueryEncode() string {
query := mapValues(opt.Params)
if opt.DeployTo != "" {
query.Add("deploy_to", opt.DeployTo)
}
query.Add("event", EventDeploy)
return query.Encode()
}
// QueryEncode returns the URL query parameters for the PipelineStartOptions.
func (opt *PipelineStartOptions) QueryEncode() string {
query := mapValues(opt.Params)
return query.Encode()
}
// Repo returns a repository by id.
func (c *client) Repo(repoID int64) (*Repo, error) {
out := new(Repo)
@ -239,10 +264,8 @@ func (c *client) PipelineLast(repoID int64, branch string) (*Pipeline, error) {
// the specified repository.
func (c *client) PipelineList(repoID int64, opt PipelineListOptions) ([]*Pipeline, error) {
var out []*Pipeline
uri, _ := url.Parse(fmt.Sprintf(pathPipelines, c.addr, repoID))
uri.RawQuery = opt.QueryEncode()
err := c.get(uri.String(), &out)
return out, err
}
@ -256,11 +279,11 @@ func (c *client) PipelineCreate(repoID int64, options *PipelineOptions) (*Pipeli
}
// PipelineStart re-starts a stopped pipeline.
func (c *client) PipelineStart(repoID, pipeline int64, params map[string]string) (*Pipeline, error) {
func (c *client) PipelineStart(repoID, pipeline int64, opt PipelineStartOptions) (*Pipeline, error) {
out := new(Pipeline)
val := mapValues(params)
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline)
err := c.post(uri+"?"+val.Encode(), nil, out)
uri, _ := url.Parse(fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline))
uri.RawQuery = opt.QueryEncode()
err := c.post(uri.String(), nil, out)
return out, err
}
@ -303,13 +326,11 @@ func (c *client) LogsPurge(repoID, pipeline int64) error {
// Deploy triggers a deployment for an existing pipeline using the
// specified target environment.
func (c *client) Deploy(repoID, pipeline int64, env string, params map[string]string) (*Pipeline, error) {
func (c *client) Deploy(repoID, pipeline int64, opt DeployOptions) (*Pipeline, error) {
out := new(Pipeline)
val := mapValues(params)
val.Set("event", EventDeploy)
val.Set("deploy_to", env)
uri := fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline)
err := c.post(uri+"?"+val.Encode(), nil, out)
uri, _ := url.Parse(fmt.Sprintf(pathPipeline, c.addr, repoID, pipeline))
uri.RawQuery = opt.QueryEncode()
err := c.post(uri.String(), nil, out)
return out, err
}

View file

@ -13,7 +13,7 @@ import (
func TestPipelineList(t *testing.T) {
tests := []struct {
name string
fixtureHandler http.HandlerFunc
handler http.HandlerFunc
opts PipelineListOptions
wantErr bool
expectedLength int
@ -21,7 +21,7 @@ func TestPipelineList(t *testing.T) {
}{
{
name: "success",
fixtureHandler: func(w http.ResponseWriter, r *http.Request) {
handler: func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, "/api/repos/123/pipelines?after=2023-01-15T00%3A00%3A00Z&before=2023-01-16T00%3A00%3A00Z&page=2&perPage=10", r.URL.RequestURI())
@ -42,7 +42,7 @@ func TestPipelineList(t *testing.T) {
},
{
name: "empty ListOptions",
fixtureHandler: func(w http.ResponseWriter, r *http.Request) {
handler: func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, "/api/repos/123/pipelines", r.URL.RequestURI())
@ -55,8 +55,8 @@ func TestPipelineList(t *testing.T) {
expectedIDs: []int64{1, 2},
},
{
name: "error",
fixtureHandler: func(w http.ResponseWriter, _ *http.Request) {
name: "server error",
handler: func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
},
opts: PipelineListOptions{},
@ -66,7 +66,7 @@ func TestPipelineList(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(tt.fixtureHandler)
ts := httptest.NewServer(tt.handler)
defer ts.Close()
client := NewClient(ts.URL, http.DefaultClient)
@ -86,3 +86,157 @@ func TestPipelineList(t *testing.T) {
})
}
}
func TestClientDeploy(t *testing.T) {
tests := []struct {
name string
handler http.HandlerFunc
repoID int64
pipelineID int64
opts DeployOptions
wantErr bool
expectedPipeline *Pipeline
}{
{
name: "success",
handler: func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPost, r.Method)
assert.Equal(t, "/api/repos/123/pipelines/456?event=deployment", r.URL.RequestURI())
w.WriteHeader(http.StatusOK)
_, err := fmt.Fprint(w, `{"id":789}`)
assert.NoError(t, err)
},
repoID: 123,
pipelineID: 456,
opts: DeployOptions{},
expectedPipeline: &Pipeline{
ID: 789,
},
},
{
name: "error",
handler: func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
},
repoID: 123,
pipelineID: 456,
opts: DeployOptions{},
wantErr: true,
},
{
name: "with options",
handler: func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPost, r.Method)
assert.Equal(t, "/api/repos/123/pipelines/456?deploy_to=production&event=deployment", r.URL.RequestURI())
w.WriteHeader(http.StatusOK)
_, err := fmt.Fprint(w, `{"id":789}`)
assert.NoError(t, err)
},
repoID: 123,
pipelineID: 456,
opts: DeployOptions{
DeployTo: "production",
},
expectedPipeline: &Pipeline{
ID: 789,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(tt.handler)
defer ts.Close()
client := NewClient(ts.URL, http.DefaultClient)
pipeline, err := client.Deploy(tt.repoID, tt.pipelineID, tt.opts)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expectedPipeline, pipeline)
})
}
}
func TestClientPipelineStart(t *testing.T) {
tests := []struct {
name string
handler http.HandlerFunc
repoID int64
pipelineID int64
opts PipelineStartOptions
wantErr bool
expectedPipeline *Pipeline
}{
{
name: "success",
handler: func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPost, r.Method)
assert.Equal(t, "/api/repos/123/pipelines/456", r.URL.RequestURI())
w.WriteHeader(http.StatusOK)
_, err := fmt.Fprint(w, `{"id":789}`)
assert.NoError(t, err)
},
repoID: 123,
pipelineID: 456,
opts: PipelineStartOptions{},
expectedPipeline: &Pipeline{
ID: 789,
},
},
{
name: "error",
handler: func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
},
repoID: 123,
pipelineID: 456,
opts: PipelineStartOptions{},
wantErr: true,
},
{
name: "with options",
handler: func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodPost, r.Method)
assert.Equal(t, "/api/repos/123/pipelines/456?foo=bar", r.URL.RequestURI())
w.WriteHeader(http.StatusOK)
_, err := fmt.Fprint(w, `{"id":789}`)
assert.NoError(t, err)
},
repoID: 123,
pipelineID: 456,
opts: PipelineStartOptions{
Params: map[string]string{"foo": "bar"},
},
expectedPipeline: &Pipeline{
ID: 789,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ts := httptest.NewServer(tt.handler)
defer ts.Close()
client := NewClient(ts.URL, http.DefaultClient)
pipeline, err := client.PipelineStart(tt.repoID, tt.pipelineID, tt.opts)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.expectedPipeline, pipeline)
})
}
}

View file

@ -76,10 +76,8 @@ func (c *client) UserDel(login string) error {
// the user has explicit access in the host system.
func (c *client) RepoList(opt RepoListOptions) ([]*Repo, error) {
var out []*Repo
uri, _ := url.Parse(fmt.Sprintf(pathRepos, c.addr))
uri.RawQuery = opt.QueryEncode()
err := c.get(uri.String(), &out)
return out, err
}