diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
index 6ced1c77..cec6fb51 100644
--- a/.devcontainer/docker-compose.yml
+++ b/.devcontainer/docker-compose.yml
@@ -8,6 +8,9 @@ services:
volumes:
- ..:/workspace:cached
command: sleep infinity
+ ports:
+ - '3000:3000'
+ - '3001:3001'
postgres:
image: 'postgres:14.5-alpine'
environment:
diff --git a/.gitignore b/.gitignore
index ba7f9dc3..3f9eca91 100644
--- a/.gitignore
+++ b/.gitignore
@@ -125,3 +125,6 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
+
+# MacOS finder preferences
+.DS_store
diff --git a/packages/backend/bin/database/seed-user.ts b/packages/backend/bin/database/seed-user.ts
index 0ce56315..a741d415 100644
--- a/packages/backend/bin/database/seed-user.ts
+++ b/packages/backend/bin/database/seed-user.ts
@@ -1,3 +1,6 @@
import { createUser } from './utils';
-createUser();
+(async () => {
+ await createUser();
+ process.exit();
+})();
diff --git a/packages/backend/src/apps/gitlab/assets/favicon.svg b/packages/backend/src/apps/gitlab/assets/favicon.svg
new file mode 100644
index 00000000..b1108696
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/assets/favicon.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/packages/backend/src/apps/gitlab/auth/generate-auth-url.ts b/packages/backend/src/apps/gitlab/auth/generate-auth-url.ts
new file mode 100644
index 00000000..6845d1c9
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/auth/generate-auth-url.ts
@@ -0,0 +1,24 @@
+import { IGlobalVariable } from '@automatisch/types';
+import { URLSearchParams } from 'url';
+
+export default async function generateAuthUrl($: IGlobalVariable) {
+ // ref: https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
+
+ const scopes = ['api', 'read_user'];
+
+ const searchParams = new URLSearchParams({
+ client_id: $.auth.data.clientId as string,
+ redirect_uri: $.auth.data.oAuthRedirectUrl as string,
+ scope: scopes.join(' '),
+ response_type: 'code',
+ state: `${Date.now()}`,
+ });
+
+ const url = `${
+ $.auth.data.oInstanceUrl
+ }/oauth/authorize?${searchParams.toString()}`;
+
+ await $.auth.set({
+ url,
+ });
+}
diff --git a/packages/backend/src/apps/gitlab/auth/index.ts b/packages/backend/src/apps/gitlab/auth/index.ts
new file mode 100644
index 00000000..e8fe83cd
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/auth/index.ts
@@ -0,0 +1,63 @@
+import generateAuthUrl from './generate-auth-url';
+import verifyCredentials from './verify-credentials';
+import isStillVerified from './is-still-verified';
+import refreshToken from './refresh-token';
+
+export default {
+ fields: [
+ {
+ key: 'oInstanceUrl',
+ label: 'Gitlab instance URL',
+ type: 'string' as const,
+ required: false,
+ readOnly: false,
+ value: 'https://gitlab.com',
+ placeholder: 'https://gitlab.com',
+ description: 'Your Gitlab instance URL. Default is https://gitlab.com.',
+ docUrl: 'https://automatisch.io/docs/gitlab#oauth-redirect-url',
+ clickToCopy: true,
+ },
+ {
+ key: 'oAuthRedirectUrl',
+ label: 'OAuth Redirect URL',
+ type: 'string' as const,
+ required: true,
+ readOnly: true,
+ value: '{WEB_APP_URL}/app/gitlab/connections/add',
+ placeholder: null,
+ description:
+ 'When asked to input an OAuth callback or redirect URL in Gitlab OAuth, enter the URL above.',
+ docUrl: 'https://automatisch.io/docs/gitlab#oauth-redirect-url',
+ clickToCopy: true,
+ },
+ {
+ key: 'clientId',
+ label: 'Client ID',
+ type: 'string' as const,
+ required: true,
+ readOnly: false,
+ value: null,
+ placeholder: null,
+ description: null,
+ docUrl: 'https://automatisch.io/docs/gitlab#client-id',
+ clickToCopy: false,
+ },
+ {
+ key: 'clientSecret',
+ label: 'Client Secret',
+ type: 'string' as const,
+ required: true,
+ readOnly: false,
+ value: null,
+ placeholder: null,
+ description: null,
+ docUrl: 'https://automatisch.io/docs/gitlab#client-secret',
+ clickToCopy: false,
+ },
+ ],
+
+ generateAuthUrl,
+ refreshToken,
+ verifyCredentials,
+ isStillVerified,
+};
diff --git a/packages/backend/src/apps/gitlab/auth/is-still-verified.ts b/packages/backend/src/apps/gitlab/auth/is-still-verified.ts
new file mode 100644
index 00000000..befb7694
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/auth/is-still-verified.ts
@@ -0,0 +1,9 @@
+import { IGlobalVariable } from '@automatisch/types';
+import getCurrentUser from '../common/get-current-user';
+
+const isStillVerified = async ($: IGlobalVariable) => {
+ const user = await getCurrentUser($);
+ return !!user.id;
+};
+
+export default isStillVerified;
diff --git a/packages/backend/src/apps/gitlab/auth/refresh-token.ts b/packages/backend/src/apps/gitlab/auth/refresh-token.ts
new file mode 100644
index 00000000..b57f292b
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/auth/refresh-token.ts
@@ -0,0 +1,24 @@
+import { IGlobalVariable } from '@automatisch/types';
+import { URLSearchParams } from 'url';
+
+const refreshToken = async ($: IGlobalVariable) => {
+ // ref: https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
+
+ const params = new URLSearchParams({
+ grant_type: 'refresh_token',
+ client_id: $.auth.data.clientId as string,
+ client_secret: $.auth.data.clientSecret as string,
+ refresh_token: $.auth.data.refreshToken as string,
+ });
+
+ const { data } = await $.http.post('/oauth/token', params.toString());
+
+ await $.auth.set({
+ accessToken: data.access_token,
+ expiresIn: data.expires_in,
+ tokenType: data.token_type,
+ refreshToken: data.refresh_token,
+ });
+};
+
+export default refreshToken;
diff --git a/packages/backend/src/apps/gitlab/auth/verify-credentials.ts b/packages/backend/src/apps/gitlab/auth/verify-credentials.ts
new file mode 100644
index 00000000..e5832113
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/auth/verify-credentials.ts
@@ -0,0 +1,41 @@
+import { IGlobalVariable } from '@automatisch/types';
+import getCurrentUser from '../common/get-current-user';
+
+const verifyCredentials = async ($: IGlobalVariable) => {
+ // ref: https://docs.gitlab.com/ee/api/oauth2.html#authorization-code-flow
+
+ const response = await $.http.post(
+ `${$.auth.data.oInstanceUrl}/oauth/token`,
+ {
+ client_id: $.auth.data.clientId,
+ client_secret: $.auth.data.clientSecret,
+ code: $.auth.data.code,
+ grant_type: 'authorization_code',
+ redirect_uri: $.auth.data.oAuthRedirectUrl,
+ },
+ {
+ headers: {
+ Accept: 'application/json',
+ },
+ }
+ );
+
+ const data = response.data;
+
+ $.auth.data.accessToken = data.access_token;
+
+ const currentUser = await getCurrentUser($);
+
+ await $.auth.set({
+ clientId: $.auth.data.clientId,
+ clientSecret: $.auth.data.clientSecret,
+ accessToken: data.access_token,
+ refreshToken: data.refresh_token,
+ scope: data.scope,
+ tokenType: data.token_type,
+ userId: currentUser.id,
+ screenName: currentUser.username,
+ });
+};
+
+export default verifyCredentials;
diff --git a/packages/backend/src/apps/gitlab/common/add-auth-header.ts b/packages/backend/src/apps/gitlab/common/add-auth-header.ts
new file mode 100644
index 00000000..3af3e250
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/common/add-auth-header.ts
@@ -0,0 +1,14 @@
+import { TBeforeRequest } from '@automatisch/types';
+
+const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
+ if ($.auth.data.oInstanceUrl) {
+ requestConfig.baseURL = $.auth.data.oInstanceUrl as string;
+ }
+
+ if (requestConfig.headers && $.auth.data?.accessToken) {
+ requestConfig.headers.Authorization = `Bearer ${$.auth.data.accessToken}`;
+ }
+ return requestConfig;
+};
+
+export default addAuthHeader;
diff --git a/packages/backend/src/apps/gitlab/common/get-current-user.ts b/packages/backend/src/apps/gitlab/common/get-current-user.ts
new file mode 100644
index 00000000..f1a98387
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/common/get-current-user.ts
@@ -0,0 +1,11 @@
+import { IGlobalVariable, IJSONObject } from '@automatisch/types';
+
+const getCurrentUser = async ($: IGlobalVariable): Promise => {
+ // ref: https://docs.gitlab.com/ee/api/users.html#list-current-user
+
+ const response = await $.http.get(`${$.auth.data.oInstanceUrl}/api/v4/user`);
+ const currentUser = response.data;
+ return currentUser;
+};
+
+export default getCurrentUser;
diff --git a/packages/backend/src/apps/gitlab/common/paginate-all.ts b/packages/backend/src/apps/gitlab/common/paginate-all.ts
new file mode 100644
index 00000000..664489ab
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/common/paginate-all.ts
@@ -0,0 +1,33 @@
+import { IGlobalVariable, IJSONObject } from '@automatisch/types';
+import type { AxiosResponse } from 'axios';
+import parseLinkHeader from '../../../helpers/parse-header-link';
+
+type TResponse = {
+ data: IJSONObject[];
+ error?: IJSONObject;
+};
+
+export default async function paginateAll(
+ $: IGlobalVariable,
+ request: Promise
+) {
+ const response = await request;
+
+ const aggregatedResponse: TResponse = {
+ data: [...response.data],
+ };
+
+ let links = parseLinkHeader(response.headers.link);
+
+ while (links.next) {
+ const nextPageResponse = await $.http.request({
+ ...response.config,
+ url: links.next.uri,
+ });
+
+ aggregatedResponse.data.push(...nextPageResponse.data);
+ links = parseLinkHeader(nextPageResponse.headers.link);
+ }
+
+ return aggregatedResponse;
+}
diff --git a/packages/backend/src/apps/gitlab/dynamic-data/index.ts b/packages/backend/src/apps/gitlab/dynamic-data/index.ts
new file mode 100644
index 00000000..27787b4b
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/dynamic-data/index.ts
@@ -0,0 +1,3 @@
+import listProjects from './list-projects';
+
+export default [listProjects];
diff --git a/packages/backend/src/apps/gitlab/dynamic-data/list-projects/index.ts b/packages/backend/src/apps/gitlab/dynamic-data/list-projects/index.ts
new file mode 100644
index 00000000..b3ac5aa6
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/dynamic-data/list-projects/index.ts
@@ -0,0 +1,33 @@
+import { IGlobalVariable } from '@automatisch/types';
+import paginateAll from '../../common/paginate-all';
+
+export default {
+ name: 'List projects',
+ key: 'listProjects',
+
+ async run($: IGlobalVariable) {
+ // ref:
+ // - https://docs.gitlab.com/ee/api/projects.html#list-all-projects
+ // - https://docs.gitlab.com/ee/api/rest/index.html#keyset-based-pagination
+
+ const firstPageRequest = $.http.get('/api/v4/projects', {
+ params: {
+ simple: true,
+ pagination: 'keyset',
+ order_by: 'id',
+ sort: 'asc',
+ },
+ });
+
+ const response = await paginateAll($, firstPageRequest);
+
+ response.data = response.data.map((repo: { name: string; id: number }) => {
+ return {
+ value: repo.id,
+ name: repo.name,
+ };
+ });
+
+ return response;
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/index.ts b/packages/backend/src/apps/gitlab/index.ts
new file mode 100644
index 00000000..f7c0b59f
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/index.ts
@@ -0,0 +1,20 @@
+import defineApp from '../../helpers/define-app';
+import addAuthHeader from './common/add-auth-header';
+import auth from './auth';
+import triggers from './triggers';
+import dynamicData from './dynamic-data';
+
+export default defineApp({
+ name: 'Gitlab',
+ key: 'gitlab',
+ baseUrl: 'https://gitlab.com',
+ apiBaseUrl: 'https://gitlab.com/api/v4',
+ iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
+ authDocUrl: 'https://automatisch.io/docs/apps/gitlab/connection',
+ primaryColor: '000000',
+ supportsConnections: true,
+ beforeRequest: [addAuthHeader],
+ auth,
+ triggers,
+ dynamicData,
+});
diff --git a/packages/backend/src/apps/gitlab/triggers/confidential-issue-event/index.ts b/packages/backend/src/apps/gitlab/triggers/confidential-issue-event/index.ts
new file mode 100644
index 00000000..81249e29
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/confidential-issue-event/index.ts
@@ -0,0 +1,27 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+// confidential_issues_events has the same event data as issues_events
+import data from './issues_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Confidential issue events',
+ description:
+ 'Confidential issue events (triggered when a new confidential issue is created or an existing issue is updated, closed, or reopened)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events',
+ key: GITLAB_EVENT_TYPE.confidential_issues_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_issues_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/confidential-issue-event/issues_events.ts b/packages/backend/src/apps/gitlab/triggers/confidential-issue-event/issues_events.ts
new file mode 100644
index 00000000..75a243b3
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/confidential-issue-event/issues_events.ts
@@ -0,0 +1,159 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events
+
+export default {
+ object_kind: 'issue',
+ event_type: 'issue',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ project: {
+ id: 1,
+ name: 'Gitlab Test',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/gitlabhq/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ namespace: 'GitlabHQ',
+ visibility_level: 20,
+ path_with_namespace: 'gitlabhq/gitlab-test',
+ default_branch: 'master',
+ ci_config_path: null,
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ },
+ object_attributes: {
+ id: 301,
+ title: 'New API: create/update/delete file',
+ assignee_ids: [51],
+ assignee_id: 51,
+ author_id: 51,
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ updated_by_id: 1,
+ last_edited_at: null,
+ last_edited_by_id: null,
+ relative_position: 0,
+ description: 'Create new API for manipulations with repository',
+ milestone_id: null,
+ state_id: 1,
+ confidential: false,
+ discussion_locked: true,
+ due_date: null,
+ moved_to_id: null,
+ duplicated_to_id: null,
+ time_estimate: 0,
+ total_time_spent: 0,
+ time_change: 0,
+ human_total_time_spent: null,
+ human_time_estimate: null,
+ human_time_change: null,
+ weight: null,
+ iid: 23,
+ url: 'http://example.com/diaspora/issues/23',
+ state: 'opened',
+ action: 'open',
+ severity: 'high',
+ escalation_status: 'triggered',
+ escalation_policy: {
+ id: 18,
+ name: 'Engineering On-call',
+ },
+ labels: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ },
+ repository: {
+ name: 'Gitlab Test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ description: 'Aut reprehenderit ut est.',
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ },
+ assignees: [
+ {
+ name: 'User1',
+ username: 'user1',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ },
+ ],
+ assignee: {
+ name: 'User1',
+ username: 'user1',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ },
+ labels: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ changes: {
+ updated_by_id: {
+ previous: null,
+ current: 1,
+ },
+ updated_at: {
+ previous: '2017-09-15 16:50:55 UTC',
+ current: '2017-09-15 16:52:00 UTC',
+ },
+ labels: {
+ previous: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ current: [
+ {
+ id: 205,
+ title: 'Platform',
+ color: '#123123',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'Platform related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ },
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/confidential-note-event/index.ts b/packages/backend/src/apps/gitlab/triggers/confidential-note-event/index.ts
new file mode 100644
index 00000000..856f0ad7
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/confidential-note-event/index.ts
@@ -0,0 +1,27 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+// confidential_note_events has the same event data as note_events
+import data from './note_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Confidential comment events',
+ description:
+ 'Confidential comment events (triggered when a new confidential comment is made on commits, merge requests, issues, and code snippets)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events',
+ key: GITLAB_EVENT_TYPE.confidential_note_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.confidential_note_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/confidential-note-event/note_events.ts b/packages/backend/src/apps/gitlab/triggers/confidential-note-event/note_events.ts
new file mode 100644
index 00000000..593188f2
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/confidential-note-event/note_events.ts
@@ -0,0 +1,74 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events
+
+export default {
+ object_kind: 'note',
+ event_type: 'note',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ project_id: 5,
+ project: {
+ id: 5,
+ name: 'Gitlab Test',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/gitlabhq/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ namespace: 'GitlabHQ',
+ visibility_level: 20,
+ path_with_namespace: 'gitlabhq/gitlab-test',
+ default_branch: 'master',
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ },
+ repository: {
+ name: 'Gitlab Test',
+ url: 'http://example.com/gitlab-org/gitlab-test.git',
+ description: 'Aut reprehenderit ut est.',
+ homepage: 'http://example.com/gitlab-org/gitlab-test',
+ },
+ object_attributes: {
+ id: 1243,
+ note: 'This is a commit comment. How does this work?',
+ noteable_type: 'Commit',
+ author_id: 1,
+ created_at: '2015-05-17 18:08:09 UTC',
+ updated_at: '2015-05-17 18:08:09 UTC',
+ project_id: 5,
+ attachment: null,
+ line_code: 'bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1',
+ commit_id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+ noteable_id: null,
+ system: false,
+ st_diff: {
+ diff: '--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n',
+ new_path: 'six',
+ old_path: 'six',
+ a_mode: '0',
+ b_mode: '160000',
+ new_file: true,
+ renamed_file: false,
+ deleted_file: false,
+ },
+ url: 'http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243',
+ },
+ commit: {
+ id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+ message:
+ 'Add submodule\n\nSigned-off-by: Example User \u003cuser@example.com.com\u003e\n',
+ timestamp: '2014-02-27T10:06:20+02:00',
+ url: 'http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+ author: {
+ name: 'Example User',
+ email: 'user@example.com',
+ },
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/deployment-event/deployment_events.ts b/packages/backend/src/apps/gitlab/triggers/deployment-event/deployment_events.ts
new file mode 100644
index 00000000..0c2d2858
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/deployment-event/deployment_events.ts
@@ -0,0 +1,45 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#deployment-events
+
+export default {
+ object_kind: 'deployment',
+ status: 'success',
+ status_changed_at: '2021-04-28 21:50:00 +0200',
+ deployment_id: 15,
+ deployable_id: 796,
+ deployable_url:
+ 'http://10.126.0.2:3000/root/test-deployment-webhooks/-/jobs/796',
+ environment: 'staging',
+ environment_slug: 'staging',
+ environment_external_url: 'https://staging.example.com',
+ project: {
+ id: 30,
+ name: 'test-deployment-webhooks',
+ description: '',
+ web_url: 'http://10.126.0.2:3000/root/test-deployment-webhooks',
+ avatar_url: null,
+ git_ssh_url: 'ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git',
+ git_http_url: 'http://10.126.0.2:3000/root/test-deployment-webhooks.git',
+ namespace: 'Administrator',
+ visibility_level: 0,
+ path_with_namespace: 'root/test-deployment-webhooks',
+ default_branch: 'master',
+ ci_config_path: '',
+ homepage: 'http://10.126.0.2:3000/root/test-deployment-webhooks',
+ url: 'ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git',
+ ssh_url: 'ssh://vlad@10.126.0.2:2222/root/test-deployment-webhooks.git',
+ http_url: 'http://10.126.0.2:3000/root/test-deployment-webhooks.git',
+ },
+ short_sha: '279484c0',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ email: 'admin@example.com',
+ },
+ user_url: 'http://10.126.0.2:3000/root',
+ commit_url:
+ 'http://10.126.0.2:3000/root/test-deployment-webhooks/-/commit/279484c09fbe69ededfced8c1bb6e6d24616b468',
+ commit_title: 'Add new file',
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/deployment-event/index.ts b/packages/backend/src/apps/gitlab/triggers/deployment-event/index.ts
new file mode 100644
index 00000000..48def28b
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/deployment-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './deployment_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Deployment events',
+ description:
+ 'Deployment events (triggered when a deployment starts, succeeds, fails or is canceled)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#deployment-events',
+ key: GITLAB_EVENT_TYPE.deployment_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.deployment_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/feature-flag-event/feature_flag_events.ts b/packages/backend/src/apps/gitlab/triggers/feature-flag-event/feature_flag_events.ts
new file mode 100644
index 00000000..bff89088
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/feature-flag-event/feature_flag_events.ts
@@ -0,0 +1,38 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#feature-flag-events
+
+export default {
+ object_kind: 'feature_flag',
+ project: {
+ id: 1,
+ name: 'Gitlab Test',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/gitlabhq/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ namespace: 'GitlabHQ',
+ visibility_level: 20,
+ path_with_namespace: 'gitlabhq/gitlab-test',
+ default_branch: 'master',
+ ci_config_path: null,
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ },
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ email: 'admin@example.com',
+ },
+ user_url: 'http://example.com/root',
+ object_attributes: {
+ id: 6,
+ name: 'test-feature-flag',
+ description: 'test-feature-flag-description',
+ active: true,
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/feature-flag-event/index.ts b/packages/backend/src/apps/gitlab/triggers/feature-flag-event/index.ts
new file mode 100644
index 00000000..a9cabbcd
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/feature-flag-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './feature_flag_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Feature flag events',
+ description:
+ 'Feature flag events (triggered when a feature flag is turned on or off)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#feature-flag-events',
+ key: GITLAB_EVENT_TYPE.feature_flag_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.feature_flag_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/index.ts b/packages/backend/src/apps/gitlab/triggers/index.ts
new file mode 100644
index 00000000..f8621d3b
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/index.ts
@@ -0,0 +1,29 @@
+import confidentialIssueEvent from './confidential-issue-event';
+import confidentialNoteEvent from './confidential-note-event';
+import deploymentEvent from './deployment-event';
+import featureFlagEvent from './feature-flag-event';
+import issueEvent from './issue-event';
+import jobEvent from './job-event';
+import mergeRequestEvent from './merge-request-event';
+import noteEvent from './note-event';
+import pipelineEvent from './pipeline-event';
+import pushEvent from './push-event';
+import releaseEvent from './release-event';
+import tagPushEvent from './tag-push-event';
+import wikiPageEvent from './wiki-page-event';
+
+export default [
+ confidentialIssueEvent,
+ confidentialNoteEvent,
+ deploymentEvent,
+ featureFlagEvent,
+ issueEvent,
+ jobEvent,
+ mergeRequestEvent,
+ noteEvent,
+ pipelineEvent,
+ pushEvent,
+ releaseEvent,
+ tagPushEvent,
+ wikiPageEvent,
+];
diff --git a/packages/backend/src/apps/gitlab/triggers/issue-event/index.ts b/packages/backend/src/apps/gitlab/triggers/issue-event/index.ts
new file mode 100644
index 00000000..b52f92cb
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/issue-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './issues_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Issue events',
+ description:
+ 'Issue events (triggered when a new issue is created or an existing issue is updated, closed, or reopened)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events',
+ key: GITLAB_EVENT_TYPE.issues_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.issues_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/issue-event/issues_events.ts b/packages/backend/src/apps/gitlab/triggers/issue-event/issues_events.ts
new file mode 100644
index 00000000..75a243b3
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/issue-event/issues_events.ts
@@ -0,0 +1,159 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#issue-events
+
+export default {
+ object_kind: 'issue',
+ event_type: 'issue',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ project: {
+ id: 1,
+ name: 'Gitlab Test',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/gitlabhq/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ namespace: 'GitlabHQ',
+ visibility_level: 20,
+ path_with_namespace: 'gitlabhq/gitlab-test',
+ default_branch: 'master',
+ ci_config_path: null,
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ },
+ object_attributes: {
+ id: 301,
+ title: 'New API: create/update/delete file',
+ assignee_ids: [51],
+ assignee_id: 51,
+ author_id: 51,
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ updated_by_id: 1,
+ last_edited_at: null,
+ last_edited_by_id: null,
+ relative_position: 0,
+ description: 'Create new API for manipulations with repository',
+ milestone_id: null,
+ state_id: 1,
+ confidential: false,
+ discussion_locked: true,
+ due_date: null,
+ moved_to_id: null,
+ duplicated_to_id: null,
+ time_estimate: 0,
+ total_time_spent: 0,
+ time_change: 0,
+ human_total_time_spent: null,
+ human_time_estimate: null,
+ human_time_change: null,
+ weight: null,
+ iid: 23,
+ url: 'http://example.com/diaspora/issues/23',
+ state: 'opened',
+ action: 'open',
+ severity: 'high',
+ escalation_status: 'triggered',
+ escalation_policy: {
+ id: 18,
+ name: 'Engineering On-call',
+ },
+ labels: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ },
+ repository: {
+ name: 'Gitlab Test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ description: 'Aut reprehenderit ut est.',
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ },
+ assignees: [
+ {
+ name: 'User1',
+ username: 'user1',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ },
+ ],
+ assignee: {
+ name: 'User1',
+ username: 'user1',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ },
+ labels: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ changes: {
+ updated_by_id: {
+ previous: null,
+ current: 1,
+ },
+ updated_at: {
+ previous: '2017-09-15 16:50:55 UTC',
+ current: '2017-09-15 16:52:00 UTC',
+ },
+ labels: {
+ previous: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ current: [
+ {
+ id: 205,
+ title: 'Platform',
+ color: '#123123',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'Platform related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ },
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/job-event/index.ts b/packages/backend/src/apps/gitlab/triggers/job-event/index.ts
new file mode 100644
index 00000000..9eb7824b
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/job-event/index.ts
@@ -0,0 +1,25 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './job_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Job events',
+ description: 'Job events (triggered when the status of a job changes)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#job-events',
+ key: GITLAB_EVENT_TYPE.job_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.job_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/job-event/job_events.ts b/packages/backend/src/apps/gitlab/triggers/job-event/job_events.ts
new file mode 100644
index 00000000..bc23866d
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/job-event/job_events.ts
@@ -0,0 +1,60 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#job-events
+
+export default {
+ object_kind: 'build',
+ ref: 'gitlab-script-trigger',
+ tag: false,
+ before_sha: '2293ada6b400935a1378653304eaf6221e0fdb8f',
+ sha: '2293ada6b400935a1378653304eaf6221e0fdb8f',
+ build_id: 1977,
+ build_name: 'test',
+ build_stage: 'test',
+ build_status: 'created',
+ build_created_at: '2021-02-23T02:41:37.886Z',
+ build_started_at: null,
+ build_finished_at: null,
+ build_duration: null,
+ build_queued_duration: 1095.588715, // duration in seconds
+ build_allow_failure: false,
+ build_failure_reason: 'script_failure',
+ retries_count: 2, // the second retry of this job
+ pipeline_id: 2366,
+ project_id: 380,
+ project_name: 'gitlab-org/gitlab-test',
+ user: {
+ id: 3,
+ name: 'User',
+ email: 'user@gitlab.com',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ },
+ commit: {
+ id: 2366,
+ name: 'Build pipeline',
+ sha: '2293ada6b400935a1378653304eaf6221e0fdb8f',
+ message: 'test\n',
+ author_name: 'User',
+ author_email: 'user@gitlab.com',
+ status: 'created',
+ duration: null,
+ started_at: null,
+ finished_at: null,
+ },
+ repository: {
+ name: 'gitlab_test',
+ description: 'Atque in sunt eos similique dolores voluptatem.',
+ homepage: 'http://192.168.64.1:3005/gitlab-org/gitlab-test',
+ git_ssh_url: 'git@192.168.64.1:gitlab-org/gitlab-test.git',
+ git_http_url: 'http://192.168.64.1:3005/gitlab-org/gitlab-test.git',
+ visibility_level: 20,
+ },
+ runner: {
+ active: true,
+ runner_type: 'project_type',
+ is_shared: false,
+ id: 380987,
+ description: 'shared-runners-manager-6.gitlab.com',
+ tags: ['linux', 'docker'],
+ },
+ environment: null,
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/lib.ts b/packages/backend/src/apps/gitlab/triggers/lib.ts
new file mode 100644
index 00000000..6b1a5ede
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/lib.ts
@@ -0,0 +1,89 @@
+import { IGlobalVariable, IJSONObject } from '@automatisch/types';
+import Crypto from 'crypto';
+import { GITLAB_EVENT_TYPE } from './types';
+import appConfig from '../../../config/app';
+
+export const projectArgumentDescriptor = {
+ label: 'Project',
+ key: 'projectId',
+ type: 'dropdown' as const,
+ required: true,
+ description: 'Pick a project to receive events from',
+ variables: false,
+ source: {
+ type: 'query',
+ name: 'getDynamicData',
+ arguments: [
+ {
+ name: 'key',
+ value: 'listProjects',
+ },
+ ],
+ },
+};
+
+export const getTestRunFn =
+ (eventData: IJSONObject) => ($: IGlobalVariable) => {
+ /*
+ Not fetching actual events from gitlab and using static event data from documentation
+ as there is no way to filter out events of one category using gitlab event types,
+ filtering is very limited and uses different grouping than what is applicable when creating a webhook.
+
+ ref:
+ - https://docs.gitlab.com/ee/api/events.html#target-types
+ - https://docs.gitlab.com/ee/api/projects.html#add-project-hook
+ */
+
+ if (!eventData) {
+ return;
+ }
+
+ const dataItem = {
+ raw: eventData,
+ meta: {
+ // there is no distinct id on gitlab event object thus creating it
+ internalId: Crypto.randomUUID(),
+ },
+ };
+
+ $.pushTriggerItem(dataItem);
+
+ return Promise.resolve();
+ };
+
+export const getRegisterHookFn =
+ (eventType: GITLAB_EVENT_TYPE) => async ($: IGlobalVariable) => {
+ // ref: https://docs.gitlab.com/ee/api/projects.html#add-project-hook
+
+ const subscriptionPayload = {
+ url: $.webhookUrl,
+ token: appConfig.webhookSecretKey,
+ enable_ssl_verification: true,
+ [eventType]: true,
+ };
+
+ if (
+ ['wildcard', 'regex'].includes(
+ $.step.parameters.branch_filter_strategy as string
+ )
+ ) {
+ subscriptionPayload.branch_filter_strategy = $.step.parameters
+ .branch_filter_strategy as string;
+ subscriptionPayload.push_events_branch_filter = $.step.parameters
+ .push_events_branch_filter as string;
+ }
+
+ const { data } = await $.http.post(
+ `/api/v4/projects/${$.step.parameters.projectId}/hooks`,
+ subscriptionPayload
+ );
+
+ await $.flow.setRemoteWebhookId(`${data.id}`);
+ };
+
+export const unregisterHook = async ($: IGlobalVariable) => {
+ // ref: https://docs.gitlab.com/ee/api/projects.html#delete-project-hook
+ await $.http.delete(
+ `/api/v4/projects/${$.step.parameters.projectId}/hooks/${$.flow.remoteWebhookId}`
+ );
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/merge-request-event/index.ts b/packages/backend/src/apps/gitlab/triggers/merge-request-event/index.ts
new file mode 100644
index 00000000..fc06c098
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/merge-request-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './merge_requests_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Merge request events',
+ description:
+ 'Merge request events (triggered when merge request is created, updated, or closed)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events',
+ key: GITLAB_EVENT_TYPE.merge_requests_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.merge_requests_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/merge-request-event/merge_requests_events.ts b/packages/backend/src/apps/gitlab/triggers/merge-request-event/merge_requests_events.ts
new file mode 100644
index 00000000..e0f3f48f
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/merge-request-event/merge_requests_events.ts
@@ -0,0 +1,208 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#merge-request-events
+
+export default {
+ object_kind: 'merge_request',
+ event_type: 'merge_request',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ project: {
+ id: 1,
+ name: 'Gitlab Test',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/gitlabhq/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ namespace: 'GitlabHQ',
+ visibility_level: 20,
+ path_with_namespace: 'gitlabhq/gitlab-test',
+ default_branch: 'master',
+ ci_config_path: '',
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ },
+ repository: {
+ name: 'Gitlab Test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ description: 'Aut reprehenderit ut est.',
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ },
+ object_attributes: {
+ id: 99,
+ iid: 1,
+ target_branch: 'master',
+ source_branch: 'ms-viewport',
+ source_project_id: 14,
+ author_id: 51,
+ assignee_ids: [6],
+ assignee_id: 6,
+ reviewer_ids: [6],
+ title: 'MS-Viewport',
+ created_at: '2013-12-03T17:23:34Z',
+ updated_at: '2013-12-03T17:23:34Z',
+ last_edited_at: '2013-12-03T17:23:34Z',
+ last_edited_by_id: 1,
+ milestone_id: null,
+ state_id: 1,
+ state: 'opened',
+ blocking_discussions_resolved: true,
+ work_in_progress: false,
+ first_contribution: true,
+ merge_status: 'unchecked',
+ target_project_id: 14,
+ description: '',
+ total_time_spent: 1800,
+ time_change: 30,
+ human_total_time_spent: '30m',
+ human_time_change: '30s',
+ human_time_estimate: '30m',
+ url: 'http://example.com/diaspora/merge_requests/1',
+ source: {
+ name: 'Awesome Project',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/awesome_space/awesome_project',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:awesome_space/awesome_project.git',
+ git_http_url: 'http://example.com/awesome_space/awesome_project.git',
+ namespace: 'Awesome Space',
+ visibility_level: 20,
+ path_with_namespace: 'awesome_space/awesome_project',
+ default_branch: 'master',
+ homepage: 'http://example.com/awesome_space/awesome_project',
+ url: 'http://example.com/awesome_space/awesome_project.git',
+ ssh_url: 'git@example.com:awesome_space/awesome_project.git',
+ http_url: 'http://example.com/awesome_space/awesome_project.git',
+ },
+ target: {
+ name: 'Awesome Project',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/awesome_space/awesome_project',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:awesome_space/awesome_project.git',
+ git_http_url: 'http://example.com/awesome_space/awesome_project.git',
+ namespace: 'Awesome Space',
+ visibility_level: 20,
+ path_with_namespace: 'awesome_space/awesome_project',
+ default_branch: 'master',
+ homepage: 'http://example.com/awesome_space/awesome_project',
+ url: 'http://example.com/awesome_space/awesome_project.git',
+ ssh_url: 'git@example.com:awesome_space/awesome_project.git',
+ http_url: 'http://example.com/awesome_space/awesome_project.git',
+ },
+ last_commit: {
+ id: 'da1560886d4f094c3e6c9ef40349f7d38b5d27d7',
+ message: 'fixed readme',
+ title: 'Update file README.md',
+ timestamp: '2012-01-03T23:36:29+02:00',
+ url: 'http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7',
+ author: {
+ name: 'GitLab dev user',
+ email: 'gitlabdev@dv6700.(none)',
+ },
+ },
+ labels: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ action: 'open',
+ detailed_merge_status: 'mergeable',
+ },
+ labels: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ changes: {
+ updated_by_id: {
+ previous: null,
+ current: 1,
+ },
+ updated_at: {
+ previous: '2017-09-15 16:50:55 UTC',
+ current: '2017-09-15 16:52:00 UTC',
+ },
+ labels: {
+ previous: [
+ {
+ id: 206,
+ title: 'API',
+ color: '#ffffff',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'API related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ current: [
+ {
+ id: 205,
+ title: 'Platform',
+ color: '#123123',
+ project_id: 14,
+ created_at: '2013-12-03T17:15:43Z',
+ updated_at: '2013-12-03T17:15:43Z',
+ template: false,
+ description: 'Platform related issues',
+ type: 'ProjectLabel',
+ group_id: 41,
+ },
+ ],
+ },
+ last_edited_at: {
+ previous: null,
+ current: '2023-03-15 00:00:10 UTC',
+ },
+ last_edited_by_id: {
+ previous: null,
+ current: 3278533,
+ },
+ },
+ assignees: [
+ {
+ id: 6,
+ name: 'User1',
+ username: 'user1',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ },
+ ],
+ reviewers: [
+ {
+ id: 6,
+ name: 'User1',
+ username: 'user1',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ },
+ ],
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/note-event/index.ts b/packages/backend/src/apps/gitlab/triggers/note-event/index.ts
new file mode 100644
index 00000000..177231cc
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/note-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './note_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Comment events',
+ description:
+ 'Comment events (triggered when a new comment is made on commits, merge requests, issues, and code snippets)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events',
+ key: GITLAB_EVENT_TYPE.note_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.note_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/note-event/note_events.ts b/packages/backend/src/apps/gitlab/triggers/note-event/note_events.ts
new file mode 100644
index 00000000..593188f2
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/note-event/note_events.ts
@@ -0,0 +1,74 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#comment-events
+
+export default {
+ object_kind: 'note',
+ event_type: 'note',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ project_id: 5,
+ project: {
+ id: 5,
+ name: 'Gitlab Test',
+ description: 'Aut reprehenderit ut est.',
+ web_url: 'http://example.com/gitlabhq/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ git_http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ namespace: 'GitlabHQ',
+ visibility_level: 20,
+ path_with_namespace: 'gitlabhq/gitlab-test',
+ default_branch: 'master',
+ homepage: 'http://example.com/gitlabhq/gitlab-test',
+ url: 'http://example.com/gitlabhq/gitlab-test.git',
+ ssh_url: 'git@example.com:gitlabhq/gitlab-test.git',
+ http_url: 'http://example.com/gitlabhq/gitlab-test.git',
+ },
+ repository: {
+ name: 'Gitlab Test',
+ url: 'http://example.com/gitlab-org/gitlab-test.git',
+ description: 'Aut reprehenderit ut est.',
+ homepage: 'http://example.com/gitlab-org/gitlab-test',
+ },
+ object_attributes: {
+ id: 1243,
+ note: 'This is a commit comment. How does this work?',
+ noteable_type: 'Commit',
+ author_id: 1,
+ created_at: '2015-05-17 18:08:09 UTC',
+ updated_at: '2015-05-17 18:08:09 UTC',
+ project_id: 5,
+ attachment: null,
+ line_code: 'bec9703f7a456cd2b4ab5fb3220ae016e3e394e3_0_1',
+ commit_id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+ noteable_id: null,
+ system: false,
+ st_diff: {
+ diff: '--- /dev/null\n+++ b/six\n@@ -0,0 +1 @@\n+Subproject commit 409f37c4f05865e4fb208c771485f211a22c4c2d\n',
+ new_path: 'six',
+ old_path: 'six',
+ a_mode: '0',
+ b_mode: '160000',
+ new_file: true,
+ renamed_file: false,
+ deleted_file: false,
+ },
+ url: 'http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660#note_1243',
+ },
+ commit: {
+ id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+ message:
+ 'Add submodule\n\nSigned-off-by: Example User \u003cuser@example.com.com\u003e\n',
+ timestamp: '2014-02-27T10:06:20+02:00',
+ url: 'http://example.com/gitlab-org/gitlab-test/commit/cfe32cf61b73a0d5e9f13e774abde7ff789b1660',
+ author: {
+ name: 'Example User',
+ email: 'user@example.com',
+ },
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/pipeline-event/index.ts b/packages/backend/src/apps/gitlab/triggers/pipeline-event/index.ts
new file mode 100644
index 00000000..e5d7cadc
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/pipeline-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './pipeline_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Pipeline events',
+ description:
+ 'Pipeline events (triggered when the status of a pipeline changes)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#pipeline-events',
+ key: GITLAB_EVENT_TYPE.pipeline_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.pipeline_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/pipeline-event/pipeline_events.ts b/packages/backend/src/apps/gitlab/triggers/pipeline-event/pipeline_events.ts
new file mode 100644
index 00000000..4a29b41b
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/pipeline-event/pipeline_events.ts
@@ -0,0 +1,254 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#pipeline-events
+
+export default {
+ object_kind: 'pipeline',
+ object_attributes: {
+ id: 31,
+ iid: 3,
+ ref: 'master',
+ tag: false,
+ sha: 'bcbb5ec396a2c0f828686f14fac9b80b780504f2',
+ before_sha: 'bcbb5ec396a2c0f828686f14fac9b80b780504f2',
+ source: 'merge_request_event',
+ status: 'success',
+ stages: ['build', 'test', 'deploy'],
+ created_at: '2016-08-12 15:23:28 UTC',
+ finished_at: '2016-08-12 15:26:29 UTC',
+ duration: 63,
+ variables: [
+ {
+ key: 'NESTOR_PROD_ENVIRONMENT',
+ value: 'us-west-1',
+ },
+ ],
+ },
+ merge_request: {
+ id: 1,
+ iid: 1,
+ title: 'Test',
+ source_branch: 'test',
+ source_project_id: 1,
+ target_branch: 'master',
+ target_project_id: 1,
+ state: 'opened',
+ merge_status: 'can_be_merged',
+ detailed_merge_status: 'mergeable',
+ url: 'http://192.168.64.1:3005/gitlab-org/gitlab-test/merge_requests/1',
+ },
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ email: 'user_email@gitlab.com',
+ },
+ project: {
+ id: 1,
+ name: 'Gitlab Test',
+ description: 'Atque in sunt eos similique dolores voluptatem.',
+ web_url: 'http://192.168.64.1:3005/gitlab-org/gitlab-test',
+ avatar_url: null,
+ git_ssh_url: 'git@192.168.64.1:gitlab-org/gitlab-test.git',
+ git_http_url: 'http://192.168.64.1:3005/gitlab-org/gitlab-test.git',
+ namespace: 'Gitlab Org',
+ visibility_level: 20,
+ path_with_namespace: 'gitlab-org/gitlab-test',
+ default_branch: 'master',
+ },
+ commit: {
+ id: 'bcbb5ec396a2c0f828686f14fac9b80b780504f2',
+ message: 'test\n',
+ timestamp: '2016-08-12T17:23:21+02:00',
+ url: 'http://example.com/gitlab-org/gitlab-test/commit/bcbb5ec396a2c0f828686f14fac9b80b780504f2',
+ author: {
+ name: 'User',
+ email: 'user@gitlab.com',
+ },
+ },
+ source_pipeline: {
+ project: {
+ id: 41,
+ web_url: 'https://gitlab.example.com/gitlab-org/upstream-project',
+ path_with_namespace: 'gitlab-org/upstream-project',
+ },
+ pipeline_id: 30,
+ job_id: 3401,
+ },
+ builds: [
+ {
+ id: 380,
+ stage: 'deploy',
+ name: 'production',
+ status: 'skipped',
+ created_at: '2016-08-12 15:23:28 UTC',
+ started_at: null,
+ finished_at: null,
+ duration: null,
+ queued_duration: null,
+ failure_reason: null,
+ when: 'manual',
+ manual: true,
+ allow_failure: false,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ runner: null,
+ artifacts_file: {
+ filename: null,
+ size: null,
+ },
+ environment: {
+ name: 'production',
+ action: 'start',
+ deployment_tier: 'production',
+ },
+ },
+ {
+ id: 377,
+ stage: 'test',
+ name: 'test-image',
+ status: 'success',
+ 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,
+ failure_reason: null,
+ when: 'on_success',
+ manual: false,
+ allow_failure: false,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ runner: {
+ id: 380987,
+ description: 'shared-runners-manager-6.gitlab.com',
+ active: true,
+ runner_type: 'instance_type',
+ is_shared: true,
+ tags: ['linux', 'docker', 'shared-runner'],
+ },
+ artifacts_file: {
+ filename: null,
+ size: null,
+ },
+ environment: null,
+ },
+ {
+ id: 378,
+ stage: 'test',
+ name: 'test-build',
+ status: 'failed',
+ 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,
+ failure_reason: 'script_failure',
+ when: 'on_success',
+ manual: false,
+ allow_failure: false,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ runner: {
+ id: 380987,
+ description: 'shared-runners-manager-6.gitlab.com',
+ active: true,
+ runner_type: 'instance_type',
+ is_shared: true,
+ tags: ['linux', 'docker'],
+ },
+ artifacts_file: {
+ filename: null,
+ size: null,
+ },
+ environment: null,
+ },
+ {
+ id: 376,
+ stage: 'build',
+ name: 'build-image',
+ status: 'success',
+ 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,
+ failure_reason: null,
+ when: 'on_success',
+ manual: false,
+ allow_failure: false,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ runner: {
+ id: 380987,
+ description: 'shared-runners-manager-6.gitlab.com',
+ active: true,
+ runner_type: 'instance_type',
+ is_shared: true,
+ tags: ['linux', 'docker'],
+ },
+ artifacts_file: {
+ filename: null,
+ size: null,
+ },
+ environment: null,
+ },
+ {
+ id: 379,
+ stage: 'deploy',
+ name: 'staging',
+ status: 'created',
+ created_at: '2016-08-12 15:23:28 UTC',
+ started_at: null,
+ finished_at: null,
+ duration: null,
+ queued_duration: null,
+ failure_reason: null,
+ when: 'on_success',
+ manual: false,
+ allow_failure: false,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ runner: null,
+ artifacts_file: {
+ filename: null,
+ size: null,
+ },
+ environment: {
+ name: 'staging',
+ action: 'start',
+ deployment_tier: 'staging',
+ },
+ },
+ ],
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/push-event/index.ts b/packages/backend/src/apps/gitlab/triggers/push-event/index.ts
new file mode 100644
index 00000000..c2916fb3
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/push-event/index.ts
@@ -0,0 +1,62 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './push_events';
+
+export const branchFilterStrategyArgumentDescriptor = {
+ label: 'What type of filter to use?',
+ key: 'branch_filter_strategy',
+ type: 'dropdown' as const,
+ description: 'Defaults to including all branches',
+ required: true,
+ variables: false,
+ value: 'all_branches',
+ options: [
+ {
+ label: 'All branches',
+ value: 'all_branches',
+ },
+ {
+ label: 'Wildcard pattern (ex: *-stable)',
+ value: 'wildcard',
+ },
+ {
+ label: 'Regular expression (ex: ^(feature|hotfix)/)',
+ value: 'regex',
+ },
+ ],
+};
+
+export const pushEventsBranchFilterArgumentDescriptor = {
+ label: 'Filter value',
+ key: 'push_events_branch_filter',
+ description: 'Leave empty when using "all branches"',
+ type: 'string' as const,
+ required: false,
+ variables: false,
+};
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Push events',
+ description: 'Push events (triggered when you push to the repository)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#push-events',
+ key: GITLAB_EVENT_TYPE.push_events,
+ type: 'webhook',
+ arguments: [
+ projectArgumentDescriptor,
+ branchFilterStrategyArgumentDescriptor,
+ pushEventsBranchFilterArgumentDescriptor,
+ ],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.push_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/push-event/push_events.ts b/packages/backend/src/apps/gitlab/triggers/push-event/push_events.ts
new file mode 100644
index 00000000..2951c153
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/push-event/push_events.ts
@@ -0,0 +1,75 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#push-events
+
+export default {
+ object_kind: 'push',
+ event_name: 'push',
+ before: '95790bf891e76fee5e1747ab589903a6a1f80f22',
+ after: 'da1560886d4f094c3e6c9ef40349f7d38b5d27d7',
+ ref: 'refs/heads/master',
+ checkout_sha: 'da1560886d4f094c3e6c9ef40349f7d38b5d27d7',
+ user_id: 4,
+ user_name: 'John Smith',
+ user_username: 'jsmith',
+ user_email: 'john@example.com',
+ user_avatar:
+ 'https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80',
+ project_id: 15,
+ project: {
+ id: 15,
+ name: 'Diaspora',
+ description: '',
+ web_url: 'http://example.com/mike/diaspora',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:mike/diaspora.git',
+ git_http_url: 'http://example.com/mike/diaspora.git',
+ namespace: 'Mike',
+ visibility_level: 0,
+ path_with_namespace: 'mike/diaspora',
+ default_branch: 'master',
+ homepage: 'http://example.com/mike/diaspora',
+ url: 'git@example.com:mike/diaspora.git',
+ ssh_url: 'git@example.com:mike/diaspora.git',
+ http_url: 'http://example.com/mike/diaspora.git',
+ },
+ repository: {
+ name: 'Diaspora',
+ url: 'git@example.com:mike/diaspora.git',
+ description: '',
+ homepage: 'http://example.com/mike/diaspora',
+ git_http_url: 'http://example.com/mike/diaspora.git',
+ git_ssh_url: 'git@example.com:mike/diaspora.git',
+ visibility_level: 0,
+ },
+ commits: [
+ {
+ id: 'b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327',
+ message:
+ 'Update Catalan translation to e38cb41.\n\nSee https://gitlab.com/gitlab-org/gitlab for more information',
+ title: 'Update Catalan translation to e38cb41.',
+ timestamp: '2011-12-12T14:27:31+02:00',
+ url: 'http://example.com/mike/diaspora/commit/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327',
+ author: {
+ name: 'Jordi Mallach',
+ email: 'jordi@softcatala.org',
+ },
+ added: ['CHANGELOG'],
+ modified: ['app/controller/application.rb'],
+ removed: [],
+ },
+ {
+ id: 'da1560886d4f094c3e6c9ef40349f7d38b5d27d7',
+ message: 'fixed readme',
+ title: 'fixed readme',
+ timestamp: '2012-01-03T23:36:29+02:00',
+ url: 'http://example.com/mike/diaspora/commit/da1560886d4f094c3e6c9ef40349f7d38b5d27d7',
+ author: {
+ name: 'GitLab dev user',
+ email: 'gitlabdev@dv6700.(none)',
+ },
+ added: ['CHANGELOG'],
+ modified: ['app/controller/application.rb'],
+ removed: [],
+ },
+ ],
+ total_commits_count: 4,
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/release-event/index.ts b/packages/backend/src/apps/gitlab/triggers/release-event/index.ts
new file mode 100644
index 00000000..565dae14
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/release-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './releases_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Release events',
+ description:
+ 'Release events (triggered when a release is created or updated)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#release-events',
+ key: GITLAB_EVENT_TYPE.releases_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.releases_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/release-event/releases_events.ts b/packages/backend/src/apps/gitlab/triggers/release-event/releases_events.ts
new file mode 100644
index 00000000..90c758b3
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/release-event/releases_events.ts
@@ -0,0 +1,72 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#release-events
+
+export default {
+ object_kind: 'release',
+ id: 1,
+ created_at: '2020-11-02 12:55:12 UTC',
+ description: 'v1.1 has been released',
+ name: 'v1.1',
+ released_at: '2020-11-02 12:55:12 UTC',
+ tag: 'v1.1',
+ project: {
+ id: 2,
+ name: 'release-webhook-example',
+ description: '',
+ web_url: 'https://example.com/gitlab-org/release-webhook-example',
+ avatar_url: null,
+ git_ssh_url: 'ssh://git@example.com/gitlab-org/release-webhook-example.git',
+ git_http_url: 'https://example.com/gitlab-org/release-webhook-example.git',
+ namespace: 'Gitlab',
+ visibility_level: 0,
+ path_with_namespace: 'gitlab-org/release-webhook-example',
+ default_branch: 'master',
+ ci_config_path: null,
+ homepage: 'https://example.com/gitlab-org/release-webhook-example',
+ url: 'ssh://git@example.com/gitlab-org/release-webhook-example.git',
+ ssh_url: 'ssh://git@example.com/gitlab-org/release-webhook-example.git',
+ http_url: 'https://example.com/gitlab-org/release-webhook-example.git',
+ },
+ url: 'https://example.com/gitlab-org/release-webhook-example/-/releases/v1.1',
+ action: 'create',
+ assets: {
+ count: 5,
+ links: [
+ {
+ id: 1,
+ external: true, // deprecated in GitLab 15.9, will be removed in GitLab 16.0.
+ link_type: 'other',
+ name: 'Changelog',
+ url: 'https://example.net/changelog',
+ },
+ ],
+ sources: [
+ {
+ format: 'zip',
+ url: 'https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.zip',
+ },
+ {
+ format: 'tar.gz',
+ url: 'https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.gz',
+ },
+ {
+ format: 'tar.bz2',
+ url: 'https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar.bz2',
+ },
+ {
+ format: 'tar',
+ url: 'https://example.com/gitlab-org/release-webhook-example/-/archive/v1.1/release-webhook-example-v1.1.tar',
+ },
+ ],
+ },
+ commit: {
+ id: 'ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8',
+ message: 'Release v1.1',
+ title: 'Release v1.1',
+ timestamp: '2020-10-31T14:58:32+11:00',
+ url: 'https://example.com/gitlab-org/release-webhook-example/-/commit/ee0a3fb31ac16e11b9dbb596ad16d4af654d08f8',
+ author: {
+ name: 'Example User',
+ email: 'user@example.com',
+ },
+ },
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/tag-push-event/index.ts b/packages/backend/src/apps/gitlab/triggers/tag-push-event/index.ts
new file mode 100644
index 00000000..6b4525be
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/tag-push-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './tag_push_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Tag events',
+ description:
+ 'Tag events (triggered when you create or delete tags in the repository)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#tag-events',
+ key: GITLAB_EVENT_TYPE.tag_push_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.tag_push_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/tag-push-event/tag_push_events.ts b/packages/backend/src/apps/gitlab/triggers/tag-push-event/tag_push_events.ts
new file mode 100644
index 00000000..8dd94cfc
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/tag-push-event/tag_push_events.ts
@@ -0,0 +1,43 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#tag-events
+
+export default {
+ object_kind: 'tag_push',
+ event_name: 'tag_push',
+ before: '0000000000000000000000000000000000000000',
+ after: '82b3d5ae55f7080f1e6022629cdb57bfae7cccc7',
+ ref: 'refs/tags/v1.0.0',
+ checkout_sha: '82b3d5ae55f7080f1e6022629cdb57bfae7cccc7',
+ user_id: 1,
+ user_name: 'John Smith',
+ user_avatar:
+ 'https://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=8://s.gravatar.com/avatar/d4c74594d841139328695756648b6bd6?s=80',
+ project_id: 1,
+ project: {
+ id: 1,
+ name: 'Example',
+ description: '',
+ web_url: 'http://example.com/jsmith/example',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:jsmith/example.git',
+ git_http_url: 'http://example.com/jsmith/example.git',
+ namespace: 'Jsmith',
+ visibility_level: 0,
+ path_with_namespace: 'jsmith/example',
+ default_branch: 'master',
+ homepage: 'http://example.com/jsmith/example',
+ url: 'git@example.com:jsmith/example.git',
+ ssh_url: 'git@example.com:jsmith/example.git',
+ http_url: 'http://example.com/jsmith/example.git',
+ },
+ repository: {
+ name: 'Example',
+ url: 'ssh://git@example.com/jsmith/example.git',
+ description: '',
+ homepage: 'http://example.com/jsmith/example',
+ git_http_url: 'http://example.com/jsmith/example.git',
+ git_ssh_url: 'git@example.com:jsmith/example.git',
+ visibility_level: 0,
+ },
+ commits: [],
+ total_commits_count: 0,
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/types.ts b/packages/backend/src/apps/gitlab/triggers/types.ts
new file mode 100644
index 00000000..38456fd0
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/types.ts
@@ -0,0 +1,24 @@
+export enum GITLAB_EVENT_TYPE {
+ // ref: https://docs.gitlab.com/ee/api/projects.html#add-project-hook
+ confidential_issues_events = 'confidential_issues_events',
+ confidential_note_events = 'confidential_note_events',
+ deployment_events = 'deployment_events',
+ feature_flag_events = 'feature_flag_events',
+ issues_events = 'issues_events',
+ job_events = 'job_events',
+ merge_requests_events = 'merge_requests_events',
+ note_events = 'note_events',
+ pipeline_events = 'pipeline_events',
+ push_events = 'push_events',
+ releases_events = 'releases_events',
+ tag_push_events = 'tag_push_events',
+ wiki_page_events = 'wiki_page_events',
+}
+
+export type EventDescriptor = {
+ name: string;
+ description: string;
+ info?: string;
+ type: GITLAB_EVENT_TYPE;
+ data: any;
+};
diff --git a/packages/backend/src/apps/gitlab/triggers/wiki-page-event/index.ts b/packages/backend/src/apps/gitlab/triggers/wiki-page-event/index.ts
new file mode 100644
index 00000000..d7d0b4da
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/wiki-page-event/index.ts
@@ -0,0 +1,26 @@
+import { IRawTrigger } from '@automatisch/types';
+import defineTrigger from '../../../../helpers/define-trigger';
+import { GITLAB_EVENT_TYPE } from '../types';
+import {
+ getRegisterHookFn,
+ getTestRunFn,
+ projectArgumentDescriptor,
+ unregisterHook,
+} from '../lib';
+
+import data from './wiki_page_events';
+
+export const triggerDescriptor: IRawTrigger = {
+ name: 'Wiki page events',
+ description:
+ 'Wiki page events (triggered when a wiki page is created, updated, or deleted)',
+ // info: 'https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#wiki-page-events',
+ key: GITLAB_EVENT_TYPE.wiki_page_events,
+ type: 'webhook',
+ arguments: [projectArgumentDescriptor],
+ testRun: getTestRunFn(data),
+ registerHook: getRegisterHookFn(GITLAB_EVENT_TYPE.wiki_page_events),
+ unregisterHook,
+};
+
+export default defineTrigger(triggerDescriptor);
diff --git a/packages/backend/src/apps/gitlab/triggers/wiki-page-event/wiki_page_events.ts b/packages/backend/src/apps/gitlab/triggers/wiki-page-event/wiki_page_events.ts
new file mode 100644
index 00000000..3058eea2
--- /dev/null
+++ b/packages/backend/src/apps/gitlab/triggers/wiki-page-event/wiki_page_events.ts
@@ -0,0 +1,48 @@
+// https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#wiki-page-events
+
+export default {
+ object_kind: 'wiki_page',
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ avatar_url:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ email: 'admin@example.com',
+ },
+ project: {
+ id: 1,
+ name: 'awesome-project',
+ description: 'This is awesome',
+ web_url: 'http://example.com/root/awesome-project',
+ avatar_url: null,
+ git_ssh_url: 'git@example.com:root/awesome-project.git',
+ git_http_url: 'http://example.com/root/awesome-project.git',
+ namespace: 'root',
+ visibility_level: 0,
+ path_with_namespace: 'root/awesome-project',
+ default_branch: 'master',
+ homepage: 'http://example.com/root/awesome-project',
+ url: 'git@example.com:root/awesome-project.git',
+ ssh_url: 'git@example.com:root/awesome-project.git',
+ http_url: 'http://example.com/root/awesome-project.git',
+ },
+ wiki: {
+ web_url: 'http://example.com/root/awesome-project/-/wikis/home',
+ git_ssh_url: 'git@example.com:root/awesome-project.wiki.git',
+ git_http_url: 'http://example.com/root/awesome-project.wiki.git',
+ path_with_namespace: 'root/awesome-project.wiki',
+ default_branch: 'master',
+ },
+ object_attributes: {
+ title: 'Awesome',
+ content: 'awesome content goes here',
+ format: 'markdown',
+ message: 'adding an awesome page to the wiki',
+ slug: 'awesome',
+ url: 'http://example.com/root/awesome-project/-/wikis/awesome',
+ action: 'create',
+ diff_url:
+ 'http://example.com/root/awesome-project/-/wikis/home/diff?version_id=78ee4a6705abfbff4f4132c6646dbaae9c8fb6ec',
+ },
+};
diff --git a/packages/types/index.d.ts b/packages/types/index.d.ts
index 1dfcd3c0..2e531bf2 100644
--- a/packages/types/index.d.ts
+++ b/packages/types/index.d.ts
@@ -4,7 +4,13 @@ import type { Request } from 'express';
// Type definitions for automatisch
-export type IJSONValue = string | number | boolean | IJSONObject | IJSONArray;
+export type IJSONValue =
+ | string
+ | number
+ | boolean
+ | null
+ | IJSONObject
+ | IJSONArray;
export type IJSONArray = Array;
export interface IJSONObject {
[x: string]: IJSONValue;
@@ -338,7 +344,7 @@ export type TPaymentPlan = {
name: string;
limit: string;
productId: string;
-}
+};
export type TSubscription = {
status: string;
@@ -354,28 +360,28 @@ export type TSubscription = {
title: string;
action: BillingCardAction;
};
-}
+};
type TBillingCardAction = TBillingTextCardAction | TBillingLinkCardAction;
type TBillingTextCardAction = {
type: 'text';
text: string;
-}
+};
type TBillingLinkCardAction = {
type: 'link';
text: string;
src: string;
-}
+};
type TInvoice = {
- id: number
- amount: number
- currency: string
- payout_date: string
- receipt_url: string
-}
+ id: number;
+ amount: number;
+ currency: string;
+ payout_date: string;
+ receipt_url: string;
+};
declare module 'axios' {
interface AxiosResponse {