diff --git a/event_webhook_types.go b/event_webhook_types.go index e59621314..0cc2f3ec5 100644 --- a/event_webhook_types.go +++ b/event_webhook_types.go @@ -720,18 +720,20 @@ type PipelineEvent struct { } `json:"author"` } `json:"commit"` Builds []struct { - ID int `json:"id"` - Stage string `json:"stage"` - Name string `json:"name"` - Status string `json:"status"` - CreatedAt string `json:"created_at"` - StartedAt string `json:"started_at"` - FinishedAt string `json:"finished_at"` - When string `json:"when"` - Manual bool `json:"manual"` - AllowFailure bool `json:"allow_failure"` - User *EventUser `json:"user"` - Runner struct { + ID int `json:"id"` + Stage string `json:"stage"` + Name string `json:"name"` + Status string `json:"status"` + CreatedAt string `json:"created_at"` + StartedAt string `json:"started_at"` + FinishedAt string `json:"finished_at"` + Duration float64 `json:"duration"` + QueuedDuration float64 `json:"queued_duration"` + When string `json:"when"` + Manual bool `json:"manual"` + AllowFailure bool `json:"allow_failure"` + User *EventUser `json:"user"` + Runner struct { ID int `json:"id"` Description string `json:"description"` Active bool `json:"active"` diff --git a/event_webhook_types_test.go b/event_webhook_types_test.go index e01ff40f6..387f97bac 100644 --- a/event_webhook_types_test.go +++ b/event_webhook_types_test.go @@ -440,6 +440,14 @@ func TestPipelineEventUnmarshal(t *testing.T) { if event.Builds[0].Environment.Name != "production" { t.Errorf("Builds.0.Environment.Name is %v, want %v", event.Builds[0].Environment.Name, "production") } + + if event.Builds[0].Duration != 17.1 { + t.Errorf("Builds[0].Duration is %v, want %v", event.Builds[0].Duration, 17.1) + } + + if event.Builds[0].QueuedDuration != 3.5 { + t.Errorf("Builds[0].QueuedDuration is %v, want %v", event.Builds[0].QueuedDuration, 3.5) + } } func TestPushEventUnmarshal(t *testing.T) { diff --git a/groups.go b/groups.go index 5280493f5..1f5d373aa 100644 --- a/groups.go +++ b/groups.go @@ -84,6 +84,7 @@ type Group struct { PreventForkingOutsideGroup bool `json:"prevent_forking_outside_group"` MarkedForDeletionOn *ISOTime `json:"marked_for_deletion_on"` CreatedAt *time.Time `json:"created_at"` + IPRestrictionRanges string `json:"ip_restriction_ranges"` } // GroupAvatar represents a GitLab group avatar. @@ -351,6 +352,7 @@ type CreateGroupOptions struct { ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` SharedRunnersMinutesLimit *int `url:"shared_runners_minutes_limit,omitempty" json:"shared_runners_minutes_limit,omitempty"` ExtraSharedRunnersMinutesLimit *int `url:"extra_shared_runners_minutes_limit,omitempty" json:"extra_shared_runners_minutes_limit,omitempty"` + IPRestrictionRanges *string `url:"ip_restriction_ranges,omitempty" json:"ip_restriction_ranges,omitempty"` } // CreateGroup creates a new project group. Available only for users who can @@ -478,6 +480,7 @@ type UpdateGroupOptions struct { PreventForkingOutsideGroup *bool `url:"prevent_forking_outside_group,omitempty" json:"prevent_forking_outside_group,omitempty"` SharedRunnersSetting *SharedRunnersSettingValue `url:"shared_runners_setting,omitempty" json:"shared_runners_setting,omitempty"` PreventSharingGroupsOutsideHierarchy *bool `url:"prevent_sharing_groups_outside_hierarchy,omitempty" json:"prevent_sharing_groups_outside_hierarchy,omitempty"` + IPRestrictionRanges *string `url:"ip_restriction_ranges,omitempty" json:"ip_restriction_ranges,omitempty"` } // UpdateGroup updates an existing group; only available to group owners and diff --git a/groups_test.go b/groups_test.go index 0ab7b6b22..5b1a4b281 100644 --- a/groups_test.go +++ b/groups_test.go @@ -522,3 +522,53 @@ func TestUnshareGroupFromGroup(t *testing.T) { t.Errorf("Groups.UnshareGroupFromGroup returned status code %d", r.StatusCode) } } + +func TestCreateGroupWithIPRestrictionRanges(t *testing.T) { + mux, server, client := setup(t) + defer teardown(server) + + mux.HandleFunc("/api/v4/groups", + func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + fmt.Fprint(w, `{"id": 1, "name": "g", "path": "g", "ip_restriction_ranges" : "192.168.0.0/24"}`) + }) + + opt := &CreateGroupOptions{ + Name: String("g"), + Path: String("g"), + IPRestrictionRanges: String("192.168.0.0/24"), + } + + group, _, err := client.Groups.CreateGroup(opt, nil) + if err != nil { + t.Errorf("Groups.CreateGroup returned error: %v", err) + } + + want := &Group{ID: 1, Name: "g", Path: "g", IPRestrictionRanges: "192.168.0.0/24"} + if !reflect.DeepEqual(want, group) { + t.Errorf("Groups.CreateGroup returned %+v, want %+v", group, want) + } +} + +func TestUpdateGroupWithIPRestrictionRanges(t *testing.T) { + mux, server, client := setup(t) + defer teardown(server) + + mux.HandleFunc("/api/v4/groups/1", + func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPut) + fmt.Fprint(w, `{"id": 1, "ip_restriction_ranges" : "192.168.0.0/24"}`) + }) + + group, _, err := client.Groups.UpdateGroup(1, &UpdateGroupOptions{ + IPRestrictionRanges: String("192.168.0.0/24"), + }) + if err != nil { + t.Errorf("Groups.UpdateGroup returned error: %v", err) + } + + want := &Group{ID: 1, IPRestrictionRanges: "192.168.0.0/24"} + if !reflect.DeepEqual(want, group) { + t.Errorf("Groups.UpdatedGroup returned %+v, want %+v", group, want) + } +} diff --git a/license.go b/license.go index ddec3beac..1c739967a 100644 --- a/license.go +++ b/license.go @@ -17,6 +17,7 @@ package gitlab import ( + "fmt" "net/http" "time" ) @@ -110,3 +111,18 @@ func (s *LicenseService) AddLicense(opt *AddLicenseOptions, options ...RequestOp return l, resp, err } + +// DeleteLicense deletes an existing license. +// +// GitLab API docs: +// https://docs.gitlab.com/ee/api/license.html#delete-a-license +func (s *LicenseService) DeleteLicense(licenseID int, options ...RequestOptionFunc) (*Response, error) { + u := fmt.Sprintf("license/%d", licenseID) + + req, err := s.client.NewRequest(http.MethodDelete, u, nil, options) + if err != nil { + return nil, err + } + + return s.client.Do(req, nil) +} diff --git a/projects.go b/projects.go index ccdaed639..094ec5794 100644 --- a/projects.go +++ b/projects.go @@ -148,6 +148,7 @@ type Project struct { ExternalAuthorizationClassificationLabel string `json:"external_authorization_classification_label"` RequirementsAccessLevel AccessControlValue `json:"requirements_access_level"` SecurityAndComplianceAccessLevel AccessControlValue `json:"security_and_compliance_access_level"` + MergeRequestDefaultTargetSelf bool `json:"mr_default_target_self"` // Deprecated members PublicBuilds bool `json:"public_builds"` @@ -843,6 +844,7 @@ type EditProjectOptions struct { KeepLatestArtifact *bool `url:"keep_latest_artifact,omitempty" json:"keep_latest_artifact,omitempty"` LFSEnabled *bool `url:"lfs_enabled,omitempty" json:"lfs_enabled,omitempty"` MergeCommitTemplate *string `url:"merge_commit_template,omitempty" json:"merge_commit_template,omitempty"` + MergeRequestDefaultTargetSelf *bool `url:"mr_default_target_self,omitempty" json:"mr_default_target_self,omitempty"` MergeMethod *MergeMethodValue `url:"merge_method,omitempty" json:"merge_method,omitempty"` MergePipelinesEnabled *bool `url:"merge_pipelines_enabled,omitempty" json:"merge_pipelines_enabled,omitempty"` MergeRequestsAccessLevel *AccessControlValue `url:"merge_requests_access_level,omitempty" json:"merge_requests_access_level,omitempty"` diff --git a/testdata/webhooks/pipeline.json b/testdata/webhooks/pipeline.json index 5a23d6a23..6f1ba2e20 100644 --- a/testdata/webhooks/pipeline.json +++ b/testdata/webhooks/pipeline.json @@ -72,6 +72,8 @@ "created_at": "2016-08-12 15:23:28 UTC", "started_at": null, "finished_at": null, + "duration": 17.1, + "queued_duration": 3.5, "when": "manual", "manual": true, "allow_failure": true, @@ -108,6 +110,8 @@ "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:26:12 UTC", "finished_at": null, + "duration": 17.0, + "queued_duration": 196.0, "when": "on_success", "manual": false, "allow_failure": false, @@ -137,6 +141,8 @@ "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:26:12 UTC", "finished_at": "2016-08-12 15:26:29 UTC", + "duration": 17.0, + "queued_duration": 196.0, "when": "on_success", "manual": false, "allow_failure": false, @@ -166,6 +172,8 @@ "created_at": "2016-08-12 15:23:28 UTC", "started_at": "2016-08-12 15:24:56 UTC", "finished_at": "2016-08-12 15:25:26 UTC", + "duration": 17.0, + "queued_duration": 196.0, "when": "on_success", "manual": false, "allow_failure": false, @@ -195,6 +203,8 @@ "created_at": "2016-08-12 15:23:28 UTC", "started_at": null, "finished_at": null, + "duration": 17.0, + "queued_duration": 196.0, "when": "on_success", "manual": false, "allow_failure": false,