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