Compare commits
38 Commits
v0.7.0
...
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 | ||
![]() |
41a67b402d | ||
![]() |
caa104b1cc | ||
![]() |
94085f2bc8 | ||
![]() |
d39c962314 | ||
![]() |
706fb0f063 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -125,3 +125,6 @@ dist
|
|||||||
.yarn/build-state.yml
|
.yarn/build-state.yml
|
||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
# MacOS finder preferences
|
||||||
|
.DS_store
|
||||||
|
@@ -4,7 +4,7 @@ WORKDIR /automatisch
|
|||||||
|
|
||||||
RUN \
|
RUN \
|
||||||
apk --no-cache add --virtual build-dependencies python3 build-base && \
|
apk --no-cache add --virtual build-dependencies python3 build-base && \
|
||||||
yarn global add @automatisch/cli@0.7.0 --network-timeout 1000000 && \
|
yarn global add @automatisch/cli@0.7.1 --network-timeout 1000000 && \
|
||||||
rm -rf /usr/local/share/.cache/ && \
|
rm -rf /usr/local/share/.cache/ && \
|
||||||
apk del build-dependencies
|
apk del build-dependencies
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
FROM automatischio/automatisch:0.7.0
|
FROM automatischio/automatisch:0.7.1
|
||||||
WORKDIR /automatisch
|
WORKDIR /automatisch
|
||||||
|
|
||||||
RUN apk add --no-cache openssl dos2unix
|
RUN apk add --no-cache openssl dos2unix
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
],
|
],
|
||||||
"version": "0.7.0",
|
"version": "0.7.1",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"command": {
|
"command": {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@automatisch/backend",
|
"name": "@automatisch/backend",
|
||||||
"version": "0.7.0",
|
"version": "0.7.1",
|
||||||
"license": "See LICENSE file",
|
"license": "See LICENSE file",
|
||||||
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"prebuild": "rm -rf ./dist"
|
"prebuild": "rm -rf ./dist"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automatisch/web": "^0.7.0",
|
"@automatisch/web": "^0.7.1",
|
||||||
"@bull-board/express": "^3.10.1",
|
"@bull-board/express": "^3.10.1",
|
||||||
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
"@graphql-tools/graphql-file-loader": "^7.3.4",
|
||||||
"@graphql-tools/load": "^7.5.2",
|
"@graphql-tools/load": "^7.5.2",
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
"url": "https://github.com/automatisch/automatisch/issues"
|
"url": "https://github.com/automatisch/automatisch/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@automatisch/types": "^0.7.0",
|
"@automatisch/types": "^0.7.1",
|
||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
"@types/bull": "^3.15.8",
|
"@types/bull": "^3.15.8",
|
||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
|
@@ -2,7 +2,7 @@ import qs from 'qs';
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
import defineAction from '../../../../helpers/define-action';
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
name: 'Translate Text',
|
name: 'Translate text',
|
||||||
key: 'translateText',
|
key: 'translateText',
|
||||||
description: 'Translates text from one language to another.',
|
description: 'Translates text from one language to another.',
|
||||||
arguments: [
|
arguments: [
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
import defineAction from '../../../../helpers/define-action';
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
name: 'Delay For',
|
name: 'Delay for',
|
||||||
key: 'delayFor',
|
key: 'delayFor',
|
||||||
description:
|
description:
|
||||||
'Delays the execution of the next action by a specified amount of time.',
|
'Delays the execution of the next action by a specified amount of time.',
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
import defineAction from '../../../../helpers/define-action';
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
name: 'Delay Until',
|
name: 'Delay until',
|
||||||
key: 'delayUntil',
|
key: 'delayUntil',
|
||||||
description:
|
description:
|
||||||
'Delays the execution of the next action until a specified date.',
|
'Delays the execution of the next action until a specified date.',
|
||||||
|
@@ -20,12 +20,14 @@ export default defineTrigger({
|
|||||||
],
|
],
|
||||||
|
|
||||||
async testRun($) {
|
async testRun($) {
|
||||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
const lastExecutionStep = await $.getLastExecutionStep();
|
||||||
|
|
||||||
|
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||||
$.pushTriggerItem({
|
$.pushTriggerItem({
|
||||||
raw: $.lastExecutionStep.dataOut,
|
raw: lastExecutionStep.dataOut,
|
||||||
meta: {
|
meta: {
|
||||||
internalId: '',
|
internalId: '',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -35,20 +37,15 @@ export default defineTrigger({
|
|||||||
name: $.flow.id,
|
name: $.flow.id,
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: $.webhookUrl,
|
url: $.webhookUrl,
|
||||||
filters: [$.step.parameters.filters]
|
filters: [$.step.parameters.filters],
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data } = await $.http.post(
|
const { data } = await $.http.post(`/v2/public/api/webhooks`, payload);
|
||||||
`/v2/public/api/webhooks`,
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
|
|
||||||
await $.flow.setRemoteWebhookId(data.id);
|
await $.flow.setRemoteWebhookId(data.id);
|
||||||
},
|
},
|
||||||
|
|
||||||
async unregisterHook($) {
|
async unregisterHook($) {
|
||||||
await $.http.delete(
|
await $.http.delete(`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`);
|
||||||
`/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';
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'List Folders',
|
name: 'List folders',
|
||||||
key: 'listFolders',
|
key: 'listFolders',
|
||||||
|
|
||||||
async run($: IGlobalVariable) {
|
async run($: IGlobalVariable) {
|
||||||
@@ -22,6 +22,7 @@ export default {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import newFilesInFolder from './new-files-in-folder';
|
import newFilesInFolder from './new-files-in-folder';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Files in Folder',
|
name: 'New files in folder',
|
||||||
key: 'newFilesInFolder',
|
key: 'newFilesInFolder',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description:
|
description:
|
||||||
|
@@ -19,6 +19,7 @@ const newFilesInFolder = async ($: IGlobalVariable) => {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import newFiles from './new-files';
|
import newFiles from './new-files';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Files',
|
name: 'New files',
|
||||||
key: 'newFiles',
|
key: 'newFiles',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description: 'Triggers when any new file is added (inside of any folder).',
|
description: 'Triggers when any new file is added (inside of any folder).',
|
||||||
|
@@ -13,6 +13,7 @@ const newFiles = async ($: IGlobalVariable) => {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import newFolders from './new-folders';
|
import newFolders from './new-folders';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Folders',
|
name: 'New folders',
|
||||||
key: 'newFolders',
|
key: 'newFolders',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description:
|
description:
|
||||||
|
@@ -20,6 +20,7 @@ const newFolders = async ($: IGlobalVariable) => {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import updatedFiles from './updated-files';
|
import updatedFiles from './updated-files';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'Updated Files',
|
name: 'Updated files',
|
||||||
key: 'updatedFiles',
|
key: 'updatedFiles',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description:
|
description:
|
||||||
|
@@ -24,6 +24,7 @@ const updatedFiles = async ($: IGlobalVariable) => {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import newFormResponses from './new-form-responses';
|
import newFormResponses from './new-form-responses';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Form Responses',
|
name: 'New form responses',
|
||||||
key: 'newFormResponses',
|
key: 'newFormResponses',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description: 'Triggers when a new form response is submitted.',
|
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 listDrives from './list-drives';
|
||||||
import listSpreadsheets from './list-spreadsheets';
|
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;
|
||||||
|
},
|
||||||
|
};
|
@@ -22,6 +22,7 @@ export default {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -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 addAuthHeader from './common/add-auth-header';
|
||||||
import auth from './auth';
|
import auth from './auth';
|
||||||
import triggers from './triggers';
|
import triggers from './triggers';
|
||||||
|
import actions from './actions';
|
||||||
import dynamicData from './dynamic-data';
|
import dynamicData from './dynamic-data';
|
||||||
|
import dynamicFields from './dynamic-fields';
|
||||||
|
|
||||||
export default defineApp({
|
export default defineApp({
|
||||||
name: 'Google Sheets',
|
name: 'Google Sheets',
|
||||||
@@ -16,5 +18,7 @@ export default defineApp({
|
|||||||
beforeRequest: [addAuthHeader],
|
beforeRequest: [addAuthHeader],
|
||||||
auth,
|
auth,
|
||||||
triggers,
|
triggers,
|
||||||
|
actions,
|
||||||
dynamicData,
|
dynamicData,
|
||||||
|
dynamicFields,
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
import newSpreadsheets from './new-spreadsheets';
|
import newSpreadsheets from './new-spreadsheets';
|
||||||
import newWorksheets from './new-worksheets';
|
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 defineTrigger from '../../../../helpers/define-trigger';
|
||||||
import newSpreadsheets from './new-spreadsheets'
|
import newSpreadsheets from './new-spreadsheets';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Spreadsheets',
|
name: 'New spreadsheets',
|
||||||
key: 'newSpreadsheets',
|
key: 'newSpreadsheets',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description: 'Triggers when you create a new spreadsheet.',
|
description: 'Triggers when you create a new spreadsheet.',
|
||||||
@@ -12,7 +12,8 @@ export default defineTrigger({
|
|||||||
key: 'driveId',
|
key: 'driveId',
|
||||||
type: 'dropdown' as const,
|
type: 'dropdown' as const,
|
||||||
required: false,
|
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,
|
variables: false,
|
||||||
source: {
|
source: {
|
||||||
type: 'query',
|
type: 'query',
|
||||||
|
@@ -13,6 +13,7 @@ const newSpreadsheets = async ($: IGlobalVariable) => {
|
|||||||
|
|
||||||
if ($.step.parameters.driveId) {
|
if ($.step.parameters.driveId) {
|
||||||
params.includeItemsFromAllDrives = true;
|
params.includeItemsFromAllDrives = true;
|
||||||
|
params.corpora = 'drive';
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import newWorksheets from './new-worksheets';
|
import newWorksheets from './new-worksheets';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Worksheets',
|
name: 'New worksheets',
|
||||||
key: 'newWorksheets',
|
key: 'newWorksheets',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description: 'Triggers when you create a new worksheet in a spreadsheet.',
|
description: 'Triggers when you create a new worksheet in a spreadsheet.',
|
||||||
|
@@ -6,15 +6,17 @@ type TMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|||||||
type THeaderEntry = {
|
type THeaderEntry = {
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
type THeaderEntries = THeaderEntry[];
|
type THeaderEntries = THeaderEntry[];
|
||||||
|
|
||||||
function isPossiblyTextBased(contentType: string) {
|
function isPossiblyTextBased(contentType: string) {
|
||||||
if (!contentType) return false;
|
if (!contentType) return false;
|
||||||
|
|
||||||
return contentType.startsWith('application/json')
|
return (
|
||||||
|| contentType.startsWith('text/');
|
contentType.startsWith('application/json') ||
|
||||||
|
contentType.startsWith('text/')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function throwIfFileSizeExceedsLimit(contentLength: string) {
|
function throwIfFileSizeExceedsLimit(contentLength: string) {
|
||||||
@@ -28,7 +30,7 @@ function throwIfFileSizeExceedsLimit(contentLength: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
name: 'Custom Request',
|
name: 'Custom request',
|
||||||
key: 'customRequest',
|
key: 'customRequest',
|
||||||
description: 'Makes a custom HTTP request by providing raw details.',
|
description: 'Makes a custom HTTP request by providing raw details.',
|
||||||
arguments: [
|
arguments: [
|
||||||
@@ -69,10 +71,12 @@ export default defineAction({
|
|||||||
type: 'dynamic' as const,
|
type: 'dynamic' as const,
|
||||||
required: false,
|
required: false,
|
||||||
description: 'Add or remove headers as needed',
|
description: 'Add or remove headers as needed',
|
||||||
value: [{
|
value: [
|
||||||
key: 'Content-Type',
|
{
|
||||||
value: 'application/json'
|
key: 'Content-Type',
|
||||||
}],
|
value: 'application/json',
|
||||||
|
},
|
||||||
|
],
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
label: 'Key',
|
label: 'Key',
|
||||||
@@ -89,9 +93,9 @@ export default defineAction({
|
|||||||
required: true,
|
required: true,
|
||||||
description: 'Header value',
|
description: 'Header value',
|
||||||
variables: true,
|
variables: true,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
@@ -100,30 +104,35 @@ export default defineAction({
|
|||||||
const url = $.step.parameters.url as string;
|
const url = $.step.parameters.url as string;
|
||||||
const headers = $.step.parameters.headers as THeaderEntries;
|
const headers = $.step.parameters.headers as THeaderEntries;
|
||||||
|
|
||||||
const headersObject: Record<string, string> = headers.reduce((result, entry) => {
|
const headersObject: Record<string, string> = headers.reduce(
|
||||||
const key = entry.key?.toLowerCase();
|
(result, entry) => {
|
||||||
const value = entry.value;
|
const key = entry.key?.toLowerCase();
|
||||||
|
const value = entry.value;
|
||||||
|
|
||||||
if (key && value) {
|
if (key && value) {
|
||||||
return {
|
return {
|
||||||
...result,
|
...result,
|
||||||
[entry.key?.toLowerCase()]: entry.value
|
[entry.key?.toLowerCase()]: entry.value,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}, {});
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
let contentType = headersObject['content-type'];
|
let contentType = headersObject['content-type'];
|
||||||
|
|
||||||
// in case HEAD request is not supported by the URL
|
// in case HEAD request is not supported by the URL
|
||||||
try {
|
try {
|
||||||
const metadataResponse = await $.http.head(url, { headers: headersObject });
|
const metadataResponse = await $.http.head(url, {
|
||||||
|
headers: headersObject,
|
||||||
|
});
|
||||||
contentType = metadataResponse.headers['content-type'];
|
contentType = metadataResponse.headers['content-type'];
|
||||||
|
|
||||||
throwIfFileSizeExceedsLimit(metadataResponse.headers['content-length']);
|
throwIfFileSizeExceedsLimit(metadataResponse.headers['content-length']);
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
} catch { }
|
} catch {}
|
||||||
|
|
||||||
const requestData: AxiosRequestConfig = {
|
const requestData: AxiosRequestConfig = {
|
||||||
url,
|
url,
|
||||||
|
@@ -18,7 +18,9 @@ const hashItem = async (value: string) => {
|
|||||||
|
|
||||||
const newItemsInFeed = async ($: IGlobalVariable) => {
|
const newItemsInFeed = async ($: IGlobalVariable) => {
|
||||||
const { data } = await $.http.get($.step.parameters.feedUrl as string);
|
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);
|
const parsedData = parser.parse(data);
|
||||||
|
|
||||||
// naive implementation to cover atom and rss feeds
|
// naive implementation to cover atom and rss feeds
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
import defineTrigger from "../../../../helpers/define-trigger";
|
import defineTrigger from '../../../../helpers/define-trigger';
|
||||||
import getBalanceTransactions from "./get-balance-transactions";
|
import getBalanceTransactions from './get-balance-transactions';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Balance Transactions',
|
name: 'New balance transactions',
|
||||||
key: 'newBalanceTransactions',
|
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,
|
pollInterval: 15,
|
||||||
async run($) {
|
async run($) {
|
||||||
await getBalanceTransactions($)
|
await getBalanceTransactions($);
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
import defineTrigger from "../../../../helpers/define-trigger";
|
import defineTrigger from '../../../../helpers/define-trigger';
|
||||||
import getPayouts from "./get-payouts";
|
import getPayouts from './get-payouts';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'New Payouts',
|
name: 'New payouts',
|
||||||
key: 'newPayouts',
|
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,
|
pollInterval: 15,
|
||||||
async run($) {
|
async run($) {
|
||||||
await getPayouts($)
|
await getPayouts($);
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
import defineAction from '../../../../helpers/define-action';
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
name: 'Create Task',
|
name: 'Create task',
|
||||||
key: 'createTask',
|
key: 'createTask',
|
||||||
description: 'Creates a Task in Todoist',
|
description: 'Creates a Task in Todoist',
|
||||||
arguments: [
|
arguments: [
|
||||||
@@ -59,8 +59,7 @@ export default defineAction({
|
|||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
required: true,
|
required: true,
|
||||||
variables: true,
|
variables: true,
|
||||||
description:
|
description: 'Task content, may be markdown. Example: "Foo"',
|
||||||
'Task content, may be markdown. Example: "Foo"',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Description',
|
label: 'Description',
|
||||||
@@ -68,22 +67,16 @@ export default defineAction({
|
|||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
required: false,
|
required: false,
|
||||||
variables: true,
|
variables: true,
|
||||||
description:
|
description: 'Task description, may be markdown. Example: "Foo"',
|
||||||
'Task description, may be markdown. Example: "Foo"',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
async run($) {
|
async run($) {
|
||||||
const requestPath = `/tasks`;
|
const requestPath = `/tasks`;
|
||||||
const {
|
const { projectId, sectionId, labels, content, description } =
|
||||||
projectId,
|
$.step.parameters;
|
||||||
sectionId,
|
|
||||||
labels,
|
|
||||||
content,
|
|
||||||
description
|
|
||||||
} = $.step.parameters;
|
|
||||||
|
|
||||||
const labelsArray = (labels as string).split(',')
|
const labelsArray = (labels as string).split(',');
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
content,
|
content,
|
||||||
@@ -91,7 +84,7 @@ export default defineAction({
|
|||||||
project_id: projectId || null,
|
project_id: projectId || null,
|
||||||
labels: labelsArray || null,
|
labels: labelsArray || null,
|
||||||
section_id: sectionId || null,
|
section_id: sectionId || null,
|
||||||
}
|
};
|
||||||
|
|
||||||
const response = await $.http.post(requestPath, payload);
|
const response = await $.http.post(requestPath, payload);
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
|
|||||||
import getActiveTasks from './get-tasks';
|
import getActiveTasks from './get-tasks';
|
||||||
|
|
||||||
export default defineTrigger({
|
export default defineTrigger({
|
||||||
name: 'Get Active Tasks',
|
name: 'Get active tasks',
|
||||||
key: 'getActiveTasks',
|
key: 'getActiveTasks',
|
||||||
pollInterval: 15,
|
pollInterval: 15,
|
||||||
description: 'Triggers when new Task(s) are found',
|
description: 'Triggers when new Task(s) are found',
|
||||||
|
@@ -28,7 +28,7 @@ export default defineTrigger({
|
|||||||
{
|
{
|
||||||
name: 'parameters.valueType',
|
name: 'parameters.valueType',
|
||||||
value: 'sid',
|
value: 'sid',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -37,12 +37,14 @@ export default defineTrigger({
|
|||||||
async testRun($) {
|
async testRun($) {
|
||||||
await fetchMessages($);
|
await fetchMessages($);
|
||||||
|
|
||||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
const lastExecutionStep = await $.getLastExecutionStep();
|
||||||
|
|
||||||
|
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||||
$.pushTriggerItem({
|
$.pushTriggerItem({
|
||||||
raw: $.lastExecutionStep.dataOut,
|
raw: lastExecutionStep.dataOut,
|
||||||
meta: {
|
meta: {
|
||||||
internalId: '',
|
internalId: '',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import defineAction from '../../../../helpers/define-action';
|
import defineAction from '../../../../helpers/define-action';
|
||||||
|
|
||||||
export default defineAction({
|
export default defineAction({
|
||||||
name: 'Create Tweet',
|
name: 'Create tweet',
|
||||||
key: 'createTweet',
|
key: 'createTweet',
|
||||||
description: 'Create a tweet.',
|
description: 'Create a tweet.',
|
||||||
arguments: [
|
arguments: [
|
||||||
|
@@ -8,12 +8,14 @@ export default defineTrigger({
|
|||||||
description: 'Triggers when the webhook receives a request.',
|
description: 'Triggers when the webhook receives a request.',
|
||||||
|
|
||||||
async testRun($) {
|
async testRun($) {
|
||||||
if (!isEmpty($.lastExecutionStep?.dataOut)) {
|
const lastExecutionStep = await $.getLastExecutionStep();
|
||||||
|
|
||||||
|
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||||
$.pushTriggerItem({
|
$.pushTriggerItem({
|
||||||
raw: $.lastExecutionStep.dataOut,
|
raw: lastExecutionStep.dataOut,
|
||||||
meta: {
|
meta: {
|
||||||
internalId: '',
|
internalId: '',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -9,6 +9,7 @@ type AppConfig = {
|
|||||||
webAppUrl: string;
|
webAppUrl: string;
|
||||||
webhookUrl: string;
|
webhookUrl: string;
|
||||||
appEnv: string;
|
appEnv: string;
|
||||||
|
logLevel: string;
|
||||||
isDev: boolean;
|
isDev: boolean;
|
||||||
isProd: boolean;
|
isProd: boolean;
|
||||||
postgresDatabase: string;
|
postgresDatabase: string;
|
||||||
@@ -80,6 +81,7 @@ const appConfig: AppConfig = {
|
|||||||
protocol,
|
protocol,
|
||||||
port,
|
port,
|
||||||
appEnv: appEnv,
|
appEnv: appEnv,
|
||||||
|
logLevel: process.env.LOG_LEVEL || 'info',
|
||||||
isDev: appEnv === 'development',
|
isDev: appEnv === 'development',
|
||||||
isProd: appEnv === 'production',
|
isProd: appEnv === 'production',
|
||||||
version: process.env.npm_package_version,
|
version: process.env.npm_package_version,
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
|
import Crypto from 'node:crypto';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import bcrypt from 'bcrypt';
|
|
||||||
import { IRequest, ITriggerItem } from '@automatisch/types';
|
import { IRequest, ITriggerItem } from '@automatisch/types';
|
||||||
|
|
||||||
|
import logger from '../../helpers/logger';
|
||||||
import Flow from '../../models/flow';
|
import Flow from '../../models/flow';
|
||||||
import { processTrigger } from '../../services/trigger';
|
import { processTrigger } from '../../services/trigger';
|
||||||
import actionQueue from '../../queues/action';
|
import actionQueue from '../../queues/action';
|
||||||
@@ -13,8 +14,19 @@ import {
|
|||||||
} from '../../helpers/remove-job-configuration';
|
} from '../../helpers/remove-job-configuration';
|
||||||
|
|
||||||
export default async (request: IRequest, response: Response) => {
|
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()
|
const flow = await Flow.query()
|
||||||
.findById(request.params.flowId)
|
.findById(flowId)
|
||||||
.throwIfNotFound();
|
.throwIfNotFound();
|
||||||
|
|
||||||
const user = await flow.$relatedQuery('user');
|
const user = await flow.$relatedQuery('user');
|
||||||
@@ -56,29 +68,19 @@ export default async (request: IRequest, response: Response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// in case trigger type is 'webhook'
|
// in case trigger type is 'webhook'
|
||||||
let payload = request.body;
|
if (!isWebhookApp) {
|
||||||
let rawInternalId: string | Buffer = request.rawBody;
|
computedRequestPayload = request.body;
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerItem: ITriggerItem = {
|
const triggerItem: ITriggerItem = {
|
||||||
raw: payload,
|
raw: computedRequestPayload,
|
||||||
meta: {
|
meta: {
|
||||||
internalId: await bcrypt.hash(rawInternalId, 1),
|
internalId: Crypto.randomUUID(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const { flowId, executionId } = await processTrigger({
|
const { executionId } = await processTrigger({
|
||||||
flowId: flow.id,
|
flowId,
|
||||||
stepId: triggerStep.id,
|
stepId: triggerStep.id,
|
||||||
triggerItem,
|
triggerItem,
|
||||||
testRun,
|
testRun,
|
||||||
|
@@ -9,7 +9,7 @@ export default class BaseError extends Error {
|
|||||||
try {
|
try {
|
||||||
computedError = JSON.parse(error as string);
|
computedError = JSON.parse(error as string);
|
||||||
} catch {
|
} catch {
|
||||||
computedError = typeof error === 'string' ? { error } : error;
|
computedError = (typeof error === 'string' || Array.isArray(error)) ? { error } : error;
|
||||||
}
|
}
|
||||||
|
|
||||||
let computedMessage: string;
|
let computedMessage: string;
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
import Context from '../../types/express/context';
|
import Context from '../../types/express/context';
|
||||||
import axios from 'axios';
|
|
||||||
import globalVariable from '../../helpers/global-variable';
|
import globalVariable from '../../helpers/global-variable';
|
||||||
import App from '../../models/app';
|
import App from '../../models/app';
|
||||||
import GenerateAuthUrlError from '../../errors/generate-auth-url';
|
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
input: {
|
input: {
|
||||||
@@ -31,12 +29,7 @@ const generateAuthUrl = async (
|
|||||||
const app = await App.findOneByKey(connection.key);
|
const app = await App.findOneByKey(connection.key);
|
||||||
|
|
||||||
const $ = await globalVariable({ connection, app });
|
const $ = await globalVariable({ connection, app });
|
||||||
try {
|
await authInstance.generateAuthUrl($);
|
||||||
await authInstance.generateAuthUrl($);
|
|
||||||
await axios.get(connection.formattedData.url as string);
|
|
||||||
} catch (error) {
|
|
||||||
throw new GenerateAuthUrlError(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection.formattedData;
|
return connection.formattedData;
|
||||||
};
|
};
|
||||||
|
@@ -80,9 +80,10 @@ const globalVariable = async (
|
|||||||
testRun,
|
testRun,
|
||||||
exit: () => {
|
exit: () => {
|
||||||
throw new EarlyExitError();
|
throw new EarlyExitError();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
lastExecutionStep: (await step?.getLastExecutionStep())?.toJSON(),
|
getLastExecutionStep: async () =>
|
||||||
|
(await step?.getLastExecutionStep())?.toJSON(),
|
||||||
triggerOutput: {
|
triggerOutput: {
|
||||||
data: [],
|
data: [],
|
||||||
},
|
},
|
||||||
|
@@ -9,10 +9,6 @@ const levels = {
|
|||||||
debug: 4,
|
debug: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
const level = () => {
|
|
||||||
return appConfig.appEnv === 'development' ? 'debug' : 'info';
|
|
||||||
};
|
|
||||||
|
|
||||||
const colors = {
|
const colors = {
|
||||||
error: 'red',
|
error: 'red',
|
||||||
warn: 'yellow',
|
warn: 'yellow',
|
||||||
@@ -41,7 +37,7 @@ const transports = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const logger = winston.createLogger({
|
export const logger = winston.createLogger({
|
||||||
level: level(),
|
level: appConfig.logLevel,
|
||||||
levels,
|
levels,
|
||||||
format,
|
format,
|
||||||
transports,
|
transports,
|
||||||
|
@@ -10,7 +10,12 @@ const webUIHandler = async (app: Application) => {
|
|||||||
const indexHtml = join(dirname(webAppPath), 'build', 'index.html');
|
const indexHtml = join(dirname(webAppPath), 'build', 'index.html');
|
||||||
|
|
||||||
app.use(express.static(webBuildPath));
|
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;
|
export default webUIHandler;
|
||||||
|
@@ -91,6 +91,7 @@ class Flow extends Base {
|
|||||||
async lastInternalId() {
|
async lastInternalId() {
|
||||||
const lastExecution = await this.$relatedQuery('executions')
|
const lastExecution = await this.$relatedQuery('executions')
|
||||||
.orderBy('created_at', 'desc')
|
.orderBy('created_at', 'desc')
|
||||||
|
.limit(1)
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
return lastExecution ? (lastExecution as Execution).internalId : null;
|
return lastExecution ? (lastExecution as Execution).internalId : null;
|
||||||
|
@@ -117,6 +117,7 @@ class Step extends Base {
|
|||||||
async getLastExecutionStep() {
|
async getLastExecutionStep() {
|
||||||
const lastExecutionStep = await this.$relatedQuery('executionSteps')
|
const lastExecutionStep = await this.$relatedQuery('executionSteps')
|
||||||
.orderBy('created_at', 'desc')
|
.orderBy('created_at', 'desc')
|
||||||
|
.limit(1)
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
return lastExecutionStep;
|
return lastExecutionStep;
|
||||||
|
@@ -102,7 +102,7 @@ class User extends Base {
|
|||||||
to: 'users.id',
|
to: 'users.id',
|
||||||
},
|
},
|
||||||
filter(builder: ExtendedQueryBuilder<UsageData>) {
|
filter(builder: ExtendedQueryBuilder<UsageData>) {
|
||||||
builder.orderBy('created_at', 'desc').first();
|
builder.orderBy('created_at', 'desc').limit(1).first();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
subscriptions: {
|
subscriptions: {
|
||||||
@@ -121,7 +121,7 @@ class User extends Base {
|
|||||||
to: 'users.id',
|
to: 'users.id',
|
||||||
},
|
},
|
||||||
filter(builder: ExtendedQueryBuilder<Subscription>) {
|
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 ExecutionStep from '../models/execution-step';
|
||||||
import computeParameters from '../helpers/compute-parameters';
|
import computeParameters from '../helpers/compute-parameters';
|
||||||
import globalVariable from '../helpers/global-variable';
|
import globalVariable from '../helpers/global-variable';
|
||||||
|
import { logger } from '../helpers/logger';
|
||||||
import HttpError from '../errors/http';
|
import HttpError from '../errors/http';
|
||||||
import EarlyExitError from '../errors/early-exit';
|
import EarlyExitError from '../errors/early-exit';
|
||||||
import AlreadyProcessedError from '../errors/already-processed';
|
import AlreadyProcessedError from '../errors/already-processed';
|
||||||
@@ -53,6 +54,8 @@ export const processAction = async (options: ProcessActionOptions) => {
|
|||||||
const shouldNotConsiderAsError = shouldEarlyExit || shouldNotProcess;
|
const shouldNotConsiderAsError = shouldEarlyExit || shouldNotProcess;
|
||||||
|
|
||||||
if (!shouldNotConsiderAsError) {
|
if (!shouldNotConsiderAsError) {
|
||||||
|
logger.error(error);
|
||||||
|
|
||||||
if (error instanceof HttpError) {
|
if (error instanceof HttpError) {
|
||||||
$.actionOutput.error = error.details;
|
$.actionOutput.error = error.details;
|
||||||
} else {
|
} else {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user