refactor: clean up github and rewrite its auth
This commit is contained in:
21
packages/backend/src/apps/github/auth/create-auth-data.ts
Normal file
21
packages/backend/src/apps/github/auth/create-auth-data.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { IField, IGlobalVariable } from '@automatisch/types';
|
||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
|
||||||
|
export default async function createAuthData($: IGlobalVariable) {
|
||||||
|
const scopes = ['read:org', 'repo', 'user'];
|
||||||
|
const oauthRedirectUrlField = $.app.auth.fields.find(
|
||||||
|
(field: IField) => field.key == 'oAuthRedirectUrl'
|
||||||
|
);
|
||||||
|
const redirectUri = oauthRedirectUrlField.value as string;
|
||||||
|
const searchParams = new URLSearchParams({
|
||||||
|
client_id: $.auth.data.consumerKey as string,
|
||||||
|
redirect_uri: redirectUri,
|
||||||
|
scope: scopes.join(','),
|
||||||
|
});
|
||||||
|
|
||||||
|
const url = `${$.app.baseUrl}/login/oauth/authorize?${searchParams.toString()}`;
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
}
|
221
packages/backend/src/apps/github/auth/index.ts
Normal file
221
packages/backend/src/apps/github/auth/index.ts
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
import createAuthData from './create-auth-data';
|
||||||
|
import verifyCredentials from './verify-credentials';
|
||||||
|
import isStillVerified from './is-still-verified';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
key: 'oAuthRedirectUrl',
|
||||||
|
label: 'OAuth Redirect URL',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: true,
|
||||||
|
value: '{WEB_APP_URL}/app/github/connections/add',
|
||||||
|
placeholder: null,
|
||||||
|
description: 'When asked to input an OAuth callback or redirect URL in Github OAuth, enter the URL above.',
|
||||||
|
docUrl: 'https://automatisch.io/docs/github#oauth-redirect-url',
|
||||||
|
clickToCopy: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'consumerKey',
|
||||||
|
label: 'Client ID',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
docUrl: 'https://automatisch.io/docs/github#client-id',
|
||||||
|
clickToCopy: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'consumerSecret',
|
||||||
|
label: 'Client Secret',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: null,
|
||||||
|
docUrl: 'https://automatisch.io/docs/github#client-secret',
|
||||||
|
clickToCopy: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
authenticationSteps: [
|
||||||
|
{
|
||||||
|
step: 1,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'createConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: '{key}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'consumerKey',
|
||||||
|
value: '{fields.consumerKey}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'consumerSecret',
|
||||||
|
value: '{fields.consumerSecret}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 2,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'createAuthData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{createConnection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 3,
|
||||||
|
type: 'openWithPopup',
|
||||||
|
name: 'openAuthPopup',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
value: '{createAuthData.url}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 4,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'updateConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{createConnection.id}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'oauthVerifier',
|
||||||
|
value: '{openAuthPopup.code}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 5,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'verifyConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{createConnection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
reconnectionSteps: [
|
||||||
|
{
|
||||||
|
step: 1,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'resetConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 2,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'updateConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'consumerKey',
|
||||||
|
value: '{fields.consumerKey}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'consumerSecret',
|
||||||
|
value: '{fields.consumerSecret}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 3,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'createAuthData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 4,
|
||||||
|
type: 'openWithPopup',
|
||||||
|
name: 'openAuthPopup',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'url',
|
||||||
|
value: '{createAuthData.url}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 5,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'updateConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'formattedData',
|
||||||
|
value: null,
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: 'oauthVerifier',
|
||||||
|
value: '{openAuthPopup.code}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
step: 6,
|
||||||
|
type: 'mutation',
|
||||||
|
name: 'verifyConnection',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'id',
|
||||||
|
value: '{connection.id}'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
createAuthData,
|
||||||
|
verifyCredentials,
|
||||||
|
isStillVerified,
|
||||||
|
};
|
13
packages/backend/src/apps/github/auth/is-still-verified.ts
Normal file
13
packages/backend/src/apps/github/auth/is-still-verified.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
import getCurrentUser from '../common/get-current-user';
|
||||||
|
|
||||||
|
const isStillVerified = async ($: IGlobalVariable) => {
|
||||||
|
try {
|
||||||
|
const user = await getCurrentUser($);
|
||||||
|
return !!user;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isStillVerified;
|
59
packages/backend/src/apps/github/auth/verify-credentials.ts
Normal file
59
packages/backend/src/apps/github/auth/verify-credentials.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { IGlobalVariable } from '@automatisch/types';
|
||||||
|
import getCurrentUser from '../common/get-current-user';
|
||||||
|
|
||||||
|
async function getTokenInfo($: IGlobalVariable) {
|
||||||
|
const basicAuthToken = Buffer.from(
|
||||||
|
$.auth.data.consumerKey + ':' + $.auth.data.consumerSecret
|
||||||
|
).toString('base64');
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
Authorization: `Basic ${basicAuthToken}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
access_token: $.auth.data.accessToken,
|
||||||
|
};
|
||||||
|
|
||||||
|
return await $.http.post(
|
||||||
|
`${$.app.baseUrl}/applications/${$.auth.data.consumerKey}/token`,
|
||||||
|
body,
|
||||||
|
{ headers }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const verifyCredentials = async ($: IGlobalVariable) => {
|
||||||
|
try {
|
||||||
|
const response = await $.http.post(
|
||||||
|
`${$.app.baseUrl}/login/oauth/access_token`,
|
||||||
|
{
|
||||||
|
client_id: $.auth.data.consumerKey,
|
||||||
|
client_secret: $.auth.data.consumerSecret,
|
||||||
|
code: $.auth.data.oauthVerifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
$.auth.data.accessToken = data.access_token;
|
||||||
|
|
||||||
|
const currentUser = await getCurrentUser($);
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
consumerKey: $.auth.data.consumerKey,
|
||||||
|
consumerSecret: $.auth.data.consumerSecret,
|
||||||
|
accessToken: data.access_token,
|
||||||
|
scope: data.scope,
|
||||||
|
tokenType: data.token_type,
|
||||||
|
userId: currentUser.id,
|
||||||
|
screenName: currentUser.login,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(error.response.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default verifyCredentials;
|
@@ -1,95 +0,0 @@
|
|||||||
import type {
|
|
||||||
IAuthentication,
|
|
||||||
IApp,
|
|
||||||
IField,
|
|
||||||
IJSONObject,
|
|
||||||
} from '@automatisch/types';
|
|
||||||
import createHttpClient, { IHttpClient } from '../../helpers/http-client';
|
|
||||||
import { URLSearchParams } from 'url';
|
|
||||||
|
|
||||||
export default class Authentication implements IAuthentication {
|
|
||||||
appData: IApp;
|
|
||||||
connectionData: IJSONObject;
|
|
||||||
scopes: string[] = ['read:org', 'repo', 'user'];
|
|
||||||
client: IHttpClient;
|
|
||||||
|
|
||||||
constructor(appData: IApp, connectionData: IJSONObject) {
|
|
||||||
this.connectionData = connectionData;
|
|
||||||
this.appData = appData;
|
|
||||||
this.client = createHttpClient({ baseURL: 'https://github.com' });
|
|
||||||
}
|
|
||||||
|
|
||||||
get oauthRedirectUrl(): string {
|
|
||||||
return this.appData.fields.find(
|
|
||||||
(field: IField) => field.key == 'oAuthRedirectUrl'
|
|
||||||
).value;
|
|
||||||
}
|
|
||||||
|
|
||||||
async createAuthData(): Promise<{ url: string }> {
|
|
||||||
const searchParams = new URLSearchParams({
|
|
||||||
client_id: this.connectionData.consumerKey as string,
|
|
||||||
redirect_uri: this.oauthRedirectUrl,
|
|
||||||
scope: this.scopes.join(','),
|
|
||||||
});
|
|
||||||
|
|
||||||
const url = `https://github.com/login/oauth/authorize?${searchParams.toString()}`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
url,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async verifyCredentials() {
|
|
||||||
const response = await this.client.post('/login/oauth/access_token', {
|
|
||||||
client_id: this.connectionData.consumerKey,
|
|
||||||
client_secret: this.connectionData.consumerSecret,
|
|
||||||
code: this.connectionData.oauthVerifier,
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = Object.fromEntries(new URLSearchParams(response.data));
|
|
||||||
|
|
||||||
this.connectionData.accessToken = data.access_token;
|
|
||||||
|
|
||||||
const tokenInfo = await this.getTokenInfo();
|
|
||||||
|
|
||||||
return {
|
|
||||||
consumerKey: this.connectionData.consumerKey,
|
|
||||||
consumerSecret: this.connectionData.consumerSecret,
|
|
||||||
accessToken: data.access_token,
|
|
||||||
scope: data.scope,
|
|
||||||
tokenType: data.token_type,
|
|
||||||
userId: tokenInfo.data.user.id,
|
|
||||||
screenName: tokenInfo.data.user.login,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTokenInfo() {
|
|
||||||
const basicAuthToken = Buffer.from(
|
|
||||||
this.connectionData.consumerKey + ':' + this.connectionData.consumerSecret
|
|
||||||
).toString('base64');
|
|
||||||
|
|
||||||
const headers = {
|
|
||||||
Authorization: `Basic ${basicAuthToken}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
access_token: this.connectionData.accessToken,
|
|
||||||
};
|
|
||||||
|
|
||||||
return await this.client.post(
|
|
||||||
`https://api.github.com/applications/${this.connectionData.consumerKey}/token`,
|
|
||||||
body,
|
|
||||||
{ headers }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async isStillVerified() {
|
|
||||||
try {
|
|
||||||
await this.getTokenInfo();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
28
packages/backend/src/apps/github/common/generate-request.ts
Normal file
28
packages/backend/src/apps/github/common/generate-request.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
|
import { Method } from 'axios';
|
||||||
|
|
||||||
|
type IGenereateRequestOptons = {
|
||||||
|
requestPath: string;
|
||||||
|
method: string;
|
||||||
|
data?: IJSONObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateRequest = async (
|
||||||
|
$: IGlobalVariable,
|
||||||
|
options: IGenereateRequestOptons
|
||||||
|
) => {
|
||||||
|
const { requestPath, method, data } = options;
|
||||||
|
|
||||||
|
const response = await $.http.request({
|
||||||
|
url: requestPath,
|
||||||
|
method: method as Method,
|
||||||
|
data,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${$.auth.data.accessToken}`
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default generateRequest;
|
14
packages/backend/src/apps/github/common/get-current-user.ts
Normal file
14
packages/backend/src/apps/github/common/get-current-user.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { IGlobalVariable, IJSONObject } from '@automatisch/types';
|
||||||
|
import generateRequest from './generate-request';
|
||||||
|
|
||||||
|
const getCurrentUser = async ($: IGlobalVariable): Promise<IJSONObject> => {
|
||||||
|
const response = await generateRequest($, {
|
||||||
|
requestPath: '/user',
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
|
||||||
|
const currentUser = response.data;
|
||||||
|
return currentUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getCurrentUser;
|
@@ -0,0 +1,13 @@
|
|||||||
|
type TRepoOwnerAndRepo = {
|
||||||
|
repoOwner: string;
|
||||||
|
repo: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRepoOwnerAndRepo(repoFullName: string): TRepoOwnerAndRepo {
|
||||||
|
const [repoOwner, repo] = repoFullName.split('/');
|
||||||
|
|
||||||
|
return {
|
||||||
|
repoOwner,
|
||||||
|
repo
|
||||||
|
};
|
||||||
|
}
|
@@ -1,16 +0,0 @@
|
|||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
import ListRepos from './data/list-repos';
|
|
||||||
import ListBranches from './data/list-branches';
|
|
||||||
import ListLabels from './data/list-labels';
|
|
||||||
|
|
||||||
export default class Data {
|
|
||||||
listRepos: ListRepos;
|
|
||||||
listBranches: ListBranches;
|
|
||||||
listLabels: ListLabels;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
this.listRepos = new ListRepos(connectionData);
|
|
||||||
this.listBranches = new ListBranches(connectionData, parameters);
|
|
||||||
this.listLabels = new ListLabels(connectionData, parameters);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,36 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import type { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class ListBranches {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters?: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
const branches = await this.client.paginate(this.client.rest.repos.listBranches, this.options);
|
|
||||||
|
|
||||||
return branches.map((branch) => ({
|
|
||||||
value: branch.name,
|
|
||||||
name: branch.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,36 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import type { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class ListLabels {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters?: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
const labels = await this.client.paginate(this.client.rest.issues.listLabelsForRepo, this.options);
|
|
||||||
|
|
||||||
return labels.map((label) => ({
|
|
||||||
value: label.name,
|
|
||||||
name: label.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,23 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import type { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class ListRepos {
|
|
||||||
client?: Octokit;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
const repos = await this.client.paginate(this.client.rest.repos.listForAuthenticatedUser);
|
|
||||||
|
|
||||||
return repos.map((repo) => ({
|
|
||||||
value: repo.full_name,
|
|
||||||
name: repo.full_name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,25 +1,10 @@
|
|||||||
import {
|
export default {
|
||||||
IService,
|
name: 'Github',
|
||||||
IAuthentication,
|
key: 'github',
|
||||||
IApp,
|
baseUrl: 'https://github.com',
|
||||||
IJSONObject,
|
apiBaseUrl: 'https://api.github.com',
|
||||||
} from '@automatisch/types';
|
iconUrl: '{BASE_URL}/apps/github/assets/favicon.svg',
|
||||||
import Authentication from './authentication';
|
authDocUrl: 'https://automatisch.io/docs/connections/github',
|
||||||
import Triggers from './triggers';
|
primaryColor: '000000',
|
||||||
import Data from './data';
|
supportsConnections: true,
|
||||||
|
};
|
||||||
export default class Github implements IService {
|
|
||||||
authenticationClient: IAuthentication;
|
|
||||||
triggers: Triggers;
|
|
||||||
data: Data;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
appData: IApp,
|
|
||||||
connectionData: IJSONObject,
|
|
||||||
parameters: IJSONObject
|
|
||||||
) {
|
|
||||||
this.authenticationClient = new Authentication(appData, connectionData);
|
|
||||||
this.data = new Data(connectionData, parameters);
|
|
||||||
this.triggers = new Triggers(connectionData, parameters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@@ -1,747 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Github",
|
|
||||||
"key": "github",
|
|
||||||
"iconUrl": "{BASE_URL}/apps/github/assets/favicon.svg",
|
|
||||||
"docUrl": "https://automatisch.io/docs/github",
|
|
||||||
"primaryColor": "000000",
|
|
||||||
"supportsConnections": true,
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"key": "oAuthRedirectUrl",
|
|
||||||
"label": "OAuth Redirect URL",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": true,
|
|
||||||
"value": "{WEB_APP_URL}/app/github/connections/add",
|
|
||||||
"placeholder": null,
|
|
||||||
"description": "When asked to input an OAuth callback or redirect URL in Github OAuth, enter the URL above.",
|
|
||||||
"docUrl": "https://automatisch.io/docs/github#oauth-redirect-url",
|
|
||||||
"clickToCopy": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "consumerKey",
|
|
||||||
"label": "Client ID",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/github#client-id",
|
|
||||||
"clickToCopy": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "consumerSecret",
|
|
||||||
"label": "Client Secret",
|
|
||||||
"type": "string",
|
|
||||||
"required": true,
|
|
||||||
"readOnly": false,
|
|
||||||
"value": null,
|
|
||||||
"placeholder": null,
|
|
||||||
"description": null,
|
|
||||||
"docUrl": "https://automatisch.io/docs/github#client-secret",
|
|
||||||
"clickToCopy": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authenticationSteps": [
|
|
||||||
{
|
|
||||||
"step": 1,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "{key}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "consumerKey",
|
|
||||||
"value": "{fields.consumerKey}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "consumerSecret",
|
|
||||||
"value": "{fields.consumerSecret}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 2,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createAuthData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 3,
|
|
||||||
"type": "openWithPopup",
|
|
||||||
"name": "openAuthPopup",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "url",
|
|
||||||
"value": "{createAuthData.url}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 4,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "oauthVerifier",
|
|
||||||
"value": "{openAuthPopup.code}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 5,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "verifyConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{createConnection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"reconnectionSteps": [
|
|
||||||
{
|
|
||||||
"step": 1,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "resetConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 2,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "consumerKey",
|
|
||||||
"value": "{fields.consumerKey}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "consumerSecret",
|
|
||||||
"value": "{fields.consumerSecret}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 3,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "createAuthData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 4,
|
|
||||||
"type": "openWithPopup",
|
|
||||||
"name": "openAuthPopup",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "url",
|
|
||||||
"value": "{createAuthData.url}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 5,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "updateConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "formattedData",
|
|
||||||
"value": null,
|
|
||||||
"properties": [
|
|
||||||
{
|
|
||||||
"name": "oauthVerifier",
|
|
||||||
"value": "{openAuthPopup.code}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"step": 6,
|
|
||||||
"type": "mutation",
|
|
||||||
"name": "verifyConnection",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"value": "{connection.id}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"triggers": [
|
|
||||||
{
|
|
||||||
"name": "New repository",
|
|
||||||
"key": "newRepository",
|
|
||||||
"description": "Triggers when a new repository is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New organization",
|
|
||||||
"key": "newOrganization",
|
|
||||||
"description": "Triggers when a new organization is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New branch",
|
|
||||||
"key": "newBranch",
|
|
||||||
"description": "Triggers when a new branch is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New notification",
|
|
||||||
"key": "newNotification",
|
|
||||||
"description": "Triggers when a new notification is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": false,
|
|
||||||
"variables": false,
|
|
||||||
"description": "If blank, we will retrieve all notifications.",
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New pull request",
|
|
||||||
"key": "newPullRequest",
|
|
||||||
"description": "Triggers when a new pull request is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New watcher",
|
|
||||||
"key": "newWatcher",
|
|
||||||
"description": "Triggers when a new watcher is added to a repo",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New milestone",
|
|
||||||
"key": "newMilestone",
|
|
||||||
"description": "Triggers when a new milestone is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New commit comment",
|
|
||||||
"key": "newCommitComment",
|
|
||||||
"description": "Triggers when a new commit comment is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New label",
|
|
||||||
"key": "newLabel",
|
|
||||||
"description": "Triggers when a new label is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New collaborator",
|
|
||||||
"key": "newCollaborator",
|
|
||||||
"description": "Triggers when a new collaborator is added to a repo",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New release",
|
|
||||||
"key": "newRelease",
|
|
||||||
"description": "Triggers when a new release is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New commit",
|
|
||||||
"key": "newCommit",
|
|
||||||
"description": "Triggers when a new commit is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Head",
|
|
||||||
"key": "head",
|
|
||||||
"type": "dropdown",
|
|
||||||
"description": "Branch to pull commits from. If unspecified, will use the repository's default branch (usually main or develop).",
|
|
||||||
"required": false,
|
|
||||||
"variables": false,
|
|
||||||
"dependsOn": ["parameters.repo"],
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listBranches"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parameters.repo",
|
|
||||||
"value": "{parameters.repo}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "New issue",
|
|
||||||
"key": "newIssue",
|
|
||||||
"description": "Triggers when a new issue is created",
|
|
||||||
"substeps": [
|
|
||||||
{
|
|
||||||
"key": "chooseConnection",
|
|
||||||
"name": "Choose connection"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "chooseTrigger",
|
|
||||||
"name": "Set up a trigger",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"label": "Repo",
|
|
||||||
"key": "repo",
|
|
||||||
"type": "dropdown",
|
|
||||||
"required": false,
|
|
||||||
"variables": false,
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listRepos"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Which types of issues should this trigger on?",
|
|
||||||
"key": "issueType",
|
|
||||||
"type": "dropdown",
|
|
||||||
"description": "Defaults to any issue you can see.",
|
|
||||||
"required": true,
|
|
||||||
"variables": false,
|
|
||||||
"value": "all",
|
|
||||||
"options": [
|
|
||||||
{
|
|
||||||
"label": "Any issue you can see",
|
|
||||||
"value": "all"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Only issues assigned to you",
|
|
||||||
"value": "assigned"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Only issues created by you",
|
|
||||||
"value": "created"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Only issues you're mentioned in",
|
|
||||||
"value": "mentioned"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Only issues you're subscribed to",
|
|
||||||
"value": "subscribed"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Label",
|
|
||||||
"key": "label",
|
|
||||||
"type": "dropdown",
|
|
||||||
"description": "Only trigger on issues when this label is added.",
|
|
||||||
"required": false,
|
|
||||||
"variables": false,
|
|
||||||
"dependsOn": ["parameters.repo"],
|
|
||||||
"source": {
|
|
||||||
"type": "query",
|
|
||||||
"name": "getData",
|
|
||||||
"arguments": [
|
|
||||||
{
|
|
||||||
"name": "key",
|
|
||||||
"value": "listLabels"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "parameters.repo",
|
|
||||||
"value": "{parameters.repo}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "testStep",
|
|
||||||
"name": "Test trigger"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
import NewRepository from './triggers/new-repository';
|
|
||||||
import NewOrganization from './triggers/new-organization';
|
|
||||||
import NewBranch from './triggers/new-branch';
|
|
||||||
import NewNotification from './triggers/new-notification';
|
|
||||||
import NewPullRequest from './triggers/new-pull-request';
|
|
||||||
import NewWatcher from './triggers/new-watcher';
|
|
||||||
import NewMilestone from './triggers/new-milestone';
|
|
||||||
import NewCommit from './triggers/new-commit';
|
|
||||||
import NewCommitComment from './triggers/new-commit-comment';
|
|
||||||
import NewLabel from './triggers/new-label';
|
|
||||||
import NewCollaborator from './triggers/new-collaborator';
|
|
||||||
import NewRelease from './triggers/new-release';
|
|
||||||
import NewIssue from './triggers/new-issue';
|
|
||||||
|
|
||||||
export default class Triggers {
|
|
||||||
newRepository: NewRepository;
|
|
||||||
newOrganization: NewOrganization;
|
|
||||||
newBranch: NewBranch;
|
|
||||||
newNotification: NewNotification;
|
|
||||||
newPullRequest: NewPullRequest;
|
|
||||||
newWatcher: NewWatcher;
|
|
||||||
newMilestone: NewMilestone;
|
|
||||||
newCommit: NewCommit;
|
|
||||||
newCommitComment: NewCommitComment;
|
|
||||||
newLabel: NewLabel;
|
|
||||||
newCollaborator: NewCollaborator;
|
|
||||||
newRelease: NewRelease;
|
|
||||||
newIssue: NewIssue;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
this.newRepository = new NewRepository(connectionData);
|
|
||||||
this.newOrganization = new NewOrganization(connectionData);
|
|
||||||
this.newBranch = new NewBranch(connectionData, parameters);
|
|
||||||
this.newNotification = new NewNotification(connectionData, parameters);
|
|
||||||
this.newPullRequest = new NewPullRequest(connectionData, parameters);
|
|
||||||
this.newWatcher = new NewWatcher(connectionData, parameters);
|
|
||||||
this.newMilestone = new NewMilestone(connectionData, parameters);
|
|
||||||
this.newCommit = new NewCommit(connectionData, parameters);
|
|
||||||
this.newCommitComment = new NewCommitComment(connectionData, parameters);
|
|
||||||
this.newLabel = new NewLabel(connectionData, parameters);
|
|
||||||
this.newCollaborator = new NewCollaborator(connectionData, parameters);
|
|
||||||
this.newRelease = new NewRelease(connectionData, parameters);
|
|
||||||
this.newIssue = new NewIssue(connectionData, parameters);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewBranch {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
// TODO: implement pagination on undated entires
|
|
||||||
return await this.client.paginate(this.client.rest.repos.listBranches, this.options);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
const { data: branches } = await this.client.rest.repos.listBranches(options);
|
|
||||||
|
|
||||||
return branches;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewCollaborator {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
// TODO: implement pagination on undated entries
|
|
||||||
return await this.client.paginate(
|
|
||||||
this.client.rest.repos.listCollaborators,
|
|
||||||
this.options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.repos.listCollaborators(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,59 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewCommitComment {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const iterator = await this.client.paginate.iterator(this.client.rest.repos.listCommitCommentsForRepo, this.options);
|
|
||||||
const newCommitComments = [];
|
|
||||||
|
|
||||||
const startTimeDateObject = DateTime.fromJSDate(startTime);
|
|
||||||
|
|
||||||
commitCommentIterator:
|
|
||||||
for await (const { data: commitComments } of iterator) {
|
|
||||||
for (const commitComment of commitComments) {
|
|
||||||
const createdAtDateObject = DateTime.fromISO(commitComment.created_at);
|
|
||||||
|
|
||||||
if (createdAtDateObject < startTimeDateObject) {
|
|
||||||
break commitCommentIterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
newCommitComments.push(commitComment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCommitComments;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.repos.listCommitCommentsForRepo(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,59 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewCommit {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
head?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameters?.head) {
|
|
||||||
this.head = parameters.head as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
const options = {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.head) {
|
|
||||||
return {
|
|
||||||
...options,
|
|
||||||
sha: this.head,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
since: DateTime.fromJSDate(startTime).toISO(),
|
|
||||||
};
|
|
||||||
return await this.client.paginate(this.client.rest.repos.listCommits, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.repos.listCommits(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,88 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewIssue {
|
|
||||||
client?: Octokit;
|
|
||||||
connectionData?: IJSONObject;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
hasRepo?: boolean;
|
|
||||||
label?: string;
|
|
||||||
issueType?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
labels: this.label,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async listRepoIssues(options = {}, paginate = false) {
|
|
||||||
const listRepoIssues = this.client.rest.issues.listForRepo;
|
|
||||||
|
|
||||||
const extendedOptions = {
|
|
||||||
...this.options,
|
|
||||||
repo: this.repo,
|
|
||||||
owner: this.repoOwner,
|
|
||||||
filter: this.issueType,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (paginate) {
|
|
||||||
return await this.client.paginate(listRepoIssues, extendedOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (await listRepoIssues(extendedOptions)).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async listIssues(options = {}, paginate = false) {
|
|
||||||
const listIssues = this.client.rest.issues.listForAuthenticatedUser;
|
|
||||||
|
|
||||||
const extendedOptions = {
|
|
||||||
...this.options,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (paginate) {
|
|
||||||
return await this.client.paginate(listIssues, extendedOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (await listIssues(extendedOptions)).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const options = {
|
|
||||||
since: DateTime.fromJSDate(startTime).toISO(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.hasRepo) {
|
|
||||||
return await this.listRepoIssues(options, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.listIssues(options, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.hasRepo) {
|
|
||||||
return await this.listRepoIssues(options, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.listIssues(options, false);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewLabel {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
// TODO: implement pagination on undated entires
|
|
||||||
return await this.client.paginate(
|
|
||||||
this.client.rest.issues.listLabelsForRepo,
|
|
||||||
this.options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.issues.listLabelsForRepo(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewMilestone {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
state: 'open' as const,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const iterator = await this.client.paginate.iterator(this.client.rest.issues.listMilestones, this.options);
|
|
||||||
const newMilestones = [];
|
|
||||||
|
|
||||||
const startTimeDateObject = DateTime.fromJSDate(startTime);
|
|
||||||
|
|
||||||
milestoneIterator:
|
|
||||||
for await (const { data: milestones } of iterator) {
|
|
||||||
for (const milestone of milestones) {
|
|
||||||
const createdAtDateObject = DateTime.fromISO(milestone.created_at);
|
|
||||||
|
|
||||||
if (createdAtDateObject < startTimeDateObject) {
|
|
||||||
break milestoneIterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
newMilestones.push(milestone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newMilestones;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.issues.listMilestones(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,83 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewNotification {
|
|
||||||
client?: Octokit;
|
|
||||||
connectionData?: IJSONObject;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
hasRepo?: boolean;
|
|
||||||
baseOptions = {
|
|
||||||
all: true,
|
|
||||||
participating: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
async listRepoNotifications(options = {}, paginate = false) {
|
|
||||||
const listRepoNotifications = this.client.rest.activity.listRepoNotificationsForAuthenticatedUser;
|
|
||||||
|
|
||||||
const extendedOptions = {
|
|
||||||
...this.baseOptions,
|
|
||||||
repo: this.repo,
|
|
||||||
owner: this.repoOwner,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (paginate) {
|
|
||||||
return await this.client.paginate(listRepoNotifications, extendedOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (await listRepoNotifications(extendedOptions)).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async listNotifications(options = {}, paginate = false) {
|
|
||||||
const listNotifications = this.client.rest.activity.listNotificationsForAuthenticatedUser;
|
|
||||||
|
|
||||||
const extendedOptions = {
|
|
||||||
...this.baseOptions,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (paginate) {
|
|
||||||
return await this.client.paginate(listNotifications, extendedOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (await listNotifications(extendedOptions)).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const options = {
|
|
||||||
since: DateTime.fromJSDate(startTime).toISO(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.hasRepo) {
|
|
||||||
return await this.listRepoNotifications(options, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.listNotifications(options, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.hasRepo) {
|
|
||||||
return await this.listRepoNotifications(options, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.listNotifications(options, false);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class NewOrganization {
|
|
||||||
client?: Octokit;
|
|
||||||
baseOptions = {
|
|
||||||
per_page: 100,
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (
|
|
||||||
connectionData.consumerKey &&
|
|
||||||
connectionData.consumerSecret &&
|
|
||||||
connectionData.accessToken
|
|
||||||
) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
// TODO: implement pagination on undated entires
|
|
||||||
return await this.client.paginate(this.client.rest.orgs.listForAuthenticatedUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const { data: orgs } = await this.client.rest.orgs.listForAuthenticatedUser({ per_page: 1 });
|
|
||||||
|
|
||||||
return orgs;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,63 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewPullRequest {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
sort: 'created' as const,
|
|
||||||
direction: 'desc' as const,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const iterator = await this.client.paginate.iterator(
|
|
||||||
this.client.rest.pulls.list,
|
|
||||||
this.options
|
|
||||||
);
|
|
||||||
const newPullRequests = [];
|
|
||||||
|
|
||||||
const startTimeDateObject = DateTime.fromJSDate(startTime);
|
|
||||||
|
|
||||||
pullRequestIterator: for await (const { data: pullRequests } of iterator) {
|
|
||||||
for (const pullRequest of pullRequests) {
|
|
||||||
const createdAtDateObject = DateTime.fromISO(pullRequest.created_at);
|
|
||||||
|
|
||||||
if (createdAtDateObject < startTimeDateObject) {
|
|
||||||
break pullRequestIterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
newPullRequests.push(pullRequest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newPullRequests;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.pulls.list(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,59 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewRelease {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const iterator = await this.client.paginate.iterator(this.client.rest.repos.listReleases, this.options);
|
|
||||||
const newReleases = [];
|
|
||||||
|
|
||||||
const startTimeDateObject = DateTime.fromJSDate(startTime);
|
|
||||||
|
|
||||||
releaseIterator:
|
|
||||||
for await (const { data: releases } of iterator) {
|
|
||||||
for (const release of releases) {
|
|
||||||
const createdAtDateObject = DateTime.fromISO(release.created_at);
|
|
||||||
|
|
||||||
if (createdAtDateObject < startTimeDateObject) {
|
|
||||||
break releaseIterator;
|
|
||||||
}
|
|
||||||
|
|
||||||
newReleases.push(release);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newReleases;
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.repos.listReleases(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,32 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
export default class NewRepository {
|
|
||||||
client?: Octokit;
|
|
||||||
connectionData?: IJSONObject;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async run(startTime: Date) {
|
|
||||||
const options = {
|
|
||||||
since: DateTime.fromJSDate(startTime).toISO(),
|
|
||||||
};
|
|
||||||
return await this.client.paginate(this.client.rest.repos.listForAuthenticatedUser, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
const options = {
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
const { data: repos } = await this.client.rest.repos.listForAuthenticatedUser(options);
|
|
||||||
|
|
||||||
return repos;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,45 +0,0 @@
|
|||||||
import { Octokit } from 'octokit';
|
|
||||||
import { IJSONObject } from '@automatisch/types';
|
|
||||||
|
|
||||||
import { assignOwnerAndRepo } from '../utils';
|
|
||||||
|
|
||||||
export default class NewWatcher {
|
|
||||||
client?: Octokit;
|
|
||||||
repoOwner?: string;
|
|
||||||
repo?: string;
|
|
||||||
|
|
||||||
constructor(connectionData: IJSONObject, parameters: IJSONObject) {
|
|
||||||
if (connectionData.accessToken) {
|
|
||||||
this.client = new Octokit({
|
|
||||||
auth: connectionData.accessToken as string,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
assignOwnerAndRepo(this, parameters?.repo as string);
|
|
||||||
}
|
|
||||||
|
|
||||||
get options() {
|
|
||||||
return {
|
|
||||||
owner: this.repoOwner,
|
|
||||||
repo: this.repo,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async run() {
|
|
||||||
// TODO: implement pagination on undated entries
|
|
||||||
return await this.client.paginate(
|
|
||||||
this.client.rest.activity.listWatchersForRepo,
|
|
||||||
this.options
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async testRun() {
|
|
||||||
return await this.run();
|
|
||||||
const options = {
|
|
||||||
...this.options,
|
|
||||||
per_page: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (await this.client.rest.activity.listWatchersForRepo(options)).data;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,10 +0,0 @@
|
|||||||
export function assignOwnerAndRepo<T extends { repoOwner?: string; repo?: string; hasRepo?: boolean; }>(object: T, repoFullName: string): T {
|
|
||||||
if (object && repoFullName) {
|
|
||||||
const [repoOwner, repo] = repoFullName.split('/');
|
|
||||||
object.repoOwner = repoOwner;
|
|
||||||
object.repo = repo;
|
|
||||||
object.hasRepo = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return object;
|
|
||||||
}
|
|
@@ -3,8 +3,8 @@ import getCurrentUser from '../common/get-current-user';
|
|||||||
|
|
||||||
const isStillVerified = async ($: IGlobalVariable) => {
|
const isStillVerified = async ($: IGlobalVariable) => {
|
||||||
try {
|
try {
|
||||||
await getCurrentUser($);
|
const user = await getCurrentUser($);
|
||||||
return true;
|
return !!user;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -4,5 +4,6 @@ export default {
|
|||||||
iconUrl: '{BASE_URL}/apps/twitter/assets/favicon.svg',
|
iconUrl: '{BASE_URL}/apps/twitter/assets/favicon.svg',
|
||||||
authDocUrl: 'https://automatisch.io/docs/connections/twitter',
|
authDocUrl: 'https://automatisch.io/docs/connections/twitter',
|
||||||
supportsConnections: true,
|
supportsConnections: true,
|
||||||
baseUrl: 'https://api.twitter.com',
|
baseUrl: 'https://twitter.com',
|
||||||
|
apiBaseUrl: 'https://api.twitter.com',
|
||||||
};
|
};
|
||||||
|
@@ -34,10 +34,10 @@ const getConnectedApps = async (
|
|||||||
const usedApps = [...new Set([...duplicatedUsedApps, ...connectionKeys])];
|
const usedApps = [...new Set([...duplicatedUsedApps, ...connectionKeys])];
|
||||||
|
|
||||||
apps = apps
|
apps = apps
|
||||||
.filter((app: IApp) => {
|
.filter((app) => {
|
||||||
return usedApps.includes(app.key);
|
return usedApps.includes(app.key);
|
||||||
})
|
})
|
||||||
.map((app: IApp) => {
|
.map((app) => {
|
||||||
const connection = connections.find(
|
const connection = connections.find(
|
||||||
(connection) => (connection as IConnection).key === app.key
|
(connection) => (connection as IConnection).key === app.key
|
||||||
);
|
);
|
||||||
@@ -54,7 +54,8 @@ const getConnectedApps = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
});
|
})
|
||||||
|
.sort((appA, appB) => appA.name.localeCompare(appB.name));
|
||||||
|
|
||||||
return apps;
|
return apps;
|
||||||
};
|
};
|
||||||
|
@@ -41,7 +41,7 @@ const globalVariable = async (
|
|||||||
data: connection?.formattedData,
|
data: connection?.formattedData,
|
||||||
},
|
},
|
||||||
app: app,
|
app: app,
|
||||||
http: createHttpClient({ baseURL: app.baseUrl }),
|
http: createHttpClient({ baseURL: app.apiBaseUrl }),
|
||||||
flow: {
|
flow: {
|
||||||
id: flow?.id,
|
id: flow?.id,
|
||||||
lastInternalId,
|
lastInternalId,
|
||||||
|
@@ -10,7 +10,12 @@ class App {
|
|||||||
|
|
||||||
// Temporaryly restrict the apps we expose until
|
// Temporaryly restrict the apps we expose until
|
||||||
// their actions/triggers are implemented!
|
// their actions/triggers are implemented!
|
||||||
static temporaryList = ['slack', 'twitter', 'scheduler'];
|
static temporaryList = [
|
||||||
|
'github',
|
||||||
|
'scheduler',
|
||||||
|
'slack',
|
||||||
|
'twitter',
|
||||||
|
];
|
||||||
|
|
||||||
static async findAll(name?: string, stripFuncs = true): Promise<IApp[]> {
|
static async findAll(name?: string, stripFuncs = true): Promise<IApp[]> {
|
||||||
if (!name)
|
if (!name)
|
||||||
|
@@ -26,7 +26,6 @@
|
|||||||
"src/apps/discord",
|
"src/apps/discord",
|
||||||
"src/apps/firebase",
|
"src/apps/firebase",
|
||||||
"src/apps/flickr",
|
"src/apps/flickr",
|
||||||
"src/apps/github",
|
|
||||||
"src/apps/gitlab",
|
"src/apps/gitlab",
|
||||||
"src/apps/twitch",
|
"src/apps/twitch",
|
||||||
"src/apps/typeform"
|
"src/apps/typeform"
|
||||||
|
@@ -29,11 +29,11 @@ export default defineConfig({
|
|||||||
text: 'Connections',
|
text: 'Connections',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
items: [
|
items: [
|
||||||
{ text: 'Twitter', link: '/connections/twitter' },
|
{ text: 'Github', link: '/connections/github' },
|
||||||
{ text: 'Slack', link: '/connections/slack' },
|
|
||||||
{ text: 'Scheduler', link: '/connections/scheduler' },
|
{ text: 'Scheduler', link: '/connections/scheduler' },
|
||||||
|
{ text: 'Slack', link: '/connections/slack' },
|
||||||
|
{ text: 'Twitter', link: '/connections/twitter' },
|
||||||
// Temporarily disable following pages until we release github and typeform integrations
|
// Temporarily disable following pages until we release github and typeform integrations
|
||||||
// { text: 'Github', link: '/connections/github' },
|
|
||||||
// { text: 'Typeform', link: '/connections/typeform' },
|
// { text: 'Typeform', link: '/connections/typeform' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
1
packages/types/index.d.ts
vendored
1
packages/types/index.d.ts
vendored
@@ -157,6 +157,7 @@ export interface IApp {
|
|||||||
authDocUrl: string;
|
authDocUrl: string;
|
||||||
primaryColor: string;
|
primaryColor: string;
|
||||||
supportsConnections: boolean;
|
supportsConnections: boolean;
|
||||||
|
apiBaseUrl: string;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
auth: IAuth;
|
auth: IAuth;
|
||||||
connectionCount: number;
|
connectionCount: number;
|
||||||
|
Reference in New Issue
Block a user