Compare commits

..

6 Commits

Author SHA1 Message Date
Faruk AYDIN
caffea49ce docs: Add postgres schema to the environment variables 2023-04-17 14:52:19 +02:00
Faruk AYDIN
272bd9dc62 feat: Use postgres schema instead of database schema 2023-04-17 14:52:19 +02:00
Faruk AYDIN
a4e7824109 chore: No need to specify schema in .env-example file 2023-04-17 14:52:19 +02:00
Shehab Ghazy
5ed7fc8b7c Update .env-example 2023-04-17 14:52:19 +02:00
Shehab Ghazy
c4d4b2a2a8 Update knexfile.ts 2023-04-17 14:52:19 +02:00
Shehab Ghazy
47212c37c2 honor schema from env 2023-04-17 14:52:19 +02:00
189 changed files with 292 additions and 4799 deletions

View File

@@ -1,8 +0,0 @@
**/node_modules/
**/dist/
**/logs/
**/.devcontainer
**/.github
**/.vscode
packages/docs
packages/e2e-test

3
.gitignore vendored
View File

@@ -125,6 +125,3 @@ dist
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# MacOS finder preferences
.DS_store

View File

@@ -1,5 +1,5 @@
The Automatisch Enterprise license (the “Enterprise License”)
Copyright (c) 2023-present AB Software GmbH.
Copyright (c) 2023 Ömer Faruk Aydın, Ali Barın.
With regard to the Automatisch Software:

View File

@@ -4,7 +4,7 @@ WORKDIR /automatisch
RUN \
apk --no-cache add --virtual build-dependencies python3 build-base && \
yarn global add @automatisch/cli@0.7.1 --network-timeout 1000000 && \
yarn global add @automatisch/cli@0.5.0 --network-timeout 1000000 && \
rm -rf /usr/local/share/.cache/ && \
apk del build-dependencies

View File

@@ -1,19 +0,0 @@
# syntax=docker/dockerfile:1
FROM node:16-alpine
WORKDIR /automatisch
ENV PORT 3000
RUN ls -lna
# copy the app, note .dockerignore
COPY . ./
RUN yarn
RUN yarn lerna bootstrap
RUN yarn lerna run --scope=@*/{web,backend,cli} build
COPY ./docker/entrypoint-cloud.sh /entrypoint-cloud.sh
EXPOSE 3000
ENTRYPOINT ["sh", "/entrypoint-cloud.sh"]

View File

@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM automatischio/automatisch:0.7.1
FROM automatischio/automatisch:0.5.0
WORKDIR /automatisch
RUN apk add --no-cache openssl dos2unix

View File

@@ -1,9 +0,0 @@
#!/bin/sh
set -e
if [ -n "$WORKER" ]; then
yarn automatisch start-worker
else
yarn automatisch start
fi

View File

@@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
"version": "0.7.1",
"version": "0.5.0",
"npmClient": "yarn",
"useWorkspaces": true,
"command": {

View File

@@ -1,6 +1,6 @@
{
"name": "@automatisch/backend",
"version": "0.7.1",
"version": "0.5.0",
"license": "See LICENSE file",
"description": "The open source Zapier alternative. Build workflow automation without spending time and money.",
"scripts": {
@@ -17,12 +17,12 @@
"db:migration:create": "knex migrate:make",
"db:rollback": "knex migrate:rollback",
"db:migrate": "knex migrate:latest",
"copy-statics": "copyfiles src/**/*.{graphql,json,svg,hbs} dist",
"copy-statics": "copyfiles src/**/*.{graphql,json,svg} dist",
"prepack": "yarn build",
"prebuild": "rm -rf ./dist"
},
"dependencies": {
"@automatisch/web": "^0.7.1",
"@automatisch/web": "^0.5.0",
"@bull-board/express": "^3.10.1",
"@graphql-tools/graphql-file-loader": "^7.3.4",
"@graphql-tools/load": "^7.5.2",
@@ -100,7 +100,7 @@
"url": "https://github.com/automatisch/automatisch/issues"
},
"devDependencies": {
"@automatisch/types": "^0.7.1",
"@automatisch/types": "^0.5.0",
"@types/bcrypt": "^5.0.0",
"@types/bull": "^3.15.8",
"@types/cors": "^2.8.12",

View File

@@ -2,7 +2,7 @@ import qs from 'qs';
import defineAction from '../../../../helpers/define-action';
export default defineAction({
name: 'Translate text',
name: 'Translate Text',
key: 'translateText',
description: 'Translates text from one language to another.',
arguments: [

View File

@@ -1,7 +1,7 @@
import defineAction from '../../../../helpers/define-action';
export default defineAction({
name: 'Delay for',
name: 'Delay For',
key: 'delayFor',
description:
'Delays the execution of the next action by a specified amount of time.',

View File

@@ -1,7 +1,7 @@
import defineAction from '../../../../helpers/define-action';
export default defineAction({
name: 'Delay until',
name: 'Delay Until',
key: 'delayUntil',
description:
'Delays the execution of the next action until a specified date.',

View File

@@ -10,7 +10,7 @@ type TGroupItem = {
type TGroup = Record<'and', TGroupItem[]>;
const isEqual = (a: string, b: string) => a === b;
const isNotEqual = (a: string, b: string) => !isEqual(a, b);
const isNotEqual = (a: string, b: string) => !isEqual(a, b)
const isGreaterThan = (a: string, b: string) => Number(a) > Number(b);
const isLessThan = (a: string, b: string) => Number(a) < Number(b);
const isGreaterThanOrEqual = (a: string, b: string) => Number(a) >= Number(b);
@@ -18,36 +18,6 @@ const isLessThanOrEqual = (a: string, b: string) => Number(a) <= Number(b);
const contains = (a: string, b: string) => a.includes(b);
const doesNotContain = (a: string, b: string) => !contains(a, b);
const shouldContinue = (orGroups: TGroup[]) => {
let atLeastOneGroupMatches = false;
for (const group of orGroups) {
let groupMatches = true;
for (const condition of group.and) {
const conditionMatches = operate(
condition.operator,
condition.key,
condition.value
);
if (!conditionMatches) {
groupMatches = false;
break;
}
}
if (groupMatches) {
atLeastOneGroupMatches = true;
break;
}
}
return atLeastOneGroupMatches;
}
type TOperatorFunc = (a: string, b: string) => boolean;
type TOperators = {
@@ -96,7 +66,7 @@ export default defineAction({
return groups;
}, []);
if (!shouldContinue(orGroups)) {
if (matchingGroups.length === 0) {
$.execution.exit();
}

View File

@@ -20,14 +20,12 @@ export default defineTrigger({
],
async testRun($) {
const lastExecutionStep = await $.getLastExecutionStep();
if (!isEmpty(lastExecutionStep?.dataOut)) {
if (!isEmpty($.lastExecutionStep?.dataOut)) {
$.pushTriggerItem({
raw: lastExecutionStep.dataOut,
raw: $.lastExecutionStep.dataOut,
meta: {
internalId: '',
},
}
});
}
},
@@ -37,15 +35,20 @@ export default defineTrigger({
name: $.flow.id,
type: 'POST',
url: $.webhookUrl,
filters: [$.step.parameters.filters],
filters: [$.step.parameters.filters]
};
const { data } = await $.http.post(`/v2/public/api/webhooks`, payload);
const { data } = await $.http.post(
`/v2/public/api/webhooks`,
payload
);
await $.flow.setRemoteWebhookId(data.id);
},
async unregisterHook($) {
await $.http.delete(`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`);
await $.http.delete(
`/v2/public/api/webhooks/${$.flow.remoteWebhookId}`
);
},
});

View File

@@ -1,2 +0,0 @@
<!-- 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>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,24 +0,0 @@
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(),
});
}

View File

@@ -1,63 +0,0 @@
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,
};

View File

@@ -1,9 +0,0 @@
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;

View File

@@ -1,24 +0,0 @@
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;

View File

@@ -1,41 +0,0 @@
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;

View File

@@ -1,11 +0,0 @@
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;

View File

@@ -1,15 +0,0 @@
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;

View File

@@ -1,11 +0,0 @@
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;

View File

@@ -1,33 +0,0 @@
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;
}

View File

@@ -1,13 +0,0 @@
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;

View File

@@ -1,3 +0,0 @@
import listProjects from './list-projects';
export default [listProjects];

View File

@@ -1,33 +0,0 @@
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;
},
};

View File

@@ -1 +0,0 @@

View File

@@ -1,21 +0,0 @@
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,
});

View File

@@ -1,27 +0,0 @@
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);

View File

@@ -1,159 +0,0 @@
// 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,
},
],
},
},
};

View File

@@ -1,27 +0,0 @@
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);

View File

@@ -1,74 +0,0 @@
// 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',
},
},
};

View File

@@ -1,45 +0,0 @@
// 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',
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,38 +0,0 @@
// 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,
},
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,29 +0,0 @@
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,
];

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,159 +0,0 @@
// 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,
},
],
},
},
};

View File

@@ -1,25 +0,0 @@
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);

View File

@@ -1,60 +0,0 @@
// 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,
};

View File

@@ -1,89 +0,0 @@
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}`
);
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,208 +0,0 @@
// 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',
},
],
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,74 +0,0 @@
// 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',
},
},
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,254 +0,0 @@
// 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',
},
},
],
};

View File

@@ -1,62 +0,0 @@
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);

View File

@@ -1,75 +0,0 @@
// 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,
};

View File

@@ -1,25 +0,0 @@
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);

View File

@@ -1,72 +0,0 @@
// 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',
},
},
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,43 +0,0 @@
// 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,
};

View File

@@ -1,24 +0,0 @@
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;
};

View File

@@ -1,26 +0,0 @@
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);

View File

@@ -1,48 +0,0 @@
// 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',
},
};

View File

@@ -1,7 +1,7 @@
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
export default {
name: 'List folders',
name: 'List Folders',
key: 'listFolders',
async run($: IGlobalVariable) {
@@ -11,20 +11,13 @@ export default {
data: [],
};
const params: Record<string, unknown> = {
const params = {
q: `mimeType='application/vnd.google-apps.folder'`,
orderBy: 'createdTime desc',
pageToken: undefined as unknown as string,
pageSize: 1000,
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get(
`https://www.googleapis.com/drive/v3/files`,

View File

@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
import newFilesInFolder from './new-files-in-folder';
export default defineTrigger({
name: 'New files in folder',
name: 'New Files in Folder',
key: 'newFilesInFolder',
pollInterval: 15,
description:
@@ -32,7 +32,6 @@ export default defineTrigger({
key: 'folderId',
type: 'dropdown' as const,
required: false,
dependsOn: ['parameters.driveId'],
description:
'Check a specific folder for new files. Please note: new files added to subfolders inside the folder you choose here will NOT trigger this flow. Defaults to the top-level folder if none is picked.',
variables: false,
@@ -44,10 +43,6 @@ export default defineTrigger({
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.driveId',
value: '{parameters.driveId}',
},
],
},
},

View File

@@ -7,21 +7,15 @@ const newFilesInFolder = async ($: IGlobalVariable) => {
} else {
q += ` and parents in 'root'`;
}
const params: Record<string, unknown> = {
const params = {
pageToken: undefined as unknown as string,
orderBy: 'createdTime desc',
fields: '*',
pageSize: 1000,
q,
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get(`/v3/files`, { params });
params.pageToken = data.nextPageToken;

View File

@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
import newFiles from './new-files';
export default defineTrigger({
name: 'New files',
name: 'New Files',
key: 'newFiles',
pollInterval: 15,
description: 'Triggers when any new file is added (inside of any folder).',

View File

@@ -1,21 +1,15 @@
import { IGlobalVariable } from '@automatisch/types';
const newFiles = async ($: IGlobalVariable) => {
const params: Record<string, unknown> = {
const params = {
pageToken: undefined as unknown as string,
orderBy: 'createdTime desc',
fields: '*',
pageSize: 1000,
q: `mimeType!='application/vnd.google-apps.folder'`,
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get('/v3/files', { params });
params.pageToken = data.nextPageToken;

View File

@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
import newFolders from './new-folders';
export default defineTrigger({
name: 'New folders',
name: 'New Folders',
key: 'newFolders',
pollInterval: 15,
description:
@@ -32,7 +32,6 @@ export default defineTrigger({
key: 'folderId',
type: 'dropdown' as const,
required: false,
dependsOn: ['parameters.driveId'],
description:
'Check a specific folder for new subfolders. Please note: new folders added to subfolders inside the folder you choose here will NOT trigger this flow. Defaults to the top-level folder if none is picked.',
variables: false,
@@ -44,10 +43,6 @@ export default defineTrigger({
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.driveId',
value: '{parameters.driveId}',
},
],
},
},

View File

@@ -8,21 +8,15 @@ const newFolders = async ($: IGlobalVariable) => {
q += ` and parents in 'root'`;
}
const params: Record<string, unknown> = {
const params = {
pageToken: undefined as unknown as string,
orderBy: 'createdTime desc',
fields: '*',
pageSize: 1000,
q,
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get(`/v3/files`, { params });
params.pageToken = data.nextPageToken;

View File

@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
import updatedFiles from './updated-files';
export default defineTrigger({
name: 'Updated files',
name: 'Updated Files',
key: 'updatedFiles',
pollInterval: 15,
description:
@@ -32,7 +32,6 @@ export default defineTrigger({
key: 'folderId',
type: 'dropdown' as const,
required: false,
dependsOn: ['parameters.driveId'],
description:
'Check a specific folder for updated files. Please note: files located in subfolders of the folder you choose here will NOT trigger this flow. Defaults to the top-level folder if none is picked.',
source: {
@@ -43,10 +42,6 @@ export default defineTrigger({
name: 'key',
value: 'listFolders',
},
{
name: 'parameters.driveId',
value: '{parameters.driveId}',
},
],
},
},

View File

@@ -12,21 +12,15 @@ const updatedFiles = async ($: IGlobalVariable) => {
q += ` and parents in 'root'`;
}
const params: Record<string, unknown> = {
const params = {
pageToken: undefined as unknown as string,
orderBy: 'modifiedTime desc',
fields: '*',
pageSize: 1000,
q,
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get(`/v3/files`, { params });
params.pageToken = data.nextPageToken;

View File

@@ -2,7 +2,7 @@ import defineTrigger from '../../../../helpers/define-trigger';
import newFormResponses from './new-form-responses';
export default defineTrigger({
name: 'New form responses',
name: 'New Form Responses',
key: 'newFormResponses',
pollInterval: 15,
description: 'Triggers when a new form response is submitted.',

View File

@@ -1,145 +0,0 @@
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,
});
},
});

View File

@@ -1,3 +0,0 @@
import createSpreadsheetRow from './create-spreadsheet-row';
export default [createSpreadsheetRow];

View File

@@ -1,6 +1,3 @@
import listDrives from './list-drives';
import listSpreadsheets from './list-spreadsheets';
import listWorksheets from './list-worksheets';
import listColumns from './list-columns';
export default [listDrives, listSpreadsheets, listWorksheets, listColumns];
export default [listDrives];

View File

@@ -1,70 +0,0 @@
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;
},
};

View File

@@ -1,47 +0,0 @@
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
export default {
name: 'List spreadsheets',
key: 'listSpreadsheets',
async run($: IGlobalVariable) {
const spreadsheets: {
data: IJSONObject[];
} = {
data: [],
};
const params: Record<string, unknown> = {
q: `mimeType='application/vnd.google-apps.spreadsheet'`,
pageSize: 100,
pageToken: undefined as unknown as string,
orderBy: 'createdTime desc',
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get(
`https://www.googleapis.com/drive/v3/files`,
{ params }
);
params.pageToken = data.nextPageToken;
if (data.files?.length) {
for (const file of data.files) {
spreadsheets.data.push({
value: file.id,
name: file.name,
});
}
}
} while (params.pageToken);
return spreadsheets;
},
};

View File

@@ -1,42 +0,0 @@
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;
},
};

View File

@@ -1,3 +0,0 @@
import listSheetHeaders from './list-sheet-headers';
export default [listSheetHeaders];

View File

@@ -1,71 +0,0 @@
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;
},
};

View File

@@ -2,9 +2,7 @@ import defineApp from '../../helpers/define-app';
import addAuthHeader from './common/add-auth-header';
import auth from './auth';
import triggers from './triggers';
import actions from './actions';
import dynamicData from './dynamic-data';
import dynamicFields from './dynamic-fields';
export default defineApp({
name: 'Google Sheets',
@@ -18,7 +16,5 @@ export default defineApp({
beforeRequest: [addAuthHeader],
auth,
triggers,
actions,
dynamicData,
dynamicFields,
});

View File

@@ -1,11 +1,3 @@
import newSpreadsheets from './new-spreadsheets';
import newWorksheets from './new-worksheets';
import newSpreadsheetRows from './new-spreadsheet-rows';
import newOrUpdatedSpreadsheetRows from './new-or-updated-spreadsheet-rows';
export default [
newSpreadsheets,
newWorksheets,
newSpreadsheetRows,
newOrUpdatedSpreadsheetRows,
];
export default [newSpreadsheets];

View File

@@ -1,109 +0,0 @@
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($);
},
});

View File

@@ -1,50 +0,0 @@
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;

View File

@@ -1,82 +0,0 @@
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($);
},
});

View File

@@ -1,46 +0,0 @@
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;

View File

@@ -1,8 +1,8 @@
import defineTrigger from '../../../../helpers/define-trigger';
import newSpreadsheets from './new-spreadsheets';
import newSpreadsheets from './new-spreadsheets'
export default defineTrigger({
name: 'New spreadsheets',
name: 'New Spreadsheets',
key: 'newSpreadsheets',
pollInterval: 15,
description: 'Triggers when you create a new spreadsheet.',
@@ -12,8 +12,7 @@ export default defineTrigger({
key: 'driveId',
type: 'dropdown' as const,
required: false,
description:
'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
description: 'The Google Drive where your spreadsheet resides. If nothing is selected, then your personal Google Drive will be used.',
variables: false,
source: {
type: 'query',
@@ -31,4 +30,4 @@ export default defineTrigger({
async run($) {
await newSpreadsheets($);
},
});
});

View File

@@ -1,21 +1,15 @@
import { IGlobalVariable } from '@automatisch/types';
const newSpreadsheets = async ($: IGlobalVariable) => {
const params: Record<string, unknown> = {
const params = {
pageToken: undefined as unknown as string,
orderBy: 'createdTime desc',
q: `mimeType='application/vnd.google-apps.spreadsheet'`,
fields: '*',
pageSize: 1000,
driveId: $.step.parameters.driveId,
supportsAllDrives: true,
};
if ($.step.parameters.driveId) {
params.includeItemsFromAllDrives = true;
params.corpora = 'drive';
}
do {
const { data } = await $.http.get(
'https://www.googleapis.com/drive/v3/files',

View File

@@ -1,57 +0,0 @@
import defineTrigger from '../../../../helpers/define-trigger';
import newWorksheets from './new-worksheets';
export default defineTrigger({
name: 'New worksheets',
key: 'newWorksheets',
pollInterval: 15,
description: 'Triggers when you create a new worksheet 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}',
},
],
},
},
],
async run($) {
await newWorksheets($);
},
});

View File

@@ -1,28 +0,0 @@
import { IGlobalVariable } from '@automatisch/types';
const newWorksheets = async ($: IGlobalVariable) => {
const params = {
pageToken: undefined as unknown as string,
};
do {
const { data } = await $.http.get(
`/v4/spreadsheets/${$.step.parameters.spreadsheetId}`,
{ params }
);
params.pageToken = data.nextPageToken;
if (data.sheets?.length) {
for (const sheet of data.sheets.reverse()) {
$.pushTriggerItem({
raw: sheet,
meta: {
internalId: sheet.properties.sheetId.toString(),
},
});
}
}
} while (params.pageToken);
};
export default newWorksheets;

View File

@@ -1,4 +1,3 @@
import type { AxiosRequestConfig } from 'axios';
import defineAction from '../../../../helpers/define-action';
type TMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
@@ -6,31 +5,12 @@ type TMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
type THeaderEntry = {
key: string;
value: string;
};
}
type THeaderEntries = THeaderEntry[];
function isPossiblyTextBased(contentType: string) {
if (!contentType) return false;
return (
contentType.startsWith('application/json') ||
contentType.startsWith('text/')
);
}
function throwIfFileSizeExceedsLimit(contentLength: string) {
const maxFileSize = 25 * 1024 * 1024; // 25MB
if (Number(contentLength) > maxFileSize) {
throw new Error(
`Response is too large. Maximum size is 25MB. Actual size is ${contentLength}`
);
}
}
export default defineAction({
name: 'Custom request',
name: 'Custom Request',
key: 'customRequest',
description: 'Makes a custom HTTP request by providing raw details.',
arguments: [
@@ -71,12 +51,10 @@ export default defineAction({
type: 'dynamic' as const,
required: false,
description: 'Add or remove headers as needed',
value: [
{
key: 'Content-Type',
value: 'application/json',
},
],
value: [{
key: 'Content-Type',
value: 'application/json'
}],
fields: [
{
label: 'Key',
@@ -93,9 +71,9 @@ export default defineAction({
required: true,
description: 'Header value',
variables: true,
},
}
],
},
}
],
async run($) {
@@ -103,56 +81,29 @@ export default defineAction({
const data = $.step.parameters.data as string;
const url = $.step.parameters.url as string;
const headers = $.step.parameters.headers as THeaderEntries;
const maxFileSize = 25 * 1024 * 1024; // 25MB
const headersObject: Record<string, string> = headers.reduce(
(result, entry) => {
const key = entry.key?.toLowerCase();
const value = entry.value;
const headersObject = headers.reduce((result, entry) => ({ ...result, [entry.key]: entry.value }), {})
if (key && value) {
return {
...result,
[entry.key?.toLowerCase()]: entry.value,
};
}
const metadataResponse = await $.http.head(url, { headers: headersObject });
return result;
},
{}
);
if (Number(metadataResponse.headers['content-length']) > maxFileSize) {
throw new Error(
`Response is too large. Maximum size is 25MB. Actual size is ${metadataResponse.headers['content-length']}`
);
}
let contentType = headersObject['content-type'];
// in case HEAD request is not supported by the URL
try {
const metadataResponse = await $.http.head(url, {
headers: headersObject,
});
contentType = metadataResponse.headers['content-type'];
throwIfFileSizeExceedsLimit(metadataResponse.headers['content-length']);
// eslint-disable-next-line no-empty
} catch {}
const requestData: AxiosRequestConfig = {
const response = await $.http.request({
url,
method,
data,
headers: headersObject,
};
if (!isPossiblyTextBased(contentType)) {
requestData.responseType = 'arraybuffer';
}
const response = await $.http.request(requestData);
throwIfFileSizeExceedsLimit(response.headers['content-length']);
});
let responseData = response.data;
if (!isPossiblyTextBased(contentType)) {
responseData = Buffer.from(responseData as string).toString('base64');
if (typeof response.data === 'string') {
responseData = response.data.replaceAll('\u0000', '');
}
$.setActionItem({ raw: { data: responseData } });

View File

@@ -1,5 +1,4 @@
import checkModeration from './check-moderation';
import sendPrompt from './send-prompt';
import sendChatPrompt from './send-chat-prompt';
export default [checkModeration, sendChatPrompt, sendPrompt];
export default [checkModeration, sendPrompt];

View File

@@ -1,137 +0,0 @@
import defineAction from '../../../../helpers/define-action';
type TMessage = {
role: string;
content: string;
}
const castFloatOrUndefined = (value: string | null) => {
return value === '' ? undefined : parseFloat(value);
}
export default defineAction({
name: 'Send chat prompt',
key: 'sendChatPrompt',
description: 'Creates a completion for the provided prompt and parameters.',
arguments: [
{
label: 'Model',
key: 'model',
type: 'dropdown' as const,
required: true,
variables: false,
source: {
type: 'query',
name: 'getDynamicData',
arguments: [
{
name: 'key',
value: 'listModels',
},
],
},
},
{
label: 'Messages',
key: 'messages',
type: 'dynamic' as const,
required: false,
description: 'Add or remove messages as needed',
value: [{ role: 'system', body: '' }],
fields: [
{
label: 'Role',
key: 'role',
type: 'dropdown' as const,
required: true,
options: [
{
label: 'System',
value: 'system',
},
{
label: 'User',
value: 'user',
}
],
},
{
label: 'Content',
key: 'content',
type: 'string' as const,
required: true,
variables: true,
}
],
},
{
label: 'Temperature',
key: 'temperature',
type: 'string' as const,
required: false,
variables: true,
description: 'What sampling temperature to use. Higher values mean the model will take more risk. Try 0.9 for more creative applications, and 0 for ones with a well-defined answer. We generally recommend altering this or Top P but not both.'
},
{
label: 'Maximum tokens',
key: 'maxTokens',
type: 'string' as const,
required: false,
variables: true,
description: 'The maximum number of tokens to generate in the completion.'
},
{
label: 'Stop Sequence',
key: 'stopSequence',
type: 'string' as const,
required: false,
variables: true,
description: 'Single stop sequence where the API will stop generating further tokens. The returned text will not contain the stop sequence.'
},
{
label: 'Top P',
key: 'topP',
type: 'string' as const,
required: false,
variables: true,
description: 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with Top P probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered.'
},
{
label: 'Frequency Penalty',
key: 'frequencyPenalty',
type: 'string' as const,
required: false,
variables: true,
description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.`
},
{
label: 'presencePenalty',
key: 'presencePenalty',
type: 'string' as const,
required: false,
variables: true,
description: `Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.`
},
],
async run($) {
const payload = {
model: $.step.parameters.model as string,
temperature: castFloatOrUndefined($.step.parameters.temperature as string),
max_tokens: castFloatOrUndefined($.step.parameters.maxTokens as string),
stop: ($.step.parameters.stopSequence as string || null),
top_p: castFloatOrUndefined($.step.parameters.topP as string),
frequency_penalty: castFloatOrUndefined($.step.parameters.frequencyPenalty as string),
presence_penalty: castFloatOrUndefined($.step.parameters.presencePenalty as string),
messages: ($.step.parameters.messages as TMessage[]).map(message => ({
role: message.role,
content: message.content,
})),
};
const { data } = await $.http.post('/v1/chat/completions', payload);
$.setActionItem({
raw: data,
});
},
});

View File

@@ -1,111 +0,0 @@
import { IJSONArray } from '@automatisch/types';
import defineAction from '../../../../helpers/define-action';
import getClient from '../../common/postgres-client';
import setParams from '../../common/set-run-time-parameters';
import whereClauseOperators from '../../common/where-clause-operators';
type TWhereClauseEntry = { columnName: string, value: string, operator: string };
type TWhereClauseEntries = TWhereClauseEntry[];
export default defineAction({
name: 'Delete',
key: 'delete',
description: 'Delete rows found based on the given where clause entries.',
arguments: [
{
label: 'Schema name',
key: 'schema',
type: 'string' as const,
value: 'public',
required: true,
variables: false,
},
{
label: 'Table name',
key: 'table',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Where clause entries',
key: 'whereClauseEntries',
type: 'dynamic' as const,
required: true,
fields: [
{
label: 'Column name',
key: 'columnName',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Operator',
key: 'operator',
type: 'dropdown' as const,
required: true,
variables: false,
options: whereClauseOperators
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
]
},
{
label: 'Run-time parameters',
key: 'params',
type: 'dynamic' as const,
required: false,
description: 'Change run-time configuration parameters with SET command',
fields: [
{
label: 'Parameter name',
key: 'parameter',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
],
}
],
async run($) {
const client = getClient($);
await setParams(client, $.step.parameters.params);
const whereClauseEntries = $.step.parameters.whereClauseEntries as TWhereClauseEntries;
const response = await client($.step.parameters.table as string)
.withSchema($.step.parameters.schema as string)
.returning('*')
.where((builder) => {
for (const whereClauseEntry of whereClauseEntries) {
const { columnName, operator, value } = whereClauseEntry;
if (columnName) {
builder.where(columnName, operator, value);
}
}
})
.del() as IJSONArray;
$.setActionItem({
raw: {
rows: response
}
});
},
});

View File

@@ -1,6 +0,0 @@
import insertAction from './insert';
import updateAction from './update';
import deleteAction from './delete';
import SQLQuery from './sql-query'
export default [insertAction, updateAction, deleteAction, SQLQuery];

View File

@@ -1,93 +0,0 @@
import { IJSONObject } from '@automatisch/types';
import defineAction from '../../../../helpers/define-action';
import getClient from '../../common/postgres-client';
import setParams from '../../common/set-run-time-parameters';
type TColumnValueEntries = { columnName: string, value: string }[];
export default defineAction({
name: 'Insert',
key: 'insert',
description: 'Create a new row in a table in specified schema.',
arguments: [
{
label: 'Schema name',
key: 'schema',
type: 'string' as const,
value: 'public',
required: true,
variables: false,
},
{
label: 'Table name',
key: 'table',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Column - value entries',
key: 'columnValueEntries',
type: 'dynamic' as const,
required: true,
description: 'Table columns with values',
fields: [
{
label: 'Column name',
key: 'columnName',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
],
},
{
label: 'Run-time parameters',
key: 'params',
type: 'dynamic' as const,
required: false,
description: 'Change run-time configuration parameters with SET command',
fields: [
{
label: 'Parameter name',
key: 'parameter',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
],
}
],
async run($) {
const client = getClient($);
await setParams(client, $.step.parameters.params);
const fields = $.step.parameters.columnValueEntries as TColumnValueEntries;
const data = fields.reduce((result, { columnName, value }) => ({
...result,
[columnName]: value,
}), {});
const response = await client($.step.parameters.table as string)
.withSchema($.step.parameters.schema as string)
.returning('*')
.insert(data) as IJSONObject;
$.setActionItem({ raw: response[0] as IJSONObject });
},
});

View File

@@ -1,56 +0,0 @@
import defineAction from '../../../../helpers/define-action';
import getClient from '../../common/postgres-client';
import setParams from '../../common/set-run-time-parameters';
export default defineAction({
name: 'SQL query',
key: 'SQLQuery',
description: 'Executes the given SQL statement.',
arguments: [
{
label: 'SQL statement',
key: 'queryStatement',
type: 'string' as const,
value: 'public',
required: true,
variables: true,
},
{
label: 'Run-time parameters',
key: 'params',
type: 'dynamic' as const,
required: false,
description: 'Change run-time configuration parameters with SET command',
fields: [
{
label: 'Parameter name',
key: 'parameter',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
],
}
],
async run($) {
const client = getClient($);
await setParams(client, $.step.parameters.params);
const queryStatemnt = $.step.parameters.queryStatement;
const { rows } = await client.raw(queryStatemnt);
$.setActionItem({
raw: {
rows
}
});
},
});

View File

@@ -1,141 +0,0 @@
import { IJSONArray } from '@automatisch/types';
import defineAction from '../../../../helpers/define-action';
import getClient from '../../common/postgres-client';
import setParams from '../../common/set-run-time-parameters';
import whereClauseOperators from '../../common/where-clause-operators';
type TColumnValueEntries = { columnName: string, value: string }[];
type TWhereClauseEntry = { columnName: string, value: string, operator: string };
type TWhereClauseEntries = TWhereClauseEntry[];
export default defineAction({
name: 'Update',
key: 'update',
description: 'Update rows found based on the given where clause entries.',
arguments: [
{
label: 'Schema name',
key: 'schema',
type: 'string' as const,
value: 'public',
required: true,
variables: false,
},
{
label: 'Table name',
key: 'table',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Where clause entries',
key: 'whereClauseEntries',
type: 'dynamic' as const,
required: true,
fields: [
{
label: 'Column name',
key: 'columnName',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Operator',
key: 'operator',
type: 'dropdown' as const,
required: true,
variables: false,
options: whereClauseOperators
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
]
},
{
label: 'Column - value entries',
key: 'columnValueEntries',
type: 'dynamic' as const,
required: true,
description: 'Table columns with values',
fields: [
{
label: 'Column name',
key: 'columnName',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
],
},
{
label: 'Run-time parameters',
key: 'params',
type: 'dynamic' as const,
required: false,
description: 'Change run-time configuration parameters with SET command',
fields: [
{
label: 'Parameter name',
key: 'parameter',
type: 'string' as const,
required: true,
variables: false,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
}
],
}
],
async run($) {
const client = getClient($);
await setParams(client, $.step.parameters.params);
const whereClauseEntries = $.step.parameters.whereClauseEntries as TWhereClauseEntries;
const fields = $.step.parameters.columnValueEntries as TColumnValueEntries;
const data: Record<string, unknown> = fields.reduce((result, { columnName, value }) => ({
...result,
[columnName]: value,
}), {});
const response = await client($.step.parameters.table as string)
.withSchema($.step.parameters.schema as string)
.returning('*')
.where((builder) => {
for (const whereClauseEntry of whereClauseEntries) {
const { columnName, operator, value } = whereClauseEntry;
if (columnName) {
builder.where(columnName, operator, value);
}
}
})
.update(data) as IJSONArray;
$.setActionItem({
raw: {
rows: response
}
});
},
});

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,98 +0,0 @@
import verifyCredentials from './verify-credentials';
import isStillVerified from './is-still-verified';
export default {
fields: [
{
key: 'version',
label: 'PostgreSQL version',
type: 'string' as const,
required: true,
readOnly: false,
value: null,
placeholder: null,
description:
'The version of PostgreSQL database that user want to connect with.',
clickToCopy: false,
},
{
key: 'host',
label: 'Host',
type: 'string' as const,
required: true,
readOnly: false,
value: '127.0.0.1',
placeholder: null,
description: 'The host of the PostgreSQL database.',
clickToCopy: false,
},
{
key: 'port',
label: 'Port',
type: 'string' as const,
required: true,
readOnly: false,
value: '5432',
placeholder: null,
description: 'The port of the PostgreSQL database.',
clickToCopy: false,
},
{
key: 'enableSsl',
label: 'Enable SSL',
type: 'dropdown' as const,
required: true,
readOnly: false,
value: 'false',
description: 'The port of the PostgreSQL database.',
variables: false,
clickToCopy: false,
options: [
{
label: 'True',
value: 'true',
},
{
label: 'False',
value: 'false',
},
],
},
{
key: 'database',
label: 'Database name',
type: 'string' as const,
required: true,
readOnly: false,
value: null,
placeholder: null,
description: 'The database name of the PostgreSQL database.',
clickToCopy: false,
},
{
key: 'user',
label: 'Database username',
type: 'string' as const,
required: true,
readOnly: false,
value: null,
placeholder: null,
description: 'The user who has access on postgres database.',
clickToCopy: false,
},
{
key: 'password',
label: 'Password',
type: 'string' as const,
required: true,
readOnly: false,
value: null,
placeholder: null,
description: 'The password of the PostgreSQL database user.',
clickToCopy: false,
},
],
verifyCredentials,
isStillVerified,
};

View File

@@ -1,10 +0,0 @@
import { IGlobalVariable } from '@automatisch/types';
import verifyCredentials from './verify-credentials';
const isStillVerified = async ($: IGlobalVariable) => {
await verifyCredentials($);
return true;
};
export default isStillVerified;

View File

@@ -1,25 +0,0 @@
import { IGlobalVariable } from '@automatisch/types';
import logger from '../../../helpers/logger';
import getClient from '../common/postgres-client';
const verifyCredentials = async ($: IGlobalVariable) => {
const client = getClient($);
const checkConnection = await client.raw('SELECT 1');
logger.debug(checkConnection);
await $.auth.set({
screenName: `${$.auth.data.user}@${$.auth.data.host}:${$.auth.data.port}/${$.auth.data.database}`,
client: 'pg',
version: $.auth.data.version,
host: $.auth.data.host,
port: Number($.auth.data.port),
enableSsl:
$.auth.data.enableSsl === 'true' || $.auth.data.enableSsl === true,
user: $.auth.data.user,
password: $.auth.data.password,
database: $.auth.data.database,
});
};
export default verifyCredentials;

View File

@@ -1,22 +0,0 @@
import knex, { Knex } from 'knex';
import { IGlobalVariable } from '@automatisch/types';
const getClient = ($: IGlobalVariable): Knex<any, unknown[]> => {
const client = knex({
client: 'pg',
version: $.auth.data.version as string,
connection: {
host: $.auth.data.host as string,
port: Number($.auth.data.port),
ssl: ($.auth.data.enableSsl === 'true' ||
$.auth.data.enableSsl === true) as boolean,
user: $.auth.data.user as string,
password: $.auth.data.password as string,
database: $.auth.data.database as string,
},
});
return client;
};
export default getClient;

View File

@@ -1,19 +0,0 @@
import { Knex } from 'knex';
import { type IJSONValue } from '@automatisch/types';
type TParams = { parameter: string; value: string; }[];
const setParams = async (client: Knex<any, unknown[]>, params: IJSONValue = []): Promise<void> => {
for (const { parameter, value } of (params as TParams)) {
if (parameter) {
const bindings = {
parameter,
value,
};
await client.raw('SET :parameter: = :value:', bindings);
}
}
};
export default setParams;

Some files were not shown because too many files have changed in this diff Show More