1//
2// Copyright 2021, Sander van Harmelen
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17package gitlab
18
19import (
20	"encoding/json"
21	"fmt"
22	"strconv"
23	"time"
24)
25
26//BuildEvent represents a build event
27//
28// GitLab API docs:
29// https://docs.gitlab.com/ce/user/project/integrations/webhooks.html#build-events
30type BuildEvent struct {
31	ObjectKind        string     `json:"object_kind"`
32	Ref               string     `json:"ref"`
33	Tag               bool       `json:"tag"`
34	BeforeSHA         string     `json:"before_sha"`
35	SHA               string     `json:"sha"`
36	BuildID           int        `json:"build_id"`
37	BuildName         string     `json:"build_name"`
38	BuildStage        string     `json:"build_stage"`
39	BuildStatus       string     `json:"build_status"`
40	BuildStartedAt    string     `json:"build_started_at"`
41	BuildFinishedAt   string     `json:"build_finished_at"`
42	BuildDuration     float64    `json:"build_duration"`
43	BuildAllowFailure bool       `json:"build_allow_failure"`
44	ProjectID         int        `json:"project_id"`
45	ProjectName       string     `json:"project_name"`
46	User              *EventUser `json:"user"`
47	Commit            struct {
48		ID          int    `json:"id"`
49		SHA         string `json:"sha"`
50		Message     string `json:"message"`
51		AuthorName  string `json:"author_name"`
52		AuthorEmail string `json:"author_email"`
53		Status      string `json:"status"`
54		Duration    int    `json:"duration"`
55		StartedAt   string `json:"started_at"`
56		FinishedAt  string `json:"finished_at"`
57	} `json:"commit"`
58	Repository *Repository `json:"repository"`
59}
60
61// CommitCommentEvent represents a comment on a commit event.
62//
63// GitLab API docs:
64// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#comment-on-a-commit
65type CommitCommentEvent struct {
66	ObjectKind string `json:"object_kind"`
67	User       *User  `json:"user"`
68	ProjectID  int    `json:"project_id"`
69	Project    struct {
70		Name              string          `json:"name"`
71		Description       string          `json:"description"`
72		AvatarURL         string          `json:"avatar_url"`
73		GitSSHURL         string          `json:"git_ssh_url"`
74		GitHTTPURL        string          `json:"git_http_url"`
75		Namespace         string          `json:"namespace"`
76		PathWithNamespace string          `json:"path_with_namespace"`
77		DefaultBranch     string          `json:"default_branch"`
78		Homepage          string          `json:"homepage"`
79		URL               string          `json:"url"`
80		SSHURL            string          `json:"ssh_url"`
81		HTTPURL           string          `json:"http_url"`
82		WebURL            string          `json:"web_url"`
83		Visibility        VisibilityValue `json:"visibility"`
84	} `json:"project"`
85	Repository       *Repository `json:"repository"`
86	ObjectAttributes struct {
87		ID           int    `json:"id"`
88		Note         string `json:"note"`
89		NoteableType string `json:"noteable_type"`
90		AuthorID     int    `json:"author_id"`
91		CreatedAt    string `json:"created_at"`
92		UpdatedAt    string `json:"updated_at"`
93		ProjectID    int    `json:"project_id"`
94		Attachment   string `json:"attachment"`
95		LineCode     string `json:"line_code"`
96		CommitID     string `json:"commit_id"`
97		NoteableID   int    `json:"noteable_id"`
98		System       bool   `json:"system"`
99		StDiff       struct {
100			Diff        string `json:"diff"`
101			NewPath     string `json:"new_path"`
102			OldPath     string `json:"old_path"`
103			AMode       string `json:"a_mode"`
104			BMode       string `json:"b_mode"`
105			NewFile     bool   `json:"new_file"`
106			RenamedFile bool   `json:"renamed_file"`
107			DeletedFile bool   `json:"deleted_file"`
108		} `json:"st_diff"`
109		Description string `json:"description"`
110		URL         string `json:"url"`
111	} `json:"object_attributes"`
112	Commit *struct {
113		ID        string     `json:"id"`
114		Title     string     `json:"title"`
115		Message   string     `json:"message"`
116		Timestamp *time.Time `json:"timestamp"`
117		URL       string     `json:"url"`
118		Author    struct {
119			Name  string `json:"name"`
120			Email string `json:"email"`
121		} `json:"author"`
122	} `json:"commit"`
123}
124
125// DeploymentEvent represents a deployment event
126//
127// GitLab API docs:
128// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#deployment-events
129type DeploymentEvent struct {
130	ObjectKind    string `json:"object_kind"`
131	Status        string `json:"status"`
132	DeployableID  int    `json:"deployable_id"`
133	DeployableURL string `json:"deployable_url"`
134	Environment   string `json:"environment"`
135	Project       struct {
136		ID                int     `json:"id"`
137		Name              string  `json:"name"`
138		Description       string  `json:"description"`
139		WebURL            string  `json:"web_url"`
140		AvatarURL         *string `json:"avatar_url"`
141		GitSSHURL         string  `json:"git_ssh_url"`
142		GitHTTPURL        string  `json:"git_http_url"`
143		Namespace         string  `json:"namespace"`
144		VisibilityLevel   int     `json:"visibility_level"`
145		PathWithNamespace string  `json:"path_with_namespace"`
146		DefaultBranch     string  `json:"default_branch"`
147		CIConfigPath      string  `json:"ci_config_path"`
148		Homepage          string  `json:"homepage"`
149		URL               string  `json:"url"`
150		SSHURL            string  `json:"ssh_url"`
151		HTTPURL           string  `json:"http_url"`
152	} `json:"project"`
153	ShortSHA    string     `json:"short_sha"`
154	User        *EventUser `json:"user"`
155	UserURL     string     `json:"user_url"`
156	CommitURL   string     `json:"commit_url"`
157	CommitTitle string     `json:"commit_title"`
158}
159
160// IssueCommentEvent represents a comment on an issue event.
161//
162// GitLab API docs:
163// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#comment-on-an-issue
164type IssueCommentEvent struct {
165	ObjectKind string `json:"object_kind"`
166	User       *User  `json:"user"`
167	ProjectID  int    `json:"project_id"`
168	Project    struct {
169		Name              string          `json:"name"`
170		Description       string          `json:"description"`
171		AvatarURL         string          `json:"avatar_url"`
172		GitSSHURL         string          `json:"git_ssh_url"`
173		GitHTTPURL        string          `json:"git_http_url"`
174		Namespace         string          `json:"namespace"`
175		PathWithNamespace string          `json:"path_with_namespace"`
176		DefaultBranch     string          `json:"default_branch"`
177		Homepage          string          `json:"homepage"`
178		URL               string          `json:"url"`
179		SSHURL            string          `json:"ssh_url"`
180		HTTPURL           string          `json:"http_url"`
181		WebURL            string          `json:"web_url"`
182		Visibility        VisibilityValue `json:"visibility"`
183	} `json:"project"`
184	Repository       *Repository `json:"repository"`
185	ObjectAttributes struct {
186		ID           int     `json:"id"`
187		Note         string  `json:"note"`
188		NoteableType string  `json:"noteable_type"`
189		AuthorID     int     `json:"author_id"`
190		CreatedAt    string  `json:"created_at"`
191		UpdatedAt    string  `json:"updated_at"`
192		ProjectID    int     `json:"project_id"`
193		Attachment   string  `json:"attachment"`
194		LineCode     string  `json:"line_code"`
195		CommitID     string  `json:"commit_id"`
196		NoteableID   int     `json:"noteable_id"`
197		System       bool    `json:"system"`
198		StDiff       []*Diff `json:"st_diff"`
199		Description  string  `json:"description"`
200		URL          string  `json:"url"`
201	} `json:"object_attributes"`
202	Issue struct {
203		ID                  int      `json:"id"`
204		IID                 int      `json:"iid"`
205		ProjectID           int      `json:"project_id"`
206		MilestoneID         int      `json:"milestone_id"`
207		AuthorID            int      `json:"author_id"`
208		Description         string   `json:"description"`
209		State               string   `json:"state"`
210		Title               string   `json:"title"`
211		Labels              []Label  `json:"labels"`
212		LastEditedAt        string   `json:"last_edit_at"`
213		LastEditedByID      int      `json:"last_edited_by_id"`
214		UpdatedAt           string   `json:"updated_at"`
215		UpdatedByID         int      `json:"updated_by_id"`
216		CreatedAt           string   `json:"created_at"`
217		ClosedAt            string   `json:"closed_at"`
218		DueDate             *ISOTime `json:"due_date"`
219		URL                 string   `json:"url"`
220		TimeEstimate        int      `json:"time_estimate"`
221		Confidential        bool     `json:"confidential"`
222		TotalTimeSpent      int      `json:"total_time_spent"`
223		HumanTotalTimeSpent string   `json:"human_total_time_spent"`
224		HumanTimeEstimate   string   `json:"human_time_estimate"`
225		AssigneeIDs         []int    `json:"assignee_ids"`
226		AssigneeID          int      `json:"assignee_id"`
227	} `json:"issue"`
228}
229
230// IssueEvent represents a issue event.
231//
232// GitLab API docs:
233// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#issue-events
234type IssueEvent struct {
235	ObjectKind string     `json:"object_kind"`
236	User       *EventUser `json:"user"`
237	Project    struct {
238		ID                int             `json:"id"`
239		Name              string          `json:"name"`
240		Description       string          `json:"description"`
241		AvatarURL         string          `json:"avatar_url"`
242		GitSSHURL         string          `json:"git_ssh_url"`
243		GitHTTPURL        string          `json:"git_http_url"`
244		Namespace         string          `json:"namespace"`
245		PathWithNamespace string          `json:"path_with_namespace"`
246		DefaultBranch     string          `json:"default_branch"`
247		Homepage          string          `json:"homepage"`
248		URL               string          `json:"url"`
249		SSHURL            string          `json:"ssh_url"`
250		HTTPURL           string          `json:"http_url"`
251		WebURL            string          `json:"web_url"`
252		Visibility        VisibilityValue `json:"visibility"`
253	} `json:"project"`
254	Repository       *Repository `json:"repository"`
255	ObjectAttributes struct {
256		ID          int    `json:"id"`
257		Title       string `json:"title"`
258		AssigneeID  int    `json:"assignee_id"`
259		AuthorID    int    `json:"author_id"`
260		ProjectID   int    `json:"project_id"`
261		CreatedAt   string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468)
262		UpdatedAt   string `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468)
263		Position    int    `json:"position"`
264		BranchName  string `json:"branch_name"`
265		Description string `json:"description"`
266		MilestoneID int    `json:"milestone_id"`
267		State       string `json:"state"`
268		IID         int    `json:"iid"`
269		URL         string `json:"url"`
270		Action      string `json:"action"`
271	} `json:"object_attributes"`
272	Assignee  *EventUser   `json:"assignee"`
273	Assignees *[]EventUser `json:"assignees"`
274	Labels    []Label      `json:"labels"`
275	Changes   struct {
276		Description struct {
277			Previous string `json:"previous"`
278			Current  string `json:"current"`
279		} `json:"description"`
280		Labels struct {
281			Previous []Label `json:"previous"`
282			Current  []Label `json:"current"`
283		} `json:"labels"`
284		Title struct {
285			Previous string `json:"previous"`
286			Current  string `json:"current"`
287		} `json:"title"`
288		UpdatedByID struct {
289			Previous int `json:"previous"`
290			Current  int `json:"current"`
291		} `json:"updated_by_id"`
292		TotalTimeSpent struct {
293			Previous int `json:"previous"`
294			Current  int `json:"current"`
295		} `json:"total_time_spent"`
296	} `json:"changes"`
297}
298
299// JobEvent represents a job event.
300//
301// GitLab API docs:
302// TODO: link to docs instead of src once they are published.
303// https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/data_builder/build.rb
304type JobEvent struct {
305	ObjectKind         string     `json:"object_kind"`
306	Ref                string     `json:"ref"`
307	Tag                bool       `json:"tag"`
308	BeforeSHA          string     `json:"before_sha"`
309	SHA                string     `json:"sha"`
310	BuildID            int        `json:"build_id"`
311	BuildName          string     `json:"build_name"`
312	BuildStage         string     `json:"build_stage"`
313	BuildStatus        string     `json:"build_status"`
314	BuildStartedAt     string     `json:"build_started_at"`
315	BuildFinishedAt    string     `json:"build_finished_at"`
316	BuildDuration      float64    `json:"build_duration"`
317	BuildAllowFailure  bool       `json:"build_allow_failure"`
318	BuildFailureReason string     `json:"build_failure_reason"`
319	PipelineID         int        `json:"pipeline_id"`
320	ProjectID          int        `json:"project_id"`
321	ProjectName        string     `json:"project_name"`
322	User               *EventUser `json:"user"`
323	Commit             struct {
324		ID          int    `json:"id"`
325		SHA         string `json:"sha"`
326		Message     string `json:"message"`
327		AuthorName  string `json:"author_name"`
328		AuthorEmail string `json:"author_email"`
329		AuthorURL   string `json:"author_url"`
330		Status      string `json:"status"`
331		Duration    int    `json:"duration"`
332		StartedAt   string `json:"started_at"`
333		FinishedAt  string `json:"finished_at"`
334	} `json:"commit"`
335	Repository *Repository `json:"repository"`
336	Runner     struct {
337		ID          int    `json:"id"`
338		Active      bool   `json:"active"`
339		Shared      bool   `json:"is_shared"`
340		Description string `json:"description"`
341	} `json:"runner"`
342}
343
344// MergeCommentEvent represents a comment on a merge event.
345//
346// GitLab API docs:
347// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-on-a-merge-request
348type MergeCommentEvent struct {
349	ObjectKind string     `json:"object_kind"`
350	User       *EventUser `json:"user"`
351	ProjectID  int        `json:"project_id"`
352	Project    struct {
353		Name              string          `json:"name"`
354		Description       string          `json:"description"`
355		AvatarURL         string          `json:"avatar_url"`
356		GitSSHURL         string          `json:"git_ssh_url"`
357		GitHTTPURL        string          `json:"git_http_url"`
358		Namespace         string          `json:"namespace"`
359		PathWithNamespace string          `json:"path_with_namespace"`
360		DefaultBranch     string          `json:"default_branch"`
361		Homepage          string          `json:"homepage"`
362		URL               string          `json:"url"`
363		SSHURL            string          `json:"ssh_url"`
364		HTTPURL           string          `json:"http_url"`
365		WebURL            string          `json:"web_url"`
366		Visibility        VisibilityValue `json:"visibility"`
367	} `json:"project"`
368	ObjectAttributes struct {
369		Attachment       string        `json:"attachment"`
370		AuthorID         int           `json:"author_id"`
371		ChangePosition   *NotePosition `json:"change_position"`
372		CommitID         string        `json:"commit_id"`
373		CreatedAt        string        `json:"created_at"`
374		DiscussionID     string        `json:"discussion_id"`
375		ID               int           `json:"id"`
376		LineCode         string        `json:"line_code"`
377		Note             string        `json:"note"`
378		NoteableID       int           `json:"noteable_id"`
379		NoteableType     string        `json:"noteable_type"`
380		OriginalPosition *NotePosition `json:"original_position"`
381		Position         *NotePosition `json:"position"`
382		ProjectID        int           `json:"project_id"`
383		ResolvedAt       string        `json:"resolved_at"`
384		ResolvedByID     int           `json:"resolved_by_id"`
385		ResolvedByPush   bool          `json:"resolved_by_push"`
386		StDiff           *Diff         `json:"st_diff"`
387		System           bool          `json:"system"`
388		Type             string        `json:"type"`
389		UpdatedAt        string        `json:"updated_at"`
390		UpdatedByID      string        `json:"updated_by_id"`
391		Description      string        `json:"description"`
392		URL              string        `json:"url"`
393	} `json:"object_attributes"`
394	Repository   *Repository `json:"repository"`
395	MergeRequest struct {
396		ID                        int          `json:"id"`
397		TargetBranch              string       `json:"target_branch"`
398		SourceBranch              string       `json:"source_branch"`
399		SourceProjectID           int          `json:"source_project_id"`
400		AuthorID                  int          `json:"author_id"`
401		AssigneeID                int          `json:"assignee_id"`
402		AssigneeIDs               []int        `json:"assignee_ids"`
403		Title                     string       `json:"title"`
404		CreatedAt                 string       `json:"created_at"`
405		UpdatedAt                 string       `json:"updated_at"`
406		MilestoneID               int          `json:"milestone_id"`
407		State                     string       `json:"state"`
408		MergeStatus               string       `json:"merge_status"`
409		TargetProjectID           int          `json:"target_project_id"`
410		IID                       int          `json:"iid"`
411		Description               string       `json:"description"`
412		Position                  int          `json:"position"`
413		LockedAt                  string       `json:"locked_at"`
414		UpdatedByID               int          `json:"updated_by_id"`
415		MergeError                string       `json:"merge_error"`
416		MergeParams               *MergeParams `json:"merge_params"`
417		MergeWhenPipelineSucceeds bool         `json:"merge_when_pipeline_succeeds"`
418		MergeUserID               int          `json:"merge_user_id"`
419		MergeCommitSHA            string       `json:"merge_commit_sha"`
420		DeletedAt                 string       `json:"deleted_at"`
421		InProgressMergeCommitSHA  string       `json:"in_progress_merge_commit_sha"`
422		LockVersion               int          `json:"lock_version"`
423		ApprovalsBeforeMerge      string       `json:"approvals_before_merge"`
424		RebaseCommitSHA           string       `json:"rebase_commit_sha"`
425		TimeEstimate              int          `json:"time_estimate"`
426		Squash                    bool         `json:"squash"`
427		LastEditedAt              string       `json:"last_edited_at"`
428		LastEditedByID            int          `json:"last_edited_by_id"`
429		Source                    *Repository  `json:"source"`
430		Target                    *Repository  `json:"target"`
431		LastCommit                struct {
432			ID        string     `json:"id"`
433			Message   string     `json:"message"`
434			Timestamp *time.Time `json:"timestamp"`
435			URL       string     `json:"url"`
436			Author    struct {
437				Name  string `json:"name"`
438				Email string `json:"email"`
439			} `json:"author"`
440		} `json:"last_commit"`
441		WorkInProgress bool `json:"work_in_progress"`
442		TotalTimeSpent int  `json:"total_time_spent"`
443		HeadPipelineID int  `json:"head_pipeline_id"`
444	} `json:"merge_request"`
445}
446
447// MergeEvent represents a merge event.
448//
449// GitLab API docs:
450// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#merge-request-events
451type MergeEvent struct {
452	ObjectKind string     `json:"object_kind"`
453	User       *EventUser `json:"user"`
454	Project    struct {
455		ID                int             `json:"id"`
456		Name              string          `json:"name"`
457		Description       string          `json:"description"`
458		AvatarURL         string          `json:"avatar_url"`
459		GitSSHURL         string          `json:"git_ssh_url"`
460		GitHTTPURL        string          `json:"git_http_url"`
461		Namespace         string          `json:"namespace"`
462		PathWithNamespace string          `json:"path_with_namespace"`
463		DefaultBranch     string          `json:"default_branch"`
464		Homepage          string          `json:"homepage"`
465		URL               string          `json:"url"`
466		SSHURL            string          `json:"ssh_url"`
467		HTTPURL           string          `json:"http_url"`
468		WebURL            string          `json:"web_url"`
469		Visibility        VisibilityValue `json:"visibility"`
470	} `json:"project"`
471	ObjectAttributes struct {
472		ID                       int          `json:"id"`
473		TargetBranch             string       `json:"target_branch"`
474		SourceBranch             string       `json:"source_branch"`
475		SourceProjectID          int          `json:"source_project_id"`
476		AuthorID                 int          `json:"author_id"`
477		AssigneeID               int          `json:"assignee_id"`
478		AssigneeIDs              []int        `json:"assignee_ids"`
479		Title                    string       `json:"title"`
480		CreatedAt                string       `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468)
481		UpdatedAt                string       `json:"updated_at"` // Should be *time.Time (see Gitlab issue #21468)
482		StCommits                []*Commit    `json:"st_commits"`
483		StDiffs                  []*Diff      `json:"st_diffs"`
484		MilestoneID              int          `json:"milestone_id"`
485		State                    string       `json:"state"`
486		MergeStatus              string       `json:"merge_status"`
487		TargetProjectID          int          `json:"target_project_id"`
488		IID                      int          `json:"iid"`
489		Description              string       `json:"description"`
490		Position                 int          `json:"position"`
491		LockedAt                 string       `json:"locked_at"`
492		UpdatedByID              int          `json:"updated_by_id"`
493		MergeError               string       `json:"merge_error"`
494		MergeParams              *MergeParams `json:"merge_params"`
495		MergeWhenBuildSucceeds   bool         `json:"merge_when_build_succeeds"`
496		MergeUserID              int          `json:"merge_user_id"`
497		MergeCommitSHA           string       `json:"merge_commit_sha"`
498		DeletedAt                string       `json:"deleted_at"`
499		ApprovalsBeforeMerge     string       `json:"approvals_before_merge"`
500		RebaseCommitSHA          string       `json:"rebase_commit_sha"`
501		InProgressMergeCommitSHA string       `json:"in_progress_merge_commit_sha"`
502		LockVersion              int          `json:"lock_version"`
503		TimeEstimate             int          `json:"time_estimate"`
504		Source                   *Repository  `json:"source"`
505		Target                   *Repository  `json:"target"`
506		HeadPipelineID           *int         `json:"head_pipeline_id"`
507		LastCommit               struct {
508			ID        string     `json:"id"`
509			Message   string     `json:"message"`
510			Timestamp *time.Time `json:"timestamp"`
511			URL       string     `json:"url"`
512			Author    struct {
513				Name  string `json:"name"`
514				Email string `json:"email"`
515			} `json:"author"`
516		} `json:"last_commit"`
517		WorkInProgress bool       `json:"work_in_progress"`
518		URL            string     `json:"url"`
519		Action         string     `json:"action"`
520		OldRev         string     `json:"oldrev"`
521		Assignee       *EventUser `json:"assignee"`
522	} `json:"object_attributes"`
523	Repository *Repository  `json:"repository"`
524	Assignee   *EventUser   `json:"assignee"`
525	Assignees  []*EventUser `json:"assignees"`
526	Labels     []*Label     `json:"labels"`
527	Changes    struct {
528		Assignees struct {
529			Previous []*EventUser `json:"previous"`
530			Current  []*EventUser `json:"current"`
531		} `json:"assignees"`
532		Description struct {
533			Previous string `json:"previous"`
534			Current  string `json:"current"`
535		} `json:"description"`
536		Labels struct {
537			Previous []*Label `json:"previous"`
538			Current  []*Label `json:"current"`
539		} `json:"labels"`
540		SourceBranch struct {
541			Previous string `json:"previous"`
542			Current  string `json:"current"`
543		} `json:"source_branch"`
544		SourceProjectID struct {
545			Previous int `json:"previous"`
546			Current  int `json:"current"`
547		} `json:"source_project_id"`
548		StateID struct {
549			Previous int `json:"previous"`
550			Current  int `json:"current"`
551		} `json:"state_id"`
552		TargetBranch struct {
553			Previous string `json:"previous"`
554			Current  string `json:"current"`
555		} `json:"target_branch"`
556		TargetProjectID struct {
557			Previous int `json:"previous"`
558			Current  int `json:"current"`
559		} `json:"target_project_id"`
560		Title struct {
561			Previous string `json:"previous"`
562			Current  string `json:"current"`
563		} `json:"title"`
564		UpdatedByID struct {
565			Previous int `json:"previous"`
566			Current  int `json:"current"`
567		} `json:"updated_by_id"`
568		MilestoneID struct {
569			Previous int `json:"previous"`
570			Current  int `json:"current"`
571		} `json:"milestone_id"`
572	} `json:"changes"`
573}
574
575// EventUser represents a user record in an event and is used as an even initiator or a merge assignee.
576type EventUser struct {
577	ID        int    `json:"id"`
578	Name      string `json:"name"`
579	Username  string `json:"username"`
580	AvatarURL string `json:"avatar_url"`
581	Email     string `json:"email"`
582}
583
584// MergeParams represents the merge params.
585type MergeParams struct {
586	ForceRemoveSourceBranch bool `json:"force_remove_source_branch"`
587}
588
589// UnmarshalJSON decodes the merge parameters
590//
591// This allows support of ForceRemoveSourceBranch for both type bool (>11.9) and string (<11.9)
592func (p *MergeParams) UnmarshalJSON(b []byte) error {
593	type Alias MergeParams
594	raw := struct {
595		*Alias
596		ForceRemoveSourceBranch interface{} `json:"force_remove_source_branch"`
597	}{
598		Alias: (*Alias)(p),
599	}
600
601	err := json.Unmarshal(b, &raw)
602	if err != nil {
603		return err
604	}
605
606	switch v := raw.ForceRemoveSourceBranch.(type) {
607	case nil:
608		// No action needed.
609	case bool:
610		p.ForceRemoveSourceBranch = v
611	case string:
612		p.ForceRemoveSourceBranch, err = strconv.ParseBool(v)
613		if err != nil {
614			return err
615		}
616	default:
617		return fmt.Errorf("failed to unmarshal ForceRemoveSourceBranch of type: %T", v)
618	}
619
620	return nil
621}
622
623// PipelineEvent represents a pipeline event.
624//
625// GitLab API docs:
626// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#pipeline-events
627type PipelineEvent struct {
628	ObjectKind       string `json:"object_kind"`
629	ObjectAttributes struct {
630		ID             int      `json:"id"`
631		Ref            string   `json:"ref"`
632		Tag            bool     `json:"tag"`
633		SHA            string   `json:"sha"`
634		BeforeSHA      string   `json:"before_sha"`
635		Source         string   `json:"source"`
636		Status         string   `json:"status"`
637		DetailedStatus string   `json:"detailed_status"`
638		Stages         []string `json:"stages"`
639		CreatedAt      string   `json:"created_at"`
640		FinishedAt     string   `json:"finished_at"`
641		Duration       int      `json:"duration"`
642		QueuedDuration int      `json:"queued_duration"`
643		Variables      []struct {
644			Key   string `json:"key"`
645			Value string `json:"value"`
646		} `json:"variables"`
647	} `json:"object_attributes"`
648	MergeRequest struct {
649		ID                 int    `json:"id"`
650		IID                int    `json:"iid"`
651		Title              string `json:"title"`
652		SourceBranch       string `json:"source_branch"`
653		SourceProjectID    int    `json:"source_project_id"`
654		TargetBranch       string `json:"target_branch"`
655		TargetProjectID    int    `json:"target_project_id"`
656		State              string `json:"state"`
657		MergeRequestStatus string `json:"merge_status"`
658		URL                string `json:"url"`
659	} `json:"merge_request"`
660	User    *EventUser `json:"user"`
661	Project struct {
662		ID                int             `json:"id"`
663		Name              string          `json:"name"`
664		Description       string          `json:"description"`
665		AvatarURL         string          `json:"avatar_url"`
666		GitSSHURL         string          `json:"git_ssh_url"`
667		GitHTTPURL        string          `json:"git_http_url"`
668		Namespace         string          `json:"namespace"`
669		PathWithNamespace string          `json:"path_with_namespace"`
670		DefaultBranch     string          `json:"default_branch"`
671		Homepage          string          `json:"homepage"`
672		URL               string          `json:"url"`
673		SSHURL            string          `json:"ssh_url"`
674		HTTPURL           string          `json:"http_url"`
675		WebURL            string          `json:"web_url"`
676		Visibility        VisibilityValue `json:"visibility"`
677	} `json:"project"`
678	Commit struct {
679		ID        string     `json:"id"`
680		Message   string     `json:"message"`
681		Timestamp *time.Time `json:"timestamp"`
682		URL       string     `json:"url"`
683		Author    struct {
684			Name  string `json:"name"`
685			Email string `json:"email"`
686		} `json:"author"`
687	} `json:"commit"`
688	Builds []struct {
689		ID           int        `json:"id"`
690		Stage        string     `json:"stage"`
691		Name         string     `json:"name"`
692		Status       string     `json:"status"`
693		CreatedAt    string     `json:"created_at"`
694		StartedAt    string     `json:"started_at"`
695		FinishedAt   string     `json:"finished_at"`
696		When         string     `json:"when"`
697		Manual       bool       `json:"manual"`
698		AllowFailure bool       `json:"allow_failure"`
699		User         *EventUser `json:"user"`
700		Runner       struct {
701			ID          int      `json:"id"`
702			Description string   `json:"description"`
703			Active      bool     `json:"active"`
704			IsShared    bool     `json:"is_shared"`
705			RunnerType  string   `json:"runner_type"`
706			Tags        []string `json:"tags"`
707		} `json:"runner"`
708		ArtifactsFile struct {
709			Filename string `json:"filename"`
710			Size     int    `json:"size"`
711		} `json:"artifacts_file"`
712		Environment struct {
713			Name           string `json:"name"`
714			Action         string `json:"action"`
715			DeploymentTier string `json:"deployment_tier"`
716		} `json:"environment"`
717	} `json:"builds"`
718}
719
720// PushEvent represents a push event.
721//
722// GitLab API docs:
723// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#push-events
724type PushEvent struct {
725	ObjectKind   string `json:"object_kind"`
726	Before       string `json:"before"`
727	After        string `json:"after"`
728	Ref          string `json:"ref"`
729	CheckoutSHA  string `json:"checkout_sha"`
730	UserID       int    `json:"user_id"`
731	UserName     string `json:"user_name"`
732	UserUsername string `json:"user_username"`
733	UserEmail    string `json:"user_email"`
734	UserAvatar   string `json:"user_avatar"`
735	ProjectID    int    `json:"project_id"`
736	Project      struct {
737		Name              string          `json:"name"`
738		Description       string          `json:"description"`
739		AvatarURL         string          `json:"avatar_url"`
740		GitSSHURL         string          `json:"git_ssh_url"`
741		GitHTTPURL        string          `json:"git_http_url"`
742		Namespace         string          `json:"namespace"`
743		PathWithNamespace string          `json:"path_with_namespace"`
744		DefaultBranch     string          `json:"default_branch"`
745		Homepage          string          `json:"homepage"`
746		URL               string          `json:"url"`
747		SSHURL            string          `json:"ssh_url"`
748		HTTPURL           string          `json:"http_url"`
749		WebURL            string          `json:"web_url"`
750		Visibility        VisibilityValue `json:"visibility"`
751	} `json:"project"`
752	Repository *Repository `json:"repository"`
753	Commits    []*struct {
754		ID        string     `json:"id"`
755		Message   string     `json:"message"`
756		Title     string     `json:"title"`
757		Timestamp *time.Time `json:"timestamp"`
758		URL       string     `json:"url"`
759		Author    struct {
760			Name  string `json:"name"`
761			Email string `json:"email"`
762		} `json:"author"`
763		Added    []string `json:"added"`
764		Modified []string `json:"modified"`
765		Removed  []string `json:"removed"`
766	} `json:"commits"`
767	TotalCommitsCount int `json:"total_commits_count"`
768}
769
770// ReleaseEvent represents a release event
771//
772// GitLab API docs:
773// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#release-events
774type ReleaseEvent struct {
775	ID          int    `json:"id"`
776	CreatedAt   string `json:"created_at"` // Should be *time.Time (see Gitlab issue #21468)
777	Description string `json:"description"`
778	Name        string `json:"name"`
779	Tag         string `json:"tag"`
780	ReleasedAt  string `json:"released_at"` // Should be *time.Time (see Gitlab issue #21468)
781	ObjectKind  string `json:"object_kind"`
782	Project     struct {
783		ID                int     `json:"id"`
784		Name              string  `json:"name"`
785		Description       string  `json:"description"`
786		WebURL            string  `json:"web_url"`
787		AvatarURL         *string `json:"avatar_url"`
788		GitSSHURL         string  `json:"git_ssh_url"`
789		GitHTTPURL        string  `json:"git_http_url"`
790		Namespace         string  `json:"namespace"`
791		VisibilityLevel   int     `json:"visibility_level"`
792		PathWithNamespace string  `json:"path_with_namespace"`
793		DefaultBranch     string  `json:"default_branch"`
794		CIConfigPath      string  `json:"ci_config_path"`
795		Homepage          string  `json:"homepage"`
796		URL               string  `json:"url"`
797		SSHURL            string  `json:"ssh_url"`
798		HTTPURL           string  `json:"http_url"`
799	} `json:"project"`
800	URL    string `json:"url"`
801	Action string `json:"action"`
802	Assets struct {
803		Count int `json:"count"`
804		Links []struct {
805			ID       int    `json:"id"`
806			External bool   `json:"external"`
807			LinkType string `json:"link_type"`
808			Name     string `json:"name"`
809			URL      string `json:"url"`
810		} `json:"links"`
811		Sources []struct {
812			Format string `json:"format"`
813			URL    string `json:"url"`
814		} `json:"sources"`
815	} `json:"assets"`
816	Commit struct {
817		ID        string `json:"id"`
818		Message   string `json:"message"`
819		Title     string `json:"title"`
820		Timestamp string `json:"timestamp"` // Should be *time.Time (see Gitlab issue #21468)
821		URL       string `json:"url"`
822		Author    struct {
823			Name  string `json:"name"`
824			Email string `json:"email"`
825		} `json:"author"`
826	} `json:"commit"`
827}
828
829// SnippetCommentEvent represents a comment on a snippet event.
830//
831// GitLab API docs:
832// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-on-a-code-snippet
833type SnippetCommentEvent struct {
834	ObjectKind string     `json:"object_kind"`
835	User       *EventUser `json:"user"`
836	ProjectID  int        `json:"project_id"`
837	Project    struct {
838		Name              string          `json:"name"`
839		Description       string          `json:"description"`
840		AvatarURL         string          `json:"avatar_url"`
841		GitSSHURL         string          `json:"git_ssh_url"`
842		GitHTTPURL        string          `json:"git_http_url"`
843		Namespace         string          `json:"namespace"`
844		PathWithNamespace string          `json:"path_with_namespace"`
845		DefaultBranch     string          `json:"default_branch"`
846		Homepage          string          `json:"homepage"`
847		URL               string          `json:"url"`
848		SSHURL            string          `json:"ssh_url"`
849		HTTPURL           string          `json:"http_url"`
850		WebURL            string          `json:"web_url"`
851		Visibility        VisibilityValue `json:"visibility"`
852	} `json:"project"`
853	Repository       *Repository `json:"repository"`
854	ObjectAttributes struct {
855		ID           int    `json:"id"`
856		Note         string `json:"note"`
857		NoteableType string `json:"noteable_type"`
858		AuthorID     int    `json:"author_id"`
859		CreatedAt    string `json:"created_at"`
860		UpdatedAt    string `json:"updated_at"`
861		ProjectID    int    `json:"project_id"`
862		Attachment   string `json:"attachment"`
863		LineCode     string `json:"line_code"`
864		CommitID     string `json:"commit_id"`
865		NoteableID   int    `json:"noteable_id"`
866		System       bool   `json:"system"`
867		StDiff       *Diff  `json:"st_diff"`
868		Description  string `json:"description"`
869		URL          string `json:"url"`
870	} `json:"object_attributes"`
871	Snippet *Snippet `json:"snippet"`
872}
873
874// SubGroupEvent represents a subgroup event.
875//
876// GitLab API docs:
877// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#subgroup-events
878type SubGroupEvent struct {
879	CreatedAt      *time.Time `json:"created_at"`
880	UpdatedAt      *time.Time `json:"updated_at"`
881	EventName      string     `json:"event_name"`
882	Name           string     `json:"name"`
883	Path           string     `json:"path"`
884	FullPath       string     `json:"full_path"`
885	GroupID        int        `json:"group_id"`
886	ParentGroupID  int        `json:"parent_group_id"`
887	ParentName     string     `json:"parent_name"`
888	ParentPath     string     `json:"parent_path"`
889	ParentFullPath string     `json:"parent_full_path"`
890}
891
892// TagEvent represents a tag event.
893//
894// GitLab API docs:
895// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#tag-events
896type TagEvent struct {
897	ObjectKind   string `json:"object_kind"`
898	Before       string `json:"before"`
899	After        string `json:"after"`
900	Ref          string `json:"ref"`
901	CheckoutSHA  string `json:"checkout_sha"`
902	UserID       int    `json:"user_id"`
903	UserName     string `json:"user_name"`
904	UserUsername string `json:"user_username"`
905	UserAvatar   string `json:"user_avatar"`
906	UserEmail    string `json:"user_email"`
907	ProjectID    int    `json:"project_id"`
908	Message      string `json:"message"`
909	Project      struct {
910		Name              string          `json:"name"`
911		Description       string          `json:"description"`
912		AvatarURL         string          `json:"avatar_url"`
913		GitSSHURL         string          `json:"git_ssh_url"`
914		GitHTTPURL        string          `json:"git_http_url"`
915		Namespace         string          `json:"namespace"`
916		PathWithNamespace string          `json:"path_with_namespace"`
917		DefaultBranch     string          `json:"default_branch"`
918		Homepage          string          `json:"homepage"`
919		URL               string          `json:"url"`
920		SSHURL            string          `json:"ssh_url"`
921		HTTPURL           string          `json:"http_url"`
922		WebURL            string          `json:"web_url"`
923		Visibility        VisibilityValue `json:"visibility"`
924	} `json:"project"`
925	Repository *Repository `json:"repository"`
926	Commits    []*struct {
927		ID        string     `json:"id"`
928		Message   string     `json:"message"`
929		Title     string     `json:"title"`
930		Timestamp *time.Time `json:"timestamp"`
931		URL       string     `json:"url"`
932		Author    struct {
933			Name  string `json:"name"`
934			Email string `json:"email"`
935		} `json:"author"`
936		Added    []string `json:"added"`
937		Modified []string `json:"modified"`
938		Removed  []string `json:"removed"`
939	} `json:"commits"`
940	TotalCommitsCount int `json:"total_commits_count"`
941}
942
943// WikiPageEvent represents a wiki page event.
944//
945// GitLab API docs:
946// https://docs.gitlab.com/ce/user/project/integrations/webhook_events.html#wiki-page-events
947type WikiPageEvent struct {
948	ObjectKind string     `json:"object_kind"`
949	User       *EventUser `json:"user"`
950	Project    struct {
951		Name              string          `json:"name"`
952		Description       string          `json:"description"`
953		AvatarURL         string          `json:"avatar_url"`
954		GitSSHURL         string          `json:"git_ssh_url"`
955		GitHTTPURL        string          `json:"git_http_url"`
956		Namespace         string          `json:"namespace"`
957		PathWithNamespace string          `json:"path_with_namespace"`
958		DefaultBranch     string          `json:"default_branch"`
959		Homepage          string          `json:"homepage"`
960		URL               string          `json:"url"`
961		SSHURL            string          `json:"ssh_url"`
962		HTTPURL           string          `json:"http_url"`
963		WebURL            string          `json:"web_url"`
964		Visibility        VisibilityValue `json:"visibility"`
965	} `json:"project"`
966	Wiki struct {
967		WebURL            string `json:"web_url"`
968		GitSSHURL         string `json:"git_ssh_url"`
969		GitHTTPURL        string `json:"git_http_url"`
970		PathWithNamespace string `json:"path_with_namespace"`
971		DefaultBranch     string `json:"default_branch"`
972	} `json:"wiki"`
973	ObjectAttributes struct {
974		Title   string `json:"title"`
975		Content string `json:"content"`
976		Format  string `json:"format"`
977		Message string `json:"message"`
978		Slug    string `json:"slug"`
979		URL     string `json:"url"`
980		Action  string `json:"action"`
981	} `json:"object_attributes"`
982}
983