Compare commits
33 Commits
v0.7.1
...
new-or-upd
Author | SHA1 | Date | |
---|---|---|---|
![]() |
03b357393e | ||
![]() |
35863ee6e9 | ||
![]() |
0784a2d4d0 | ||
![]() |
75d5c0e356 | ||
![]() |
a2dd6d76a8 | ||
![]() |
bdc6b59857 | ||
![]() |
34e95f1e89 | ||
![]() |
6a92cfc573 | ||
![]() |
9f759d70b6 | ||
![]() |
43e957e8d3 | ||
![]() |
ae316f60e4 | ||
![]() |
1ac423ba56 | ||
![]() |
b43490dd76 | ||
![]() |
f586e81dd1 | ||
![]() |
8a6d8a7d8c | ||
![]() |
45d607f1a0 | ||
![]() |
d84abaa229 | ||
![]() |
3fd1d4d9b3 | ||
![]() |
078b8efb56 | ||
![]() |
5066995f72 | ||
![]() |
577fe3dba8 | ||
![]() |
d96f4999bc | ||
![]() |
6e80ff4eb6 | ||
![]() |
3f8f022d48 | ||
![]() |
93a2e2151e | ||
![]() |
663a1ed9d4 | ||
![]() |
4f46c55c85 | ||
![]() |
9701c98af9 | ||
![]() |
aabf2a1c79 | ||
![]() |
29539b090e | ||
![]() |
1c80677ac3 | ||
![]() |
ad419855e9 | ||
![]() |
30b75943f3 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -125,3 +125,6 @@ dist
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# MacOS finder preferences
|
||||
.DS_store
|
||||
|
@@ -2,7 +2,7 @@ import qs from 'qs';
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Translate Text',
|
||||
name: 'Translate text',
|
||||
key: 'translateText',
|
||||
description: 'Translates text from one language to another.',
|
||||
arguments: [
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Delay For',
|
||||
name: 'Delay for',
|
||||
key: 'delayFor',
|
||||
description:
|
||||
'Delays the execution of the next action by a specified amount of time.',
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Delay Until',
|
||||
name: 'Delay until',
|
||||
key: 'delayUntil',
|
||||
description:
|
||||
'Delays the execution of the next action until a specified date.',
|
||||
|
@@ -20,12 +20,14 @@ export default defineTrigger({
|
||||
],
|
||||
|
||||
async testRun($) {
|
||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: $.lastExecutionStep.dataOut,
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -35,20 +37,15 @@ export default defineTrigger({
|
||||
name: $.flow.id,
|
||||
type: 'POST',
|
||||
url: $.webhookUrl,
|
||||
filters: [$.step.parameters.filters]
|
||||
filters: [$.step.parameters.filters],
|
||||
};
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v2/public/api/webhooks`,
|
||||
payload
|
||||
);
|
||||
const { data } = await $.http.post(`/v2/public/api/webhooks`, payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(data.id);
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(
|
||||
`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`
|
||||
);
|
||||
await $.http.delete(`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
||||
|
2
packages/backend/src/apps/gitlab/assets/favicon.svg
Normal file
2
packages/backend/src/apps/gitlab/assets/favicon.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<!-- https://about.gitlab.com/images/press/logo/svg/gitlab-logo-500.svg -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 380 380"><defs><style>.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style></defs><g id="LOGO"><path class="cls-1" d="M282.83,170.73l-.27-.69-26.14-68.22a6.81,6.81,0,0,0-2.69-3.24,7,7,0,0,0-8,.43,7,7,0,0,0-2.32,3.52l-17.65,54H154.29l-17.65-54A6.86,6.86,0,0,0,134.32,99a7,7,0,0,0-8-.43,6.87,6.87,0,0,0-2.69,3.24L97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82,19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91,40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-2" d="M282.83,170.73l-.27-.69a88.3,88.3,0,0,0-35.15,15.8L190,229.25c19.55,14.79,36.57,27.64,36.57,27.64l40.06-30,.1-.08A48.56,48.56,0,0,0,282.83,170.73Z"/><path class="cls-3" d="M153.43,256.89l19.7,14.91,12,9.06a8.07,8.07,0,0,0,9.76,0l12-9.06,19.7-14.91S209.55,244,190,229.25C170.45,244,153.43,256.89,153.43,256.89Z"/><path class="cls-2" d="M132.58,185.84A88.19,88.19,0,0,0,97.44,170l-.26.69a48.54,48.54,0,0,0,16.1,56.1l.09.07.24.17,39.82,29.82s17-12.85,36.57-27.64Z"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
24
packages/backend/src/apps/gitlab/auth/generate-auth-url.ts
Normal file
24
packages/backend/src/apps/gitlab/auth/generate-auth-url.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
import { URL, URLSearchParams } from 'url';
|
||||
import getBaseUrl from '../common/get-base-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().toString(),
|
||||
});
|
||||
|
||||
const baseUrl = getBaseUrl($);
|
||||
const path = `/oauth/authorize?${searchParams.toString()}`;
|
||||
|
||||
await $.auth.set({
|
||||
url: new URL(path, baseUrl).toString(),
|
||||
});
|
||||
}
|
63
packages/backend/src/apps/gitlab/auth/index.ts
Normal file
63
packages/backend/src/apps/gitlab/auth/index.ts
Normal file
@@ -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: '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: 'instanceUrl',
|
||||
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: '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,
|
||||
};
|
@@ -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;
|
24
packages/backend/src/apps/gitlab/auth/refresh-token.ts
Normal file
24
packages/backend/src/apps/gitlab/auth/refresh-token.ts
Normal file
@@ -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;
|
41
packages/backend/src/apps/gitlab/auth/verify-credentials.ts
Normal file
41
packages/backend/src/apps/gitlab/auth/verify-credentials.ts
Normal file
@@ -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(
|
||||
'/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} @ ${$.auth.data.instanceUrl}`,
|
||||
});
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
11
packages/backend/src/apps/gitlab/common/add-auth-header.ts
Normal file
11
packages/backend/src/apps/gitlab/common/add-auth-header.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const addAuthHeader: TBeforeRequest = ($, requestConfig) => {
|
||||
if ($.auth.data?.accessToken) {
|
||||
requestConfig.headers = requestConfig.headers || {};
|
||||
requestConfig.headers.Authorization = `Bearer ${$.auth.data.accessToken}`;
|
||||
}
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
15
packages/backend/src/apps/gitlab/common/get-base-url.ts
Normal file
15
packages/backend/src/apps/gitlab/common/get-base-url.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
const getBaseUrl = ($: IGlobalVariable): string => {
|
||||
if ($.auth.data.instanceUrl) {
|
||||
return $.auth.data.instanceUrl as string;
|
||||
}
|
||||
|
||||
if ($.app.apiBaseUrl) {
|
||||
return $.app.apiBaseUrl;
|
||||
}
|
||||
|
||||
return $.app.baseUrl;
|
||||
};
|
||||
|
||||
export default getBaseUrl;
|
11
packages/backend/src/apps/gitlab/common/get-current-user.ts
Normal file
11
packages/backend/src/apps/gitlab/common/get-current-user.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
const getCurrentUser = async ($: IGlobalVariable): Promise<IJSONObject> => {
|
||||
// ref: https://docs.gitlab.com/ee/api/users.html#list-current-user
|
||||
|
||||
const response = await $.http.get('/api/v4/user');
|
||||
const currentUser = response.data;
|
||||
return currentUser;
|
||||
};
|
||||
|
||||
export default getCurrentUser;
|
33
packages/backend/src/apps/gitlab/common/paginate-all.ts
Normal file
33
packages/backend/src/apps/gitlab/common/paginate-all.ts
Normal file
@@ -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<AxiosResponse>
|
||||
) {
|
||||
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;
|
||||
}
|
13
packages/backend/src/apps/gitlab/common/set-base-url.ts
Normal file
13
packages/backend/src/apps/gitlab/common/set-base-url.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { TBeforeRequest } from '@automatisch/types';
|
||||
|
||||
const setBaseUrl: TBeforeRequest = ($, requestConfig) => {
|
||||
if ($.auth.data.instanceUrl) {
|
||||
requestConfig.baseURL = $.auth.data.instanceUrl as string;
|
||||
} else if ($.app.apiBaseUrl) {
|
||||
requestConfig.baseURL = $.app.apiBaseUrl as string;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default setBaseUrl;
|
3
packages/backend/src/apps/gitlab/dynamic-data/index.ts
Normal file
3
packages/backend/src/apps/gitlab/dynamic-data/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import listProjects from './list-projects';
|
||||
|
||||
export default [listProjects];
|
@@ -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;
|
||||
},
|
||||
};
|
1
packages/backend/src/apps/gitlab/index.d.ts
vendored
Normal file
1
packages/backend/src/apps/gitlab/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
|
21
packages/backend/src/apps/gitlab/index.ts
Normal file
21
packages/backend/src/apps/gitlab/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import defineApp from '../../helpers/define-app';
|
||||
import addAuthHeader from './common/add-auth-header';
|
||||
import setBaseUrl from './common/set-base-url';
|
||||
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',
|
||||
iconUrl: '{BASE_URL}/apps/gitlab/assets/favicon.svg',
|
||||
authDocUrl: 'https://automatisch.io/docs/apps/gitlab/connection',
|
||||
primaryColor: 'FC6D26',
|
||||
supportsConnections: true,
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
dynamicData,
|
||||
});
|
@@ -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 './issue_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Confidential issue event',
|
||||
description:
|
||||
'Confidential issue event (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);
|
@@ -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,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Confidential comment event',
|
||||
description:
|
||||
'Confidential comment event (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);
|
@@ -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',
|
||||
},
|
||||
},
|
||||
};
|
@@ -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',
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Deployment event',
|
||||
description:
|
||||
'Deployment event (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);
|
@@ -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,
|
||||
},
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Feature flag event',
|
||||
description:
|
||||
'Feature flag event (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);
|
29
packages/backend/src/apps/gitlab/triggers/index.ts
Normal file
29
packages/backend/src/apps/gitlab/triggers/index.ts
Normal file
@@ -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,
|
||||
];
|
@@ -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 './issue_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Issue event',
|
||||
description:
|
||||
'Issue event (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);
|
@@ -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,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
25
packages/backend/src/apps/gitlab/triggers/job-event/index.ts
Normal file
25
packages/backend/src/apps/gitlab/triggers/job-event/index.ts
Normal file
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Job event',
|
||||
description: 'Job event (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);
|
@@ -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,
|
||||
};
|
89
packages/backend/src/apps/gitlab/triggers/lib.ts
Normal file
89
packages/backend/src/apps/gitlab/triggers/lib.ts
Normal file
@@ -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.toString());
|
||||
};
|
||||
|
||||
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}`
|
||||
);
|
||||
};
|
@@ -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_request_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Merge request event',
|
||||
description:
|
||||
'Merge request event (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);
|
@@ -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',
|
||||
},
|
||||
],
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Comment event',
|
||||
description:
|
||||
'Comment event (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);
|
@@ -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',
|
||||
},
|
||||
},
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Pipeline event',
|
||||
description:
|
||||
'Pipeline event (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);
|
@@ -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',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
@@ -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_event';
|
||||
|
||||
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 event',
|
||||
description: 'Push event (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);
|
@@ -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,
|
||||
};
|
@@ -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 './release_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Release event',
|
||||
description: 'Release event (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);
|
@@ -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',
|
||||
},
|
||||
},
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Tag event',
|
||||
description:
|
||||
'Tag event (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);
|
@@ -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,
|
||||
};
|
24
packages/backend/src/apps/gitlab/triggers/types.ts
Normal file
24
packages/backend/src/apps/gitlab/triggers/types.ts
Normal file
@@ -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;
|
||||
};
|
@@ -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_event';
|
||||
|
||||
export const triggerDescriptor: IRawTrigger = {
|
||||
name: 'Wiki page event',
|
||||
description:
|
||||
'Wiki page event (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);
|
@@ -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',
|
||||
},
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
export default {
|
||||
name: 'List Folders',
|
||||
name: 'List folders',
|
||||
key: 'listFolders',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newFilesInFolder from './new-files-in-folder';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Files in Folder',
|
||||
name: 'New files in folder',
|
||||
key: 'newFilesInFolder',
|
||||
pollInterval: 15,
|
||||
description:
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newFiles from './new-files';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Files',
|
||||
name: 'New files',
|
||||
key: 'newFiles',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when any new file is added (inside of any folder).',
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newFolders from './new-folders';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Folders',
|
||||
name: 'New folders',
|
||||
key: 'newFolders',
|
||||
pollInterval: 15,
|
||||
description:
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import updatedFiles from './updated-files';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'Updated Files',
|
||||
name: 'Updated files',
|
||||
key: 'updatedFiles',
|
||||
pollInterval: 15,
|
||||
description:
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newFormResponses from './new-form-responses';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Form Responses',
|
||||
name: 'New form responses',
|
||||
key: 'newFormResponses',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when a new form response is submitted.',
|
||||
|
@@ -0,0 +1,145 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
type TSheetsResponse = {
|
||||
sheets: {
|
||||
properties: {
|
||||
sheetId: string;
|
||||
title: string;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create spreadsheet row',
|
||||
key: 'createSpreadsheetRow',
|
||||
description: 'Creates a new row in a specified spreadsheet.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Drive',
|
||||
key: 'driveId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listDrives',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Spreadsheet',
|
||||
key: 'spreadsheetId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.driveId'],
|
||||
description: 'The spreadsheets in your Google Drive.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpreadsheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.driveId',
|
||||
value: '{parameters.driveId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Worksheet',
|
||||
key: 'worksheetId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.spreadsheetId'],
|
||||
description: 'The worksheets in your selected spreadsheet.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorksheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spreadsheetId',
|
||||
value: '{parameters.spreadsheetId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
additionalFields: {
|
||||
type: 'query',
|
||||
name: 'getDynamicFields',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSheetHeaders',
|
||||
},
|
||||
{
|
||||
name: 'parameters.worksheetId',
|
||||
value: '{parameters.worksheetId}',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spreadsheetId',
|
||||
value: '{parameters.spreadsheetId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const {
|
||||
data: { sheets },
|
||||
} = await $.http.get<TSheetsResponse>(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`
|
||||
);
|
||||
|
||||
const selectedSheet = sheets.find(
|
||||
(sheet) => sheet.properties.sheetId === $.step.parameters.worksheetId
|
||||
);
|
||||
|
||||
const sheetName = selectedSheet.properties.title;
|
||||
|
||||
const range = sheetName;
|
||||
|
||||
const dataValues = Object.entries($.step.parameters)
|
||||
.filter((entry: [string, string]) => entry[0].startsWith('header-'))
|
||||
.map((value) => value[1]);
|
||||
|
||||
const values = [dataValues];
|
||||
|
||||
const params = {
|
||||
valueInputOption: 'USER_ENTERED',
|
||||
insertDataOption: 'INSERT_ROWS',
|
||||
includeValuesInResponse: true,
|
||||
};
|
||||
|
||||
const body = {
|
||||
majorDimension: 'ROWS',
|
||||
range,
|
||||
values,
|
||||
};
|
||||
|
||||
const { data } = await $.http.post(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}/values/${range}:append`,
|
||||
body,
|
||||
{ params }
|
||||
);
|
||||
|
||||
$.setActionItem({
|
||||
raw: data,
|
||||
});
|
||||
},
|
||||
});
|
3
packages/backend/src/apps/google-sheets/actions/index.ts
Normal file
3
packages/backend/src/apps/google-sheets/actions/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import createSpreadsheetRow from './create-spreadsheet-row';
|
||||
|
||||
export default [createSpreadsheetRow];
|
@@ -1,4 +1,6 @@
|
||||
import listDrives from './list-drives';
|
||||
import listSpreadsheets from './list-spreadsheets';
|
||||
import listWorksheets from './list-worksheets';
|
||||
import listColumns from './list-columns';
|
||||
|
||||
export default [listDrives, listSpreadsheets];
|
||||
export default [listDrives, listSpreadsheets, listWorksheets, listColumns];
|
||||
|
@@ -0,0 +1,70 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
type TSheetsResponse = {
|
||||
sheets: {
|
||||
properties: {
|
||||
sheetId: string;
|
||||
title: string;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
function getColumnNameByNumber(columnNumber: number) {
|
||||
let columnName = '';
|
||||
while (columnNumber > 0) {
|
||||
const modulo = (columnNumber - 1) % 26;
|
||||
columnName = String.fromCharCode(65 + modulo) + columnName;
|
||||
columnNumber = Math.floor((columnNumber - modulo) / 26);
|
||||
}
|
||||
return columnName;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'List columns',
|
||||
key: 'listColumns',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const spreadsheetId = $.step.parameters.spreadsheetId as string;
|
||||
|
||||
const headers: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
if (!spreadsheetId) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
const {
|
||||
data: { sheets },
|
||||
} = await $.http.get<TSheetsResponse>(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`
|
||||
);
|
||||
|
||||
const selectedSheet = sheets.find(
|
||||
(sheet) => sheet.properties.sheetId === $.step.parameters.worksheetId
|
||||
);
|
||||
|
||||
if (!selectedSheet) return;
|
||||
|
||||
const sheetName = selectedSheet.properties.title;
|
||||
|
||||
const range = `${sheetName}!1:1`;
|
||||
|
||||
const { data } = await $.http.get(
|
||||
`v4/spreadsheets/${$.step.parameters.spreadsheetId}/values/${range}`
|
||||
);
|
||||
|
||||
if (data.values?.length) {
|
||||
for (let number = 0; number < data.values[0].length; number++) {
|
||||
headers.data.push({
|
||||
value: getColumnNameByNumber(number + 1),
|
||||
name: data.values[0][number],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return headers;
|
||||
},
|
||||
};
|
@@ -0,0 +1,42 @@
|
||||
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||
|
||||
export default {
|
||||
name: 'List worksheets',
|
||||
key: 'listWorksheets',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
const spreadsheetId = $.step.parameters.spreadsheetId as string;
|
||||
|
||||
const worksheets: {
|
||||
data: IJSONObject[];
|
||||
} = {
|
||||
data: [],
|
||||
};
|
||||
|
||||
if (!spreadsheetId) {
|
||||
return worksheets;
|
||||
}
|
||||
|
||||
const params: Record<string, unknown> = {
|
||||
pageToken: undefined as unknown as string,
|
||||
};
|
||||
|
||||
do {
|
||||
const { data } = await $.http.get(`/v4/spreadsheets/${spreadsheetId}`, {
|
||||
params,
|
||||
});
|
||||
params.pageToken = data.nextPageToken;
|
||||
|
||||
if (data.sheets?.length) {
|
||||
for (const sheet of data.sheets) {
|
||||
worksheets.data.push({
|
||||
value: sheet.properties.sheetId,
|
||||
name: sheet.properties.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (params.pageToken);
|
||||
|
||||
return worksheets;
|
||||
},
|
||||
};
|
@@ -0,0 +1,3 @@
|
||||
import listSheetHeaders from './list-sheet-headers';
|
||||
|
||||
export default [listSheetHeaders];
|
@@ -0,0 +1,71 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
type TSheetsResponse = {
|
||||
sheets: {
|
||||
properties: {
|
||||
sheetId: string;
|
||||
title: string;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
type TSheetsValueResponse = {
|
||||
majorDimension: string;
|
||||
range: string;
|
||||
values: string[][];
|
||||
};
|
||||
|
||||
const hasValue = (value: any) => value !== null && value !== undefined;
|
||||
|
||||
export default {
|
||||
name: 'List Sheet Headers',
|
||||
key: 'listSheetHeaders',
|
||||
|
||||
async run($: IGlobalVariable) {
|
||||
if (!hasValue($.step.parameters.spreadsheetId) || !hasValue($.step.parameters.worksheetId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
data: { sheets },
|
||||
} = await $.http.get<TSheetsResponse>(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`
|
||||
);
|
||||
|
||||
const selectedSheet = sheets.find(
|
||||
(sheet) => sheet.properties.sheetId === $.step.parameters.worksheetId
|
||||
);
|
||||
|
||||
if (!selectedSheet) return;
|
||||
|
||||
const sheetName = selectedSheet.properties.title;
|
||||
|
||||
const range = `${sheetName}!1:1`;
|
||||
|
||||
const params: Record<string, unknown> = {
|
||||
majorDimension: 'ROWS',
|
||||
};
|
||||
|
||||
const { data } = await $.http.get<TSheetsValueResponse>(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}/values/${range}`,
|
||||
{
|
||||
params,
|
||||
}
|
||||
);
|
||||
|
||||
if (!data.values) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = data.values[0].map((item: string, index: number) => ({
|
||||
label: item,
|
||||
key: `header-${index}`,
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
value: item,
|
||||
variables: true,
|
||||
}));
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
@@ -2,7 +2,9 @@ import defineApp from '../../helpers/define-app';
|
||||
import addAuthHeader from './common/add-auth-header';
|
||||
import auth from './auth';
|
||||
import triggers from './triggers';
|
||||
import actions from './actions';
|
||||
import dynamicData from './dynamic-data';
|
||||
import dynamicFields from './dynamic-fields';
|
||||
|
||||
export default defineApp({
|
||||
name: 'Google Sheets',
|
||||
@@ -16,5 +18,7 @@ export default defineApp({
|
||||
beforeRequest: [addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
actions,
|
||||
dynamicData,
|
||||
dynamicFields,
|
||||
});
|
||||
|
@@ -1,4 +1,11 @@
|
||||
import newSpreadsheets from './new-spreadsheets';
|
||||
import newWorksheets from './new-worksheets';
|
||||
import newSpreadsheetRows from './new-spreadsheet-rows';
|
||||
import newOrUpdatedSpreadsheetRows from './new-or-updated-spreadsheet-rows';
|
||||
|
||||
export default [newSpreadsheets, newWorksheets];
|
||||
export default [
|
||||
newSpreadsheets,
|
||||
newWorksheets,
|
||||
newSpreadsheetRows,
|
||||
newOrUpdatedSpreadsheetRows,
|
||||
];
|
||||
|
@@ -0,0 +1,109 @@
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newOrUpdatedSpreadsheetRows from './new-or-updated-spreadsheet-rows';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New or updated spreadsheet rows',
|
||||
key: 'newOrUpdatedSpreadsheetRows',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when a new row is added or modified in a spreadsheet.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Drive',
|
||||
key: 'driveId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listDrives',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Spreadsheet',
|
||||
key: 'spreadsheetId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.driveId'],
|
||||
description: 'The spreadsheets in your Google Drive.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpreadsheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.driveId',
|
||||
value: '{parameters.driveId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Worksheet',
|
||||
key: 'worksheetId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.spreadsheetId'],
|
||||
description:
|
||||
'The worksheets in your selected spreadsheet. You must have column headers.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorksheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spreadsheetId',
|
||||
value: '{parameters.spreadsheetId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Trigger Column',
|
||||
key: 'triggerColumnIndex',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
dependsOn: ['parameters.worksheetId'],
|
||||
description:
|
||||
'Triggers on changes to cells in this column only. Leave this field blank if you want the flow to trigger on changes to any cell within the row. Please note: All new rows will trigger the flow even if the Trigger column is empty.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listColumns',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spreadsheetId',
|
||||
value: '{parameters.spreadsheetId}',
|
||||
},
|
||||
{
|
||||
name: 'parameters.worksheetId',
|
||||
value: '{parameters.worksheetId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
await newOrUpdatedSpreadsheetRows($);
|
||||
},
|
||||
});
|
@@ -0,0 +1,50 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
type TSheetsResponse = {
|
||||
sheets: {
|
||||
properties: {
|
||||
sheetId: string;
|
||||
title: string;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
const newOrUpdatedSpreadsheetRows = async ($: IGlobalVariable) => {
|
||||
const {
|
||||
data: { sheets },
|
||||
} = await $.http.get<TSheetsResponse>(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`
|
||||
);
|
||||
|
||||
const selectedSheet = sheets.find(
|
||||
(sheet) => sheet.properties.sheetId === $.step.parameters.worksheetId
|
||||
);
|
||||
|
||||
if (!selectedSheet) return;
|
||||
|
||||
const sheetName = selectedSheet.properties.title;
|
||||
|
||||
let range = sheetName;
|
||||
|
||||
if ($.step.parameters.triggerColumnIndex) {
|
||||
range = `${sheetName}!${$.step.parameters.triggerColumnIndex}:${$.step.parameters.triggerColumnIndex}`;
|
||||
}
|
||||
|
||||
const { data } = await $.http.get(
|
||||
`v4/spreadsheets/${$.step.parameters.spreadsheetId}/values/${range}`
|
||||
);
|
||||
|
||||
if (data.values?.length) {
|
||||
for (let index = data.values.length - 1; index > 0; index--) {
|
||||
const value = data.values[index];
|
||||
$.pushTriggerItem({
|
||||
raw: { row: value },
|
||||
meta: {
|
||||
internalId: `${value}-${index.toString()}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default newOrUpdatedSpreadsheetRows;
|
@@ -0,0 +1,82 @@
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newSpreadsheetRows from './new-spreadsheet-rows';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New spreadsheet rows',
|
||||
key: 'newSpreadsheetRows',
|
||||
pollInterval: 15,
|
||||
description:
|
||||
'Triggers when a new row is added to the bottom of a spreadsheet.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Drive',
|
||||
key: 'driveId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description:
|
||||
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listDrives',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Spreadsheet',
|
||||
key: 'spreadsheetId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.driveId'],
|
||||
description: 'The spreadsheets in your Google Drive.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listSpreadsheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.driveId',
|
||||
value: '{parameters.driveId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Worksheet',
|
||||
key: 'worksheetId',
|
||||
type: 'dropdown' as const,
|
||||
required: true,
|
||||
dependsOn: ['parameters.spreadsheetId'],
|
||||
description:
|
||||
'The worksheets in your selected spreadsheet. You must have column headers.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
name: 'getDynamicData',
|
||||
arguments: [
|
||||
{
|
||||
name: 'key',
|
||||
value: 'listWorksheets',
|
||||
},
|
||||
{
|
||||
name: 'parameters.spreadsheetId',
|
||||
value: '{parameters.spreadsheetId}',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
await newSpreadsheetRows($);
|
||||
},
|
||||
});
|
@@ -0,0 +1,46 @@
|
||||
import { IGlobalVariable } from '@automatisch/types';
|
||||
|
||||
type TSheetsResponse = {
|
||||
sheets: {
|
||||
properties: {
|
||||
sheetId: string;
|
||||
title: string;
|
||||
};
|
||||
}[];
|
||||
};
|
||||
|
||||
const newSpreadsheetRows = async ($: IGlobalVariable) => {
|
||||
const {
|
||||
data: { sheets },
|
||||
} = await $.http.get<TSheetsResponse>(
|
||||
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`
|
||||
);
|
||||
|
||||
const selectedSheet = sheets.find(
|
||||
(sheet) => sheet.properties.sheetId === $.step.parameters.worksheetId
|
||||
);
|
||||
|
||||
if (!selectedSheet) return;
|
||||
|
||||
const sheetName = selectedSheet.properties.title;
|
||||
|
||||
const range = sheetName;
|
||||
|
||||
const { data } = await $.http.get(
|
||||
`v4/spreadsheets/${$.step.parameters.spreadsheetId}/values/${range}`
|
||||
);
|
||||
|
||||
if (data.values?.length) {
|
||||
for (let index = data.values.length - 1; index > 0; index--) {
|
||||
const value = data.values[index];
|
||||
$.pushTriggerItem({
|
||||
raw: { row: value },
|
||||
meta: {
|
||||
internalId: index.toString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default newSpreadsheetRows;
|
@@ -1,8 +1,8 @@
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newSpreadsheets from './new-spreadsheets'
|
||||
import newSpreadsheets from './new-spreadsheets';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Spreadsheets',
|
||||
name: 'New spreadsheets',
|
||||
key: 'newSpreadsheets',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when you create a new spreadsheet.',
|
||||
@@ -12,7 +12,8 @@ export default defineTrigger({
|
||||
key: 'driveId',
|
||||
type: 'dropdown' as const,
|
||||
required: false,
|
||||
description: 'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||
description:
|
||||
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
|
||||
variables: false,
|
||||
source: {
|
||||
type: 'query',
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import newWorksheets from './new-worksheets';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Worksheets',
|
||||
name: 'New worksheets',
|
||||
key: 'newWorksheets',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when you create a new worksheet in a spreadsheet.',
|
||||
|
@@ -6,15 +6,17 @@ type TMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
||||
type THeaderEntry = {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
};
|
||||
|
||||
type THeaderEntries = THeaderEntry[];
|
||||
|
||||
function isPossiblyTextBased(contentType: string) {
|
||||
if (!contentType) return false;
|
||||
|
||||
return contentType.startsWith('application/json')
|
||||
|| contentType.startsWith('text/');
|
||||
return (
|
||||
contentType.startsWith('application/json') ||
|
||||
contentType.startsWith('text/')
|
||||
);
|
||||
}
|
||||
|
||||
function throwIfFileSizeExceedsLimit(contentLength: string) {
|
||||
@@ -28,7 +30,7 @@ function throwIfFileSizeExceedsLimit(contentLength: string) {
|
||||
}
|
||||
|
||||
export default defineAction({
|
||||
name: 'Custom Request',
|
||||
name: 'Custom request',
|
||||
key: 'customRequest',
|
||||
description: 'Makes a custom HTTP request by providing raw details.',
|
||||
arguments: [
|
||||
@@ -69,10 +71,12 @@ export default defineAction({
|
||||
type: 'dynamic' as const,
|
||||
required: false,
|
||||
description: 'Add or remove headers as needed',
|
||||
value: [{
|
||||
value: [
|
||||
{
|
||||
key: 'Content-Type',
|
||||
value: 'application/json'
|
||||
}],
|
||||
value: 'application/json',
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
{
|
||||
label: 'Key',
|
||||
@@ -89,9 +93,9 @@ export default defineAction({
|
||||
required: true,
|
||||
description: 'Header value',
|
||||
variables: true,
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
@@ -100,30 +104,35 @@ export default defineAction({
|
||||
const url = $.step.parameters.url as string;
|
||||
const headers = $.step.parameters.headers as THeaderEntries;
|
||||
|
||||
const headersObject: Record<string, string> = headers.reduce((result, entry) => {
|
||||
const headersObject: Record<string, string> = headers.reduce(
|
||||
(result, entry) => {
|
||||
const key = entry.key?.toLowerCase();
|
||||
const value = entry.value;
|
||||
|
||||
if (key && value) {
|
||||
return {
|
||||
...result,
|
||||
[entry.key?.toLowerCase()]: entry.value
|
||||
}
|
||||
[entry.key?.toLowerCase()]: entry.value,
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}, {});
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
let contentType = headersObject['content-type'];
|
||||
|
||||
// in case HEAD request is not supported by the URL
|
||||
try {
|
||||
const metadataResponse = await $.http.head(url, { headers: headersObject });
|
||||
const metadataResponse = await $.http.head(url, {
|
||||
headers: headersObject,
|
||||
});
|
||||
contentType = metadataResponse.headers['content-type'];
|
||||
|
||||
throwIfFileSizeExceedsLimit(metadataResponse.headers['content-length']);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch { }
|
||||
} catch {}
|
||||
|
||||
const requestData: AxiosRequestConfig = {
|
||||
url,
|
||||
|
@@ -18,7 +18,9 @@ const hashItem = async (value: string) => {
|
||||
|
||||
const newItemsInFeed = async ($: IGlobalVariable) => {
|
||||
const { data } = await $.http.get($.step.parameters.feedUrl as string);
|
||||
const parser = new XMLParser();
|
||||
const parser = new XMLParser({
|
||||
ignoreAttributes: false,
|
||||
});
|
||||
const parsedData = parser.parse(data);
|
||||
|
||||
// naive implementation to cover atom and rss feeds
|
||||
|
@@ -1,12 +1,13 @@
|
||||
import defineTrigger from "../../../../helpers/define-trigger";
|
||||
import getBalanceTransactions from "./get-balance-transactions";
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import getBalanceTransactions from './get-balance-transactions';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Balance Transactions',
|
||||
name: 'New balance transactions',
|
||||
key: 'newBalanceTransactions',
|
||||
description: 'Triggers when a new transaction is processed (refund, payout, adjustment, ...)',
|
||||
description:
|
||||
'Triggers when a new transaction is processed (refund, payout, adjustment, ...)',
|
||||
pollInterval: 15,
|
||||
async run($) {
|
||||
await getBalanceTransactions($)
|
||||
}
|
||||
})
|
||||
await getBalanceTransactions($);
|
||||
},
|
||||
});
|
||||
|
@@ -1,12 +1,13 @@
|
||||
import defineTrigger from "../../../../helpers/define-trigger";
|
||||
import getPayouts from "./get-payouts";
|
||||
import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import getPayouts from './get-payouts';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New Payouts',
|
||||
name: 'New payouts',
|
||||
key: 'newPayouts',
|
||||
description: 'Triggers when a payout (Stripe <-> Bank account) has been updated',
|
||||
description:
|
||||
'Triggers when a payout (Stripe <-> Bank account) has been updated',
|
||||
pollInterval: 15,
|
||||
async run($) {
|
||||
await getPayouts($)
|
||||
}
|
||||
})
|
||||
await getPayouts($);
|
||||
},
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create Task',
|
||||
name: 'Create task',
|
||||
key: 'createTask',
|
||||
description: 'Creates a Task in Todoist',
|
||||
arguments: [
|
||||
@@ -59,8 +59,7 @@ export default defineAction({
|
||||
type: 'string' as const,
|
||||
required: true,
|
||||
variables: true,
|
||||
description:
|
||||
'Task content, may be markdown. Example: "Foo"',
|
||||
description: 'Task content, may be markdown. Example: "Foo"',
|
||||
},
|
||||
{
|
||||
label: 'Description',
|
||||
@@ -68,22 +67,16 @@ export default defineAction({
|
||||
type: 'string' as const,
|
||||
required: false,
|
||||
variables: true,
|
||||
description:
|
||||
'Task description, may be markdown. Example: "Foo"',
|
||||
description: 'Task description, may be markdown. Example: "Foo"',
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const requestPath = `/tasks`;
|
||||
const {
|
||||
projectId,
|
||||
sectionId,
|
||||
labels,
|
||||
content,
|
||||
description
|
||||
} = $.step.parameters;
|
||||
const { projectId, sectionId, labels, content, description } =
|
||||
$.step.parameters;
|
||||
|
||||
const labelsArray = (labels as string).split(',')
|
||||
const labelsArray = (labels as string).split(',');
|
||||
|
||||
const payload = {
|
||||
content,
|
||||
@@ -91,7 +84,7 @@ export default defineAction({
|
||||
project_id: projectId || null,
|
||||
labels: labelsArray || null,
|
||||
section_id: sectionId || null,
|
||||
}
|
||||
};
|
||||
|
||||
const response = await $.http.post(requestPath, payload);
|
||||
|
||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
||||
import getActiveTasks from './get-tasks';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'Get Active Tasks',
|
||||
name: 'Get active tasks',
|
||||
key: 'getActiveTasks',
|
||||
pollInterval: 15,
|
||||
description: 'Triggers when new Task(s) are found',
|
||||
|
@@ -28,7 +28,7 @@ export default defineTrigger({
|
||||
{
|
||||
name: 'parameters.valueType',
|
||||
value: 'sid',
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -37,12 +37,14 @@ export default defineTrigger({
|
||||
async testRun($) {
|
||||
await fetchMessages($);
|
||||
|
||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: $.lastExecutionStep.dataOut,
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import defineAction from '../../../../helpers/define-action';
|
||||
|
||||
export default defineAction({
|
||||
name: 'Create Tweet',
|
||||
name: 'Create tweet',
|
||||
key: 'createTweet',
|
||||
description: 'Create a tweet.',
|
||||
arguments: [
|
||||
|
@@ -8,12 +8,14 @@ export default defineTrigger({
|
||||
description: 'Triggers when the webhook receives a request.',
|
||||
|
||||
async testRun($) {
|
||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: $.lastExecutionStep.dataOut,
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
@@ -9,6 +9,7 @@ type AppConfig = {
|
||||
webAppUrl: string;
|
||||
webhookUrl: string;
|
||||
appEnv: string;
|
||||
logLevel: string;
|
||||
isDev: boolean;
|
||||
isProd: boolean;
|
||||
postgresDatabase: string;
|
||||
@@ -80,6 +81,7 @@ const appConfig: AppConfig = {
|
||||
protocol,
|
||||
port,
|
||||
appEnv: appEnv,
|
||||
logLevel: process.env.LOG_LEVEL || 'info',
|
||||
isDev: appEnv === 'development',
|
||||
isProd: appEnv === 'production',
|
||||
version: process.env.npm_package_version,
|
||||
|
@@ -1,7 +1,8 @@
|
||||
import Crypto from 'node:crypto';
|
||||
import { Response } from 'express';
|
||||
import bcrypt from 'bcrypt';
|
||||
import { IRequest, ITriggerItem } from '@automatisch/types';
|
||||
|
||||
import logger from '../../helpers/logger';
|
||||
import Flow from '../../models/flow';
|
||||
import { processTrigger } from '../../services/trigger';
|
||||
import actionQueue from '../../queues/action';
|
||||
@@ -13,8 +14,19 @@ import {
|
||||
} from '../../helpers/remove-job-configuration';
|
||||
|
||||
export default async (request: IRequest, response: Response) => {
|
||||
const flowId = request.params.flowId;
|
||||
|
||||
// in case it's our built-in generic webhook trigger
|
||||
let computedRequestPayload = {
|
||||
headers: request.headers,
|
||||
body: request.body,
|
||||
query: request.query,
|
||||
};
|
||||
logger.debug(`Handling incoming webhook request at ${request.originalUrl}.`);
|
||||
logger.debug(JSON.stringify(computedRequestPayload, null, 2));
|
||||
|
||||
const flow = await Flow.query()
|
||||
.findById(request.params.flowId)
|
||||
.findById(flowId)
|
||||
.throwIfNotFound();
|
||||
|
||||
const user = await flow.$relatedQuery('user');
|
||||
@@ -56,29 +68,19 @@ export default async (request: IRequest, response: Response) => {
|
||||
}
|
||||
|
||||
// in case trigger type is 'webhook'
|
||||
let payload = request.body;
|
||||
let rawInternalId: string | Buffer = request.rawBody;
|
||||
|
||||
// in case it's our built-in generic webhook trigger
|
||||
if (isWebhookApp) {
|
||||
payload = {
|
||||
headers: request.headers,
|
||||
body: request.body,
|
||||
query: request.query,
|
||||
};
|
||||
|
||||
rawInternalId = JSON.stringify(payload);
|
||||
if (!isWebhookApp) {
|
||||
computedRequestPayload = request.body;
|
||||
}
|
||||
|
||||
const triggerItem: ITriggerItem = {
|
||||
raw: payload,
|
||||
raw: computedRequestPayload,
|
||||
meta: {
|
||||
internalId: await bcrypt.hash(rawInternalId, 1),
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
const { flowId, executionId } = await processTrigger({
|
||||
flowId: flow.id,
|
||||
const { executionId } = await processTrigger({
|
||||
flowId,
|
||||
stepId: triggerStep.id,
|
||||
triggerItem,
|
||||
testRun,
|
||||
|
@@ -9,7 +9,7 @@ export default class BaseError extends Error {
|
||||
try {
|
||||
computedError = JSON.parse(error as string);
|
||||
} catch {
|
||||
computedError = typeof error === 'string' ? { error } : error;
|
||||
computedError = (typeof error === 'string' || Array.isArray(error)) ? { error } : error;
|
||||
}
|
||||
|
||||
let computedMessage: string;
|
||||
|
@@ -1,8 +1,6 @@
|
||||
import Context from '../../types/express/context';
|
||||
import axios from 'axios';
|
||||
import globalVariable from '../../helpers/global-variable';
|
||||
import App from '../../models/app';
|
||||
import GenerateAuthUrlError from '../../errors/generate-auth-url';
|
||||
|
||||
type Params = {
|
||||
input: {
|
||||
@@ -31,12 +29,7 @@ const generateAuthUrl = async (
|
||||
const app = await App.findOneByKey(connection.key);
|
||||
|
||||
const $ = await globalVariable({ connection, app });
|
||||
try {
|
||||
await authInstance.generateAuthUrl($);
|
||||
await axios.get(connection.formattedData.url as string);
|
||||
} catch (error) {
|
||||
throw new GenerateAuthUrlError(error);
|
||||
}
|
||||
|
||||
return connection.formattedData;
|
||||
};
|
||||
|
@@ -80,9 +80,10 @@ const globalVariable = async (
|
||||
testRun,
|
||||
exit: () => {
|
||||
throw new EarlyExitError();
|
||||
}
|
||||
},
|
||||
lastExecutionStep: (await step?.getLastExecutionStep())?.toJSON(),
|
||||
},
|
||||
getLastExecutionStep: async () =>
|
||||
(await step?.getLastExecutionStep())?.toJSON(),
|
||||
triggerOutput: {
|
||||
data: [],
|
||||
},
|
||||
|
@@ -9,10 +9,6 @@ const levels = {
|
||||
debug: 4,
|
||||
};
|
||||
|
||||
const level = () => {
|
||||
return appConfig.appEnv === 'development' ? 'debug' : 'info';
|
||||
};
|
||||
|
||||
const colors = {
|
||||
error: 'red',
|
||||
warn: 'yellow',
|
||||
@@ -41,7 +37,7 @@ const transports = [
|
||||
];
|
||||
|
||||
export const logger = winston.createLogger({
|
||||
level: level(),
|
||||
level: appConfig.logLevel,
|
||||
levels,
|
||||
format,
|
||||
transports,
|
||||
|
@@ -10,7 +10,12 @@ const webUIHandler = async (app: Application) => {
|
||||
const indexHtml = join(dirname(webAppPath), 'build', 'index.html');
|
||||
|
||||
app.use(express.static(webBuildPath));
|
||||
app.get('*', (_req, res) => res.sendFile(indexHtml));
|
||||
app.get('*', (_req, res) => {
|
||||
res.set('Content-Security-Policy', 'frame-ancestors: none;');
|
||||
res.set('X-Frame-Options', 'DENY');
|
||||
|
||||
res.sendFile(indexHtml);
|
||||
});
|
||||
};
|
||||
|
||||
export default webUIHandler;
|
||||
|
@@ -91,6 +91,7 @@ class Flow extends Base {
|
||||
async lastInternalId() {
|
||||
const lastExecution = await this.$relatedQuery('executions')
|
||||
.orderBy('created_at', 'desc')
|
||||
.limit(1)
|
||||
.first();
|
||||
|
||||
return lastExecution ? (lastExecution as Execution).internalId : null;
|
||||
|
@@ -117,6 +117,7 @@ class Step extends Base {
|
||||
async getLastExecutionStep() {
|
||||
const lastExecutionStep = await this.$relatedQuery('executionSteps')
|
||||
.orderBy('created_at', 'desc')
|
||||
.limit(1)
|
||||
.first();
|
||||
|
||||
return lastExecutionStep;
|
||||
|
@@ -102,7 +102,7 @@ class User extends Base {
|
||||
to: 'users.id',
|
||||
},
|
||||
filter(builder: ExtendedQueryBuilder<UsageData>) {
|
||||
builder.orderBy('created_at', 'desc').first();
|
||||
builder.orderBy('created_at', 'desc').limit(1).first();
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
@@ -121,7 +121,7 @@ class User extends Base {
|
||||
to: 'users.id',
|
||||
},
|
||||
filter(builder: ExtendedQueryBuilder<Subscription>) {
|
||||
builder.orderBy('created_at', 'desc').first();
|
||||
builder.orderBy('created_at', 'desc').limit(1).first();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@@ -4,6 +4,7 @@ import Execution from '../models/execution';
|
||||
import ExecutionStep from '../models/execution-step';
|
||||
import computeParameters from '../helpers/compute-parameters';
|
||||
import globalVariable from '../helpers/global-variable';
|
||||
import { logger } from '../helpers/logger';
|
||||
import HttpError from '../errors/http';
|
||||
import EarlyExitError from '../errors/early-exit';
|
||||
import AlreadyProcessedError from '../errors/already-processed';
|
||||
@@ -53,6 +54,8 @@ export const processAction = async (options: ProcessActionOptions) => {
|
||||
const shouldNotConsiderAsError = shouldEarlyExit || shouldNotProcess;
|
||||
|
||||
if (!shouldNotConsiderAsError) {
|
||||
logger.error(error);
|
||||
|
||||
if (error instanceof HttpError) {
|
||||
$.actionOutput.error = error.details;
|
||||
} else {
|
||||
|
@@ -3,6 +3,7 @@ import globalVariable from '../helpers/global-variable';
|
||||
import EarlyExitError from '../errors/early-exit';
|
||||
import AlreadyProcessedError from '../errors/already-processed';
|
||||
import HttpError from '../errors/http';
|
||||
import { logger } from '../helpers/logger';
|
||||
|
||||
type ProcessFlowOptions = {
|
||||
flowId: string;
|
||||
@@ -35,6 +36,8 @@ export const processFlow = async (options: ProcessFlowOptions) => {
|
||||
const shouldNotConsiderAsError = shouldEarlyExit || shouldNotProcess;
|
||||
|
||||
if (!shouldNotConsiderAsError) {
|
||||
logger.error(error);
|
||||
|
||||
if (error instanceof HttpError) {
|
||||
$.triggerOutput.error = error.details;
|
||||
} else {
|
||||
|
@@ -26,6 +26,8 @@ export const worker = new Worker(
|
||||
const { stepId, flowId, executionId, computedParameters, executionStep } =
|
||||
await processAction(job.data as JobData);
|
||||
|
||||
if (executionStep.isFailed) return;
|
||||
|
||||
const step = await Step.query().findById(stepId).throwIfNotFound();
|
||||
const nextStep = await step.getNextStep();
|
||||
|
||||
|
@@ -68,6 +68,15 @@ export default defineConfig({
|
||||
{ text: 'Connection', link: '/apps/dropbox/connection' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Filter',
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Actions', link: '/apps/filter/actions' },
|
||||
{ text: 'Connection', link: '/apps/filter/connection' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Flickr',
|
||||
collapsible: true,
|
||||
@@ -111,6 +120,7 @@ export default defineConfig({
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Triggers', link: '/apps/google-sheets/triggers' },
|
||||
{ text: 'Actions', link: '/apps/google-sheets/actions' },
|
||||
{ text: 'Connection', link: '/apps/google-sheets/connection' },
|
||||
],
|
||||
},
|
||||
|
@@ -15,13 +15,14 @@ Please be careful with the `ENCRYPTION_KEY` and `WEBHOOK_SECRET_KEY` environment
|
||||
:::
|
||||
|
||||
| Variable Name | Type | Default Value | Description |
|
||||
| --------------------------- | ------- | ------------------ | ---------------------------------------------------- |
|
||||
| --------------------------- | ------- | ------------------ | ---------------------------------------------------------------------------------------------------- |
|
||||
| `HOST` | string | `localhost` | HTTP Host |
|
||||
| `PROTOCOL` | string | `http` | HTTP Protocol |
|
||||
| `PORT` | string | `3000` | HTTP Port |
|
||||
| `APP_ENV` | string | `production` | Automatisch Environment |
|
||||
| `WEB_APP_URL` | string | | Can be used to override connection URLs and CORS URL |
|
||||
| `WEBHOOK_URL` | string | | Can be used to override webhook URL |
|
||||
| `LOG_LEVEL` | string | `info` | Can be used to configure log level such as `error`, `warn`, `info`, `http`, `debug` |
|
||||
| `POSTGRES_DATABASE` | string | `automatisch` | Database Name |
|
||||
| `POSTGRES_SCHEMA` | string | `public` | Database Schema |
|
||||
| `POSTGRES_PORT` | number | `5432` | Database Port |
|
||||
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
favicon: /favicons/deepl.svg
|
||||
items:
|
||||
- name: Translate Text
|
||||
- name: Translate text
|
||||
desc: Translates text from one language to another.
|
||||
---
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
---
|
||||
favicon: /favicons/delay.svg
|
||||
items:
|
||||
- name: Delay For
|
||||
- name: Delay for
|
||||
desc: Delays the execution of the next action by a specified amount of time.
|
||||
- name: Delay Until
|
||||
- name: Delay until
|
||||
desc: Delays the execution of the next action until a specified date.
|
||||
---
|
||||
|
||||
|
12
packages/docs/pages/apps/filter/actions.md
Normal file
12
packages/docs/pages/apps/filter/actions.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
favicon: /favicons/filter.svg
|
||||
items:
|
||||
- name: Continue if conditions match
|
||||
desc: Let the execution continue if the conditions match.
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import CustomListing from '../../components/CustomListing.vue'
|
||||
</script>
|
||||
|
||||
<CustomListing />
|
12
packages/docs/pages/apps/filter/connection.md
Normal file
12
packages/docs/pages/apps/filter/connection.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Filter
|
||||
|
||||
Filter is a built-in app shipped with Automatisch, and it doesn't need to talk with any other external service to run. So there are no additional steps to use the Filter app. It can be used as an action and it filters the flow based on the given conditions. Available conditions are:
|
||||
|
||||
- is equal
|
||||
- is not equal
|
||||
- is greater than
|
||||
- is less than
|
||||
- is greater than or equal
|
||||
- is less than or equal
|
||||
- contains
|
||||
- does not contain
|
@@ -1,14 +1,14 @@
|
||||
---
|
||||
favicon: /favicons/google-drive.svg
|
||||
items:
|
||||
- name: New Files
|
||||
- name: New files
|
||||
desc: Triggers when any new file is added (inside of any folder)
|
||||
- name: New Files in Folder
|
||||
desc: Triggers when a new file is added directly to a specific folder (but not its subfolder)
|
||||
- name: New Folders
|
||||
desc: Triggers when a new folder is added directly to a specific folder (but not its subfolder)
|
||||
- name: Updated Files
|
||||
desc: Triggers when a file is updated in a specific folder (but not its subfolder)
|
||||
- name: New files in folder
|
||||
desc: Triggers when a new file is added directly to a specified folder (but not its subfolder)
|
||||
- name: New folders
|
||||
desc: Triggers when a new folder is added directly to a specified folder (but not its subfolder)
|
||||
- name: Updated files
|
||||
desc: Triggers when a file is updated in a specified folder (but not its subfolder)
|
||||
---
|
||||
|
||||
<script setup>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
---
|
||||
favicon: /favicons/google-forms.svg
|
||||
items:
|
||||
- name: New Form Responses
|
||||
- name: New form responses
|
||||
desc: Triggers when a new form response is submitted
|
||||
---
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user