Loading pipelines.go +74 Changes for pipelines.go: 74 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import ( ) var ( routePipelines = route("pipelines") routeProjectsIDPipeline = route("projects/%s/pipeline") routeProjectsIDPipelines = route("projects/%s/pipelines") routeProjectsIDPipelinesID = route("projects/%s/pipelines/%d") Loading Loading @@ -59,6 +60,13 @@ const ( type ( PipelinesServiceInterface interface { // ListUserPipelines gets the pipelines across all projects that were // triggered by the authenticated user. Only keyset pagination is // supported. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines ListUserPipelines(opt *ListUserPipelinesOptions, options ...RequestOptionFunc) ([]*UserPipeline, *Response, error) ListProjectPipelines(pid any, opt *ListProjectPipelinesOptions, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) GetPipeline(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) GetPipelineVariables(pid any, pipeline int64, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) Loading Loading @@ -257,6 +265,72 @@ func (p PipelineInfo) String() string { return Stringify(p) } // UserPipeline represents a pipeline triggered by the authenticated user, as // returned by ListUserPipelines. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines type UserPipeline struct { ID int64 `json:"id"` IID int64 `json:"iid"` ProjectID int64 `json:"project_id"` Status string `json:"status"` Source PipelineSource `json:"source"` Ref string `json:"ref"` SHA string `json:"sha"` Name string `json:"name"` WebURL string `json:"web_url"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` StartedAt *time.Time `json:"started_at"` FinishedAt *time.Time `json:"finished_at"` Duration int64 `json:"duration"` QueuedDuration int64 `json:"queued_duration"` DetailedStatus *DetailedStatus `json:"detailed_status"` MergeRequest *UserPipelineMergeRequest `json:"merge_request"` Project *BasicProject `json:"project"` } func (p UserPipeline) String() string { return Stringify(p) } // UserPipelineMergeRequest represents the merge request of a merge request // pipeline in a UserPipeline. It is only set if the merge request is visible // to the user. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines type UserPipelineMergeRequest struct { IID int64 `json:"iid"` Title string `json:"title"` WebURL string `json:"web_url"` } // ListUserPipelinesOptions represents the available ListUserPipelines() // options. Only keyset pagination is supported, so it does not embed // ListOptions. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines type ListUserPipelinesOptions struct { CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` Cursor *string `url:"cursor,omitempty" json:"cursor,omitempty"` OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` Source *PipelineSource `url:"source,omitempty" json:"source,omitempty"` PerPage *int64 `url:"per_page,omitempty" json:"per_page,omitempty"` } func (s *PipelinesService) ListUserPipelines(opt *ListUserPipelinesOptions, options ...RequestOptionFunc) ([]*UserPipeline, *Response, error) { return do[[]*UserPipeline](s.client, withPath(routePipelines), withAPIOpts(opt), withRequestOpts(options...), ) } // ListProjectPipelinesOptions represents the available ListProjectPipelines() // options. // Loading pipelines_test.go +107 Changes for pipelines_test.go: 107 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -45,6 +45,113 @@ func TestListProjectPipelines(t *testing.T) { assert.Equal(t, want, pipelines) } func TestListUserPipelines(t *testing.T) { t.Parallel() mux, client := setup(t) // GIVEN a server that lists the pipelines of the authenticated user mux.HandleFunc("/api/v4/pipelines", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) testParam(t, r, "source", "merge_request_event") testParam(t, r, "created_after", "2016-08-11T00:00:00Z") testParam(t, r, "created_before", "2016-08-12T00:00:00Z") testParam(t, r, "cursor", "eyJpZCI6IjE0In0") testParam(t, r, "order_by", "created_at") testParam(t, r, "sort", "desc") testParam(t, r, "per_page", "50") w.Header().Set("Link", `<https://gitlab.example.com/api/v4/pipelines?cursor=next>; rel="next"`) mustWriteJSONResponse(t, w, []map[string]any{{ "id": 47, "iid": 12, "project_id": 1, "status": "running", "source": "merge_request_event", "ref": "refs/merge-requests/14/merge", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "name": "Build pipeline", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": "2016-08-11T11:28:54.085Z", "finished_at": nil, "duration": nil, "queued_duration": 20, "detailed_status": map[string]any{"icon": "status_running", "text": "Running", "label": "running", "group": "running", "has_details": true}, "merge_request": map[string]any{"iid": 14, "title": "Add rate limiting", "web_url": "https://example.com/foo/bar/-/merge_requests/14"}, "project": map[string]any{"id": 1, "name": "Bar", "path_with_namespace": "foo/bar"}, }}) }) // WHEN listing the pipelines with every option set opt := &ListUserPipelinesOptions{ CreatedAfter: mustParseTime("2016-08-11T00:00:00Z"), CreatedBefore: mustParseTime("2016-08-12T00:00:00Z"), Cursor: new("eyJpZCI6IjE0In0"), OrderBy: new("created_at"), Sort: new("desc"), Source: new(PipelineSourceMergeRequestEvent), PerPage: new(int64(50)), } pipelines, resp, err := client.Pipelines.ListUserPipelines(opt) // THEN the pipelines and the next page link are returned require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, "https://gitlab.example.com/api/v4/pipelines?cursor=next", resp.NextLink) want := []*UserPipeline{{ ID: 47, IID: 12, ProjectID: 1, Status: "running", Source: PipelineSourceMergeRequestEvent, Ref: "refs/merge-requests/14/merge", SHA: "a91957a858320c0e17f3a0eca7cfacbff50ea29a", Name: "Build pipeline", WebURL: "https://example.com/foo/bar/pipelines/47", CreatedAt: mustParseTime("2016-08-11T11:28:34.085Z"), UpdatedAt: mustParseTime("2016-08-11T11:32:35.169Z"), StartedAt: mustParseTime("2016-08-11T11:28:54.085Z"), QueuedDuration: 20, DetailedStatus: &DetailedStatus{Icon: "status_running", Text: "Running", Label: "running", Group: "running", HasDetails: true}, MergeRequest: &UserPipelineMergeRequest{IID: 14, Title: "Add rate limiting", WebURL: "https://example.com/foo/bar/-/merge_requests/14"}, Project: &BasicProject{ID: 1, Name: "Bar", PathWithNamespace: "foo/bar"}, }} assert.Equal(t, want, pipelines) } func TestListUserPipelines_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) // GIVEN a request option that fails // WHEN listing the pipelines pipelines, resp, err := client.Pipelines.ListUserPipelines(nil, errorOption) // THEN the error is returned require.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, pipelines) } func TestListUserPipelines_Unauthorized(t *testing.T) { t.Parallel() mux, client := setup(t) // GIVEN a server that rejects the request mux.HandleFunc("/api/v4/pipelines", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) w.WriteHeader(http.StatusUnauthorized) }) // WHEN listing the pipelines without options pipelines, resp, err := client.Pipelines.ListUserPipelines(nil) // THEN a 401 error is returned require.Error(t, err) assert.Nil(t, pipelines) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) } func TestGetPipeline(t *testing.T) { t.Parallel() mux, client := setup(t) Loading testing/pipelines_mock.go +45 Changes for testing/pipelines_mock.go: 45 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -443,6 +443,51 @@ func (c *MockPipelinesServiceInterfaceListProjectPipelinesCall) DoAndReturn(f fu return c } // ListUserPipelines mocks base method. func (m *MockPipelinesServiceInterface) ListUserPipelines(opt *gitlab.ListUserPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.UserPipeline, *gitlab.Response, error) { m.ctrl.T.Helper() varargs := []any{opt} for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "ListUserPipelines", varargs...) ret0, _ := ret[0].([]*gitlab.UserPipeline) ret1, _ := ret[1].(*gitlab.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ListUserPipelines indicates an expected call of ListUserPipelines. func (mr *MockPipelinesServiceInterfaceMockRecorder) ListUserPipelines(opt any, options ...any) *MockPipelinesServiceInterfaceListUserPipelinesCall { mr.mock.ctrl.T.Helper() varargs := append([]any{opt}, options...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListUserPipelines", reflect.TypeOf((*MockPipelinesServiceInterface)(nil).ListUserPipelines), varargs...) return &MockPipelinesServiceInterfaceListUserPipelinesCall{Call: call} } // MockPipelinesServiceInterfaceListUserPipelinesCall wrap *gomock.Call type MockPipelinesServiceInterfaceListUserPipelinesCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return func (c *MockPipelinesServiceInterfaceListUserPipelinesCall) Return(arg0 []*gitlab.UserPipeline, arg1 *gitlab.Response, arg2 error) *MockPipelinesServiceInterfaceListUserPipelinesCall { c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do func (c *MockPipelinesServiceInterfaceListUserPipelinesCall) Do(f func(*gitlab.ListUserPipelinesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.UserPipeline, *gitlab.Response, error)) *MockPipelinesServiceInterfaceListUserPipelinesCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn func (c *MockPipelinesServiceInterfaceListUserPipelinesCall) DoAndReturn(f func(*gitlab.ListUserPipelinesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.UserPipeline, *gitlab.Response, error)) *MockPipelinesServiceInterfaceListUserPipelinesCall { c.Call = c.Call.DoAndReturn(f) return c } // RetryPipelineBuild mocks base method. func (m *MockPipelinesServiceInterface) RetryPipelineBuild(pid any, pipeline int64, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) { m.ctrl.T.Helper() Loading Loading
pipelines.go +74 Changes for pipelines.go: 74 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import ( ) var ( routePipelines = route("pipelines") routeProjectsIDPipeline = route("projects/%s/pipeline") routeProjectsIDPipelines = route("projects/%s/pipelines") routeProjectsIDPipelinesID = route("projects/%s/pipelines/%d") Loading Loading @@ -59,6 +60,13 @@ const ( type ( PipelinesServiceInterface interface { // ListUserPipelines gets the pipelines across all projects that were // triggered by the authenticated user. Only keyset pagination is // supported. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines ListUserPipelines(opt *ListUserPipelinesOptions, options ...RequestOptionFunc) ([]*UserPipeline, *Response, error) ListProjectPipelines(pid any, opt *ListProjectPipelinesOptions, options ...RequestOptionFunc) ([]*PipelineInfo, *Response, error) GetPipeline(pid any, pipeline int64, options ...RequestOptionFunc) (*Pipeline, *Response, error) GetPipelineVariables(pid any, pipeline int64, options ...RequestOptionFunc) ([]*PipelineVariable, *Response, error) Loading Loading @@ -257,6 +265,72 @@ func (p PipelineInfo) String() string { return Stringify(p) } // UserPipeline represents a pipeline triggered by the authenticated user, as // returned by ListUserPipelines. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines type UserPipeline struct { ID int64 `json:"id"` IID int64 `json:"iid"` ProjectID int64 `json:"project_id"` Status string `json:"status"` Source PipelineSource `json:"source"` Ref string `json:"ref"` SHA string `json:"sha"` Name string `json:"name"` WebURL string `json:"web_url"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` StartedAt *time.Time `json:"started_at"` FinishedAt *time.Time `json:"finished_at"` Duration int64 `json:"duration"` QueuedDuration int64 `json:"queued_duration"` DetailedStatus *DetailedStatus `json:"detailed_status"` MergeRequest *UserPipelineMergeRequest `json:"merge_request"` Project *BasicProject `json:"project"` } func (p UserPipeline) String() string { return Stringify(p) } // UserPipelineMergeRequest represents the merge request of a merge request // pipeline in a UserPipeline. It is only set if the merge request is visible // to the user. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines type UserPipelineMergeRequest struct { IID int64 `json:"iid"` Title string `json:"title"` WebURL string `json:"web_url"` } // ListUserPipelinesOptions represents the available ListUserPipelines() // options. Only keyset pagination is supported, so it does not embed // ListOptions. // // GitLab API docs: // https://docs.gitlab.com/api/pipelines/#list-pipelines type ListUserPipelinesOptions struct { CreatedAfter *time.Time `url:"created_after,omitempty" json:"created_after,omitempty"` CreatedBefore *time.Time `url:"created_before,omitempty" json:"created_before,omitempty"` Cursor *string `url:"cursor,omitempty" json:"cursor,omitempty"` OrderBy *string `url:"order_by,omitempty" json:"order_by,omitempty"` Sort *string `url:"sort,omitempty" json:"sort,omitempty"` Source *PipelineSource `url:"source,omitempty" json:"source,omitempty"` PerPage *int64 `url:"per_page,omitempty" json:"per_page,omitempty"` } func (s *PipelinesService) ListUserPipelines(opt *ListUserPipelinesOptions, options ...RequestOptionFunc) ([]*UserPipeline, *Response, error) { return do[[]*UserPipeline](s.client, withPath(routePipelines), withAPIOpts(opt), withRequestOpts(options...), ) } // ListProjectPipelinesOptions represents the available ListProjectPipelines() // options. // Loading
pipelines_test.go +107 Changes for pipelines_test.go: 107 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -45,6 +45,113 @@ func TestListProjectPipelines(t *testing.T) { assert.Equal(t, want, pipelines) } func TestListUserPipelines(t *testing.T) { t.Parallel() mux, client := setup(t) // GIVEN a server that lists the pipelines of the authenticated user mux.HandleFunc("/api/v4/pipelines", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) testParam(t, r, "source", "merge_request_event") testParam(t, r, "created_after", "2016-08-11T00:00:00Z") testParam(t, r, "created_before", "2016-08-12T00:00:00Z") testParam(t, r, "cursor", "eyJpZCI6IjE0In0") testParam(t, r, "order_by", "created_at") testParam(t, r, "sort", "desc") testParam(t, r, "per_page", "50") w.Header().Set("Link", `<https://gitlab.example.com/api/v4/pipelines?cursor=next>; rel="next"`) mustWriteJSONResponse(t, w, []map[string]any{{ "id": 47, "iid": 12, "project_id": 1, "status": "running", "source": "merge_request_event", "ref": "refs/merge-requests/14/merge", "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a", "name": "Build pipeline", "web_url": "https://example.com/foo/bar/pipelines/47", "created_at": "2016-08-11T11:28:34.085Z", "updated_at": "2016-08-11T11:32:35.169Z", "started_at": "2016-08-11T11:28:54.085Z", "finished_at": nil, "duration": nil, "queued_duration": 20, "detailed_status": map[string]any{"icon": "status_running", "text": "Running", "label": "running", "group": "running", "has_details": true}, "merge_request": map[string]any{"iid": 14, "title": "Add rate limiting", "web_url": "https://example.com/foo/bar/-/merge_requests/14"}, "project": map[string]any{"id": 1, "name": "Bar", "path_with_namespace": "foo/bar"}, }}) }) // WHEN listing the pipelines with every option set opt := &ListUserPipelinesOptions{ CreatedAfter: mustParseTime("2016-08-11T00:00:00Z"), CreatedBefore: mustParseTime("2016-08-12T00:00:00Z"), Cursor: new("eyJpZCI6IjE0In0"), OrderBy: new("created_at"), Sort: new("desc"), Source: new(PipelineSourceMergeRequestEvent), PerPage: new(int64(50)), } pipelines, resp, err := client.Pipelines.ListUserPipelines(opt) // THEN the pipelines and the next page link are returned require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, "https://gitlab.example.com/api/v4/pipelines?cursor=next", resp.NextLink) want := []*UserPipeline{{ ID: 47, IID: 12, ProjectID: 1, Status: "running", Source: PipelineSourceMergeRequestEvent, Ref: "refs/merge-requests/14/merge", SHA: "a91957a858320c0e17f3a0eca7cfacbff50ea29a", Name: "Build pipeline", WebURL: "https://example.com/foo/bar/pipelines/47", CreatedAt: mustParseTime("2016-08-11T11:28:34.085Z"), UpdatedAt: mustParseTime("2016-08-11T11:32:35.169Z"), StartedAt: mustParseTime("2016-08-11T11:28:54.085Z"), QueuedDuration: 20, DetailedStatus: &DetailedStatus{Icon: "status_running", Text: "Running", Label: "running", Group: "running", HasDetails: true}, MergeRequest: &UserPipelineMergeRequest{IID: 14, Title: "Add rate limiting", WebURL: "https://example.com/foo/bar/-/merge_requests/14"}, Project: &BasicProject{ID: 1, Name: "Bar", PathWithNamespace: "foo/bar"}, }} assert.Equal(t, want, pipelines) } func TestListUserPipelines_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) // GIVEN a request option that fails // WHEN listing the pipelines pipelines, resp, err := client.Pipelines.ListUserPipelines(nil, errorOption) // THEN the error is returned require.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, pipelines) } func TestListUserPipelines_Unauthorized(t *testing.T) { t.Parallel() mux, client := setup(t) // GIVEN a server that rejects the request mux.HandleFunc("/api/v4/pipelines", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) w.WriteHeader(http.StatusUnauthorized) }) // WHEN listing the pipelines without options pipelines, resp, err := client.Pipelines.ListUserPipelines(nil) // THEN a 401 error is returned require.Error(t, err) assert.Nil(t, pipelines) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) } func TestGetPipeline(t *testing.T) { t.Parallel() mux, client := setup(t) Loading
testing/pipelines_mock.go +45 Changes for testing/pipelines_mock.go: 45 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -443,6 +443,51 @@ func (c *MockPipelinesServiceInterfaceListProjectPipelinesCall) DoAndReturn(f fu return c } // ListUserPipelines mocks base method. func (m *MockPipelinesServiceInterface) ListUserPipelines(opt *gitlab.ListUserPipelinesOptions, options ...gitlab.RequestOptionFunc) ([]*gitlab.UserPipeline, *gitlab.Response, error) { m.ctrl.T.Helper() varargs := []any{opt} for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "ListUserPipelines", varargs...) ret0, _ := ret[0].([]*gitlab.UserPipeline) ret1, _ := ret[1].(*gitlab.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ListUserPipelines indicates an expected call of ListUserPipelines. func (mr *MockPipelinesServiceInterfaceMockRecorder) ListUserPipelines(opt any, options ...any) *MockPipelinesServiceInterfaceListUserPipelinesCall { mr.mock.ctrl.T.Helper() varargs := append([]any{opt}, options...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListUserPipelines", reflect.TypeOf((*MockPipelinesServiceInterface)(nil).ListUserPipelines), varargs...) return &MockPipelinesServiceInterfaceListUserPipelinesCall{Call: call} } // MockPipelinesServiceInterfaceListUserPipelinesCall wrap *gomock.Call type MockPipelinesServiceInterfaceListUserPipelinesCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return func (c *MockPipelinesServiceInterfaceListUserPipelinesCall) Return(arg0 []*gitlab.UserPipeline, arg1 *gitlab.Response, arg2 error) *MockPipelinesServiceInterfaceListUserPipelinesCall { c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do func (c *MockPipelinesServiceInterfaceListUserPipelinesCall) Do(f func(*gitlab.ListUserPipelinesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.UserPipeline, *gitlab.Response, error)) *MockPipelinesServiceInterfaceListUserPipelinesCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn func (c *MockPipelinesServiceInterfaceListUserPipelinesCall) DoAndReturn(f func(*gitlab.ListUserPipelinesOptions, ...gitlab.RequestOptionFunc) ([]*gitlab.UserPipeline, *gitlab.Response, error)) *MockPipelinesServiceInterfaceListUserPipelinesCall { c.Call = c.Call.DoAndReturn(f) return c } // RetryPipelineBuild mocks base method. func (m *MockPipelinesServiceInterface) RetryPipelineBuild(pid any, pipeline int64, options ...gitlab.RequestOptionFunc) (*gitlab.Pipeline, *gitlab.Response, error) { m.ctrl.T.Helper() Loading