Merge pull request #1102 from G3root/hasura-cloud

feat: add hasura cloud integration
This commit is contained in:
BlackMagiq
2023-10-23 20:37:52 +01:00
committed by GitHub
18 changed files with 1415 additions and 841 deletions
File diff suppressed because it is too large Load Diff
+171 -29
View File
@@ -32,6 +32,8 @@ import {
INTEGRATION_GITLAB,
INTEGRATION_GITLAB_API_URL,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_HASURA_CLOUD,
INTEGRATION_HASURA_CLOUD_API_URL,
INTEGRATION_HEROKU,
INTEGRATION_HEROKU_API_URL,
INTEGRATION_LARAVELFORGE,
@@ -63,6 +65,10 @@ import { Octokit } from "@octokit/rest";
import _ from "lodash";
import sodium from "libsodium-wrappers";
import { standardRequest } from "../config/request";
import {
ZGetTenantEnv,
ZUpdateTenantEnv
} from "../validation/hasuraCloudIntegration";
const getSecretKeyValuePair = (
secrets: Record<string, { value: string | null; comment?: string } | null>
@@ -95,7 +101,7 @@ const syncSecrets = async ({
secrets: Record<string, { value: string; comment?: string }>;
accessId: string | null;
accessToken: string;
appendices?: { prefix: string, suffix: string };
appendices?: { prefix: string; suffix: string };
}) => {
switch (integration.integration) {
case INTEGRATION_GCP_SECRET_MANAGER:
@@ -306,6 +312,14 @@ const syncSecrets = async ({
accessToken
});
break;
case INTEGRATION_HASURA_CLOUD:
await syncSecretsHasuraCloud({
integration,
secrets,
accessToken
});
break;
}
};
@@ -963,8 +977,9 @@ const syncSecretsVercel = async ({
: {}),
...(integration?.path
? {
gitBranch: integration?.path
} : {})
gitBranch: integration?.path
}
: {})
};
const vercelSecrets: VercelSecret[] = (
@@ -992,7 +1007,7 @@ const syncSecretsVercel = async ({
return true;
});
const res: { [key: string]: VercelSecret } = {};
for await (const vercelSecret of vercelSecrets) {
@@ -1352,7 +1367,7 @@ const syncSecretsGitHub = async ({
integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>;
accessToken: string;
appendices?: { prefix: string, suffix: string };
appendices?: { prefix: string; suffix: string };
}) => {
interface GitHubRepoKey {
key_id: string;
@@ -1395,14 +1410,23 @@ const syncSecretsGitHub = async ({
{}
);
encryptedSecrets = Object.keys(encryptedSecrets).reduce((result: {
[key: string]: GitHubSecret;
}, key) => {
if ((appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)) {
result[key] = encryptedSecrets[key];
}
return result;
}, {});
encryptedSecrets = Object.keys(encryptedSecrets).reduce(
(
result: {
[key: string]: GitHubSecret;
},
key
) => {
if (
(appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) &&
(appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)
) {
result[key] = encryptedSecrets[key];
}
return result;
},
{}
);
Object.keys(encryptedSecrets).map(async (key) => {
if (!(key in secrets)) {
@@ -2095,7 +2119,7 @@ const syncSecretsCheckly = async ({
integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>;
accessToken: string;
appendices?: { prefix: string, suffix: string };
appendices?: { prefix: string; suffix: string };
}) => {
let getSecretsRes = (
await standardRequest.get(`${INTEGRATION_CHECKLY_API_URL}/v1/variables`, {
@@ -2113,14 +2137,23 @@ const syncSecretsCheckly = async ({
{}
);
getSecretsRes = Object.keys(getSecretsRes).reduce((result: {
[key: string]: string;
}, key) => {
if ((appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) && (appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)) {
result[key] = getSecretsRes[key];
}
return result;
}, {});
getSecretsRes = Object.keys(getSecretsRes).reduce(
(
result: {
[key: string]: string;
},
key
) => {
if (
(appendices?.prefix !== undefined ? key.startsWith(appendices?.prefix) : true) &&
(appendices?.suffix !== undefined ? key.endsWith(appendices?.suffix) : true)
) {
result[key] = getSecretsRes[key];
}
return result;
},
{}
);
// add secrets
for await (const key of Object.keys(secrets)) {
@@ -2195,18 +2228,20 @@ const syncSecretsQovery = async ({
secrets: Record<string, { value: string; comment?: string }>;
accessToken: string;
}) => {
const getSecretsRes = (
await standardRequest.get(`${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable`, {
headers: {
Authorization: `Token ${accessToken}`,
"Accept-Encoding": "application/json"
await standardRequest.get(
`${INTEGRATION_QOVERY_API_URL}/${integration.scope}/${integration.appId}/environmentVariable`,
{
headers: {
Authorization: `Token ${accessToken}`,
"Accept-Encoding": "application/json"
}
}
})
)
).data.results.reduce(
(obj: any, secret: any) => ({
...obj,
[secret.key]: {"id": secret.id, "value": secret.value}
[secret.key]: { id: secret.id, value: secret.value }
}),
{}
);
@@ -3076,4 +3111,111 @@ const syncSecretsNorthflank = async ({
);
};
/** Sync/push [secrets] to Hasura Cloud
* @param {Object} obj
* @param {IIntegration} obj.integration - integration details
* @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values)
* @param {String} obj.accessToken - access token for Hasura Cloud integration
*/
const syncSecretsHasuraCloud = async ({
integration,
secrets,
accessToken
}: {
integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>;
accessToken: string;
}) => {
const res = await standardRequest.post(
INTEGRATION_HASURA_CLOUD_API_URL,
{
query:
"query MyQuery($tenantId: uuid!) { getTenantEnv(tenantId: $tenantId) { hash envVars } }",
variables: {
tenantId: integration.appId
}
},
{
headers: {
Authorization: `pat ${accessToken}`,
"Content-Type": "application/json"
}
}
);
const {
data: {
getTenantEnv: { hash, envVars }
}
} = ZGetTenantEnv.parse(res.data);
let currentHash = hash;
const secretsToUpdate = Object.keys(secrets).map((key) => {
return ({
key,
value: secrets[key].value
});
});
if (secretsToUpdate.length) {
// update secrets
const addRequest = await standardRequest.post(
INTEGRATION_HASURA_CLOUD_API_URL,
{
query:
"mutation MyQuery($currentHash: String!, $envs: [UpdateEnvObject!]!, $tenantId: uuid!) { updateTenantEnv(currentHash: $currentHash, envs: $envs, tenantId: $tenantId) { hash envVars} }",
variables: {
currentHash,
envs: secretsToUpdate,
tenantId: integration.appId
}
},
{
headers: {
Authorization: `pat ${accessToken}`,
"Content-Type": "application/json"
}
}
);
const addRequestResponse = ZUpdateTenantEnv.safeParse(addRequest.data);
if (addRequestResponse.success) {
currentHash = addRequestResponse.data.data.updateTenantEnv.hash;
}
}
const secretsToDelete = envVars.environment
? Object.keys(envVars.environment).filter((key) => !(key in secrets))
: [];
if (secretsToDelete.length) {
await standardRequest.post(
INTEGRATION_HASURA_CLOUD_API_URL,
{
query: `
mutation deleteTenantEnv($id: uuid!, $currentHash: String!, $env: [String!]!) {
deleteTenantEnv(tenantId: $id, currentHash: $currentHash, deleteEnvs: $env) {
hash
envVars
}
}
`,
variables: {
id: integration.appId,
currentHash,
env: secretsToDelete
}
},
{
headers: {
Authorization: `pat ${accessToken}`,
"Content-Type": "application/json"
}
}
);
}
};
export { syncSecrets };
+23 -20
View File
@@ -14,6 +14,7 @@ import {
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_HASURA_CLOUD,
INTEGRATION_HEROKU,
INTEGRATION_LARAVELFORGE,
INTEGRATION_NETLIFY,
@@ -76,7 +77,8 @@ export interface IIntegration {
| "cloud-66"
| "northflank"
| "windmill"
| "gcp-secret-manager";
| "gcp-secret-manager"
| "hasura-cloud";
integrationAuth: Types.ObjectId;
metadata: Metadata;
}
@@ -86,67 +88,67 @@ const integrationSchema = new Schema<IIntegration>(
workspace: {
type: Schema.Types.ObjectId,
ref: "Workspace",
required: true,
required: true
},
environment: {
type: String,
required: true,
required: true
},
isActive: {
type: Boolean,
required: true,
required: true
},
url: {
// for custom self-hosted integrations (e.g. self-hosted GitHub enterprise)
type: String,
default: null,
default: null
},
app: {
// name of app in provider
type: String,
default: null,
default: null
},
appId: {
// id of app in provider
type: String,
default: null,
default: null
},
targetEnvironment: {
// target environment
type: String,
default: null,
default: null
},
targetEnvironmentId: {
type: String,
default: null,
default: null
},
targetService: {
// railway-specific service
// qovery-specific project
type: String,
default: null,
default: null
},
targetServiceId: {
// railway-specific service
// qovery specific project
type: String,
default: null,
default: null
},
owner: {
// github-specific repo owner-login
type: String,
default: null,
default: null
},
path: {
// aws-parameter-store-specific path
// (also) vercel preview-branch
type: String,
default: null,
default: null
},
region: {
// aws-parameter-store-specific path
type: String,
default: null,
default: null
},
scope: {
// qovery-specific scope
@@ -183,19 +185,20 @@ const integrationSchema = new Schema<IIntegration>(
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_CLOUD_66,
INTEGRATION_NORTHFLANK,
INTEGRATION_GCP_SECRET_MANAGER
INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_HASURA_CLOUD
],
required: true,
required: true
},
integrationAuth: {
type: Schema.Types.ObjectId,
ref: "IntegrationAuth",
required: true,
required: true
},
secretPath: {
type: String,
required: true,
default: "/",
default: "/"
},
metadata: {
type: Schema.Types.Mixed,
@@ -203,8 +206,8 @@ const integrationSchema = new Schema<IIntegration>(
}
},
{
timestamps: true,
timestamps: true
}
);
export const Integration = model<IIntegration>("Integration", integrationSchema);
export const Integration = model<IIntegration>("Integration", integrationSchema);
@@ -1,205 +1,203 @@
import {
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8,
INTEGRATION_AWS_PARAMETER_STORE,
INTEGRATION_AWS_SECRET_MANAGER,
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_BITBUCKET,
INTEGRATION_CIRCLECI,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUD_66,
INTEGRATION_CODEFRESH,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_FLYIO,
INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_HEROKU,
INTEGRATION_LARAVELFORGE,
INTEGRATION_NETLIFY,
INTEGRATION_NORTHFLANK,
INTEGRATION_RAILWAY,
INTEGRATION_RENDER,
INTEGRATION_SUPABASE,
INTEGRATION_TEAMCITY,
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_TRAVISCI,
INTEGRATION_VERCEL,
INTEGRATION_WINDMILL
} from "../../variables";
import { Document, Schema, Types, model } from "mongoose";
import { IntegrationAuthMetadata } from "./types";
export interface IIntegrationAuth extends Document {
_id: Types.ObjectId;
workspace: Types.ObjectId;
integration:
| "heroku"
| "vercel"
| "netlify"
| "github"
| "gitlab"
| "render"
| "railway"
| "flyio"
| "azure-key-vault"
| "laravel-forge"
| "circleci"
| "travisci"
| "supabase"
| "aws-parameter-store"
| "aws-secret-manager"
| "checkly"
| "qovery"
| "cloudflare-pages"
| "codefresh"
| "digital-ocean-app-platform"
| "bitbucket"
| "cloud-66"
| "terraform-cloud"
| "teamcity"
| "northflank"
| "windmill"
| "gcp-secret-manager";
teamId: string;
accountId: string;
url: string;
namespace: string;
refreshCiphertext?: string;
refreshIV?: string;
refreshTag?: string;
accessIdCiphertext?: string;
accessIdIV?: string;
accessIdTag?: string;
accessCiphertext?: string;
accessIV?: string;
accessTag?: string;
algorithm?: "aes-256-gcm";
keyEncoding?: "utf8" | "base64";
accessExpiresAt?: Date;
metadata?: IntegrationAuthMetadata;
}
const integrationAuthSchema = new Schema<IIntegrationAuth>(
{
workspace: {
type: Schema.Types.ObjectId,
ref: "Workspace",
required: true,
},
integration: {
type: String,
enum: [
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_AWS_PARAMETER_STORE,
INTEGRATION_AWS_SECRET_MANAGER,
INTEGRATION_HEROKU,
INTEGRATION_VERCEL,
INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_RENDER,
INTEGRATION_RAILWAY,
INTEGRATION_FLYIO,
INTEGRATION_CIRCLECI,
INTEGRATION_LARAVELFORGE,
INTEGRATION_TRAVISCI,
INTEGRATION_TEAMCITY,
INTEGRATION_SUPABASE,
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_CLOUD_66,
INTEGRATION_NORTHFLANK,
INTEGRATION_GCP_SECRET_MANAGER
],
required: true,
},
teamId: {
// vercel-specific integration param
type: String,
},
url: {
// for any self-hosted integrations (e.g. self-hosted hashicorp-vault)
type: String,
},
namespace: {
// hashicorp-vault-specific integration param
type: String,
},
accountId: {
// netlify-specific integration param
type: String,
},
refreshCiphertext: {
type: String,
select: false,
},
refreshIV: {
type: String,
select: false,
},
refreshTag: {
type: String,
select: false,
},
accessIdCiphertext: {
type: String,
select: false,
},
accessIdIV: {
type: String,
select: false,
},
accessIdTag: {
type: String,
select: false,
},
accessCiphertext: {
type: String,
select: false,
},
accessIV: {
type: String,
select: false,
},
accessTag: {
type: String,
select: false,
},
accessExpiresAt: {
type: Date,
select: false,
},
algorithm: { // the encryption algorithm used
type: String,
enum: [ALGORITHM_AES_256_GCM],
required: true,
},
keyEncoding: {
type: String,
enum: [
ENCODING_SCHEME_UTF8,
ENCODING_SCHEME_BASE64,
],
required: true,
},
metadata: {
type: Schema.Types.Mixed
}
ALGORITHM_AES_256_GCM,
ENCODING_SCHEME_BASE64,
ENCODING_SCHEME_UTF8,
INTEGRATION_AWS_PARAMETER_STORE,
INTEGRATION_AWS_SECRET_MANAGER,
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_BITBUCKET,
INTEGRATION_CIRCLECI,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUD_66,
INTEGRATION_CODEFRESH,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_FLYIO,
INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_HASURA_CLOUD,
INTEGRATION_HEROKU,
INTEGRATION_LARAVELFORGE,
INTEGRATION_NETLIFY,
INTEGRATION_NORTHFLANK,
INTEGRATION_RAILWAY,
INTEGRATION_RENDER,
INTEGRATION_SUPABASE,
INTEGRATION_TEAMCITY,
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_TRAVISCI,
INTEGRATION_VERCEL,
INTEGRATION_WINDMILL
} from "../../variables";
import { Document, Schema, Types, model } from "mongoose";
import { IntegrationAuthMetadata } from "./types";
export interface IIntegrationAuth extends Document {
_id: Types.ObjectId;
workspace: Types.ObjectId;
integration:
| "heroku"
| "vercel"
| "netlify"
| "github"
| "gitlab"
| "render"
| "railway"
| "flyio"
| "azure-key-vault"
| "laravel-forge"
| "circleci"
| "travisci"
| "supabase"
| "aws-parameter-store"
| "aws-secret-manager"
| "checkly"
| "qovery"
| "cloudflare-pages"
| "codefresh"
| "digital-ocean-app-platform"
| "bitbucket"
| "cloud-66"
| "terraform-cloud"
| "teamcity"
| "northflank"
| "windmill"
| "gcp-secret-manager"
| "hasura-cloud";
teamId: string;
accountId: string;
url: string;
namespace: string;
refreshCiphertext?: string;
refreshIV?: string;
refreshTag?: string;
accessIdCiphertext?: string;
accessIdIV?: string;
accessIdTag?: string;
accessCiphertext?: string;
accessIV?: string;
accessTag?: string;
algorithm?: "aes-256-gcm";
keyEncoding?: "utf8" | "base64";
accessExpiresAt?: Date;
metadata?: IntegrationAuthMetadata;
}
const integrationAuthSchema = new Schema<IIntegrationAuth>(
{
workspace: {
type: Schema.Types.ObjectId,
ref: "Workspace",
required: true
},
{
timestamps: true,
integration: {
type: String,
enum: [
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_AWS_PARAMETER_STORE,
INTEGRATION_AWS_SECRET_MANAGER,
INTEGRATION_HEROKU,
INTEGRATION_VERCEL,
INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_RENDER,
INTEGRATION_RAILWAY,
INTEGRATION_FLYIO,
INTEGRATION_CIRCLECI,
INTEGRATION_LARAVELFORGE,
INTEGRATION_TRAVISCI,
INTEGRATION_TEAMCITY,
INTEGRATION_SUPABASE,
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_CLOUD_66,
INTEGRATION_NORTHFLANK,
INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_HASURA_CLOUD
],
required: true
},
teamId: {
// vercel-specific integration param
type: String
},
url: {
// for any self-hosted integrations (e.g. self-hosted hashicorp-vault)
type: String
},
namespace: {
// hashicorp-vault-specific integration param
type: String
},
accountId: {
// netlify-specific integration param
type: String
},
refreshCiphertext: {
type: String,
select: false
},
refreshIV: {
type: String,
select: false
},
refreshTag: {
type: String,
select: false
},
accessIdCiphertext: {
type: String,
select: false
},
accessIdIV: {
type: String,
select: false
},
accessIdTag: {
type: String,
select: false
},
accessCiphertext: {
type: String,
select: false
},
accessIV: {
type: String,
select: false
},
accessTag: {
type: String,
select: false
},
accessExpiresAt: {
type: Date,
select: false
},
algorithm: {
// the encryption algorithm used
type: String,
enum: [ALGORITHM_AES_256_GCM],
required: true
},
keyEncoding: {
type: String,
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
required: true
},
metadata: {
type: Schema.Types.Mixed
}
);
export const IntegrationAuth = model<IIntegrationAuth>(
"IntegrationAuth",
integrationAuthSchema
);
},
{
timestamps: true
}
);
export const IntegrationAuth = model<IIntegrationAuth>("IntegrationAuth", integrationAuthSchema);
@@ -0,0 +1,21 @@
import * as z from "zod";
export const ZGetTenantEnv = z.object({
data: z.object({
getTenantEnv: z.object({
hash: z.string(),
envVars: z.object({
environment: z.record(z.any()).optional()
})
})
})
});
export const ZUpdateTenantEnv = z.object({
data: z.object({
updateTenantEnv: z.object({
hash: z.string(),
envVars: z.record(z.any())
})
})
});
+312 -300
View File
@@ -1,12 +1,12 @@
import {
getClientIdAzure,
getClientIdBitBucket,
getClientIdGCPSecretManager,
getClientIdGitHub,
getClientIdGitLab,
getClientIdHeroku,
getClientIdNetlify,
getClientSlugVercel
getClientIdAzure,
getClientIdBitBucket,
getClientIdGCPSecretManager,
getClientIdGitHub,
getClientIdGitLab,
getClientIdHeroku,
getClientIdNetlify,
getClientSlugVercel
} from "../config";
// integrations
@@ -22,7 +22,7 @@ export const INTEGRATION_GITLAB = "gitlab";
export const INTEGRATION_RENDER = "render";
export const INTEGRATION_RAILWAY = "railway";
export const INTEGRATION_FLYIO = "flyio";
export const INTEGRATION_LARAVELFORGE = "laravel-forge"
export const INTEGRATION_LARAVELFORGE = "laravel-forge";
export const INTEGRATION_CIRCLECI = "circleci";
export const INTEGRATION_TRAVISCI = "travisci";
export const INTEGRATION_TEAMCITY = "teamcity";
@@ -38,32 +38,34 @@ export const INTEGRATION_WINDMILL = "windmill";
export const INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM = "digital-ocean-app-platform";
export const INTEGRATION_CLOUD_66 = "cloud-66";
export const INTEGRATION_NORTHFLANK = "northflank";
export const INTEGRATION_HASURA_CLOUD = "hasura-cloud";
export const INTEGRATION_SET = new Set([
INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_HEROKU,
INTEGRATION_VERCEL,
INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_RENDER,
INTEGRATION_FLYIO,
INTEGRATION_CIRCLECI,
INTEGRATION_LARAVELFORGE,
INTEGRATION_TRAVISCI,
INTEGRATION_TEAMCITY,
INTEGRATION_SUPABASE,
INTEGRATION_CHECKLY,
INTEGRATION_QOVERY,
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_CLOUD_66,
INTEGRATION_NORTHFLANK
INTEGRATION_GCP_SECRET_MANAGER,
INTEGRATION_AZURE_KEY_VAULT,
INTEGRATION_HEROKU,
INTEGRATION_VERCEL,
INTEGRATION_NETLIFY,
INTEGRATION_GITHUB,
INTEGRATION_GITLAB,
INTEGRATION_RENDER,
INTEGRATION_FLYIO,
INTEGRATION_CIRCLECI,
INTEGRATION_LARAVELFORGE,
INTEGRATION_TRAVISCI,
INTEGRATION_TEAMCITY,
INTEGRATION_SUPABASE,
INTEGRATION_CHECKLY,
INTEGRATION_QOVERY,
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
INTEGRATION_CLOUD_66,
INTEGRATION_NORTHFLANK,
INTEGRATION_HASURA_CLOUD
]);
// integration types
@@ -71,15 +73,14 @@ export const INTEGRATION_OAUTH2 = "oauth2";
// integration oauth endpoints
export const INTEGRATION_GCP_TOKEN_URL = "https://oauth2.googleapis.com/token";
export const INTEGRATION_AZURE_TOKEN_URL = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
export const INTEGRATION_AZURE_TOKEN_URL =
"https://login.microsoftonline.com/common/oauth2/v2.0/token";
export const INTEGRATION_HEROKU_TOKEN_URL = "https://id.heroku.com/oauth/token";
export const INTEGRATION_VERCEL_TOKEN_URL =
"https://api.vercel.com/v2/oauth/access_token";
export const INTEGRATION_VERCEL_TOKEN_URL = "https://api.vercel.com/v2/oauth/access_token";
export const INTEGRATION_NETLIFY_TOKEN_URL = "https://api.netlify.com/oauth/token";
export const INTEGRATION_GITHUB_TOKEN_URL =
"https://github.com/login/oauth/access_token";
export const INTEGRATION_GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token";
export const INTEGRATION_GITLAB_TOKEN_URL = "https://gitlab.com/oauth/token";
export const INTEGRATION_BITBUCKET_TOKEN_URL = "https://bitbucket.org/site/oauth2/access_token"
export const INTEGRATION_BITBUCKET_TOKEN_URL = "https://bitbucket.org/site/oauth2/access_token";
// integration apps endpoints
export const INTEGRATION_GCP_API_URL = "https://cloudresourcemanager.googleapis.com";
@@ -106,268 +107,279 @@ export const INTEGRATION_WINDMILL_API_URL = "https://app.windmill.dev/api";
export const INTEGRATION_DIGITAL_OCEAN_API_URL = "https://api.digitalocean.com";
export const INTEGRATION_CLOUD_66_API_URL = "https://app.cloud66.com/api";
export const INTEGRATION_NORTHFLANK_API_URL = "https://api.northflank.com";
export const INTEGRATION_HASURA_CLOUD_API_URL = "https://data.pro.hasura.io/v1/graphql";
export const INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME = "secretmanager.googleapis.com"
export const INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME = "secretmanager.googleapis.com";
export const INTEGRATION_GCP_SECRET_MANAGER_URL = `https://${INTEGRATION_GCP_SECRET_MANAGER_SERVICE_NAME}`;
export const INTEGRATION_GCP_SERVICE_USAGE_URL = "https://serviceusage.googleapis.com";
export const INTEGRATION_GCP_CLOUD_PLATFORM_SCOPE = "https://www.googleapis.com/auth/cloud-platform";
export const INTEGRATION_GCP_CLOUD_PLATFORM_SCOPE =
"https://www.googleapis.com/auth/cloud-platform";
export const getIntegrationOptions = async () => {
const INTEGRATION_OPTIONS = [
{
name: "Heroku",
slug: "heroku",
image: "Heroku.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdHeroku(),
docsLink: "",
},
{
name: "Vercel",
slug: "vercel",
image: "Vercel.png",
isAvailable: true,
type: "oauth",
clientId: "",
clientSlug: await getClientSlugVercel(),
docsLink: "",
},
{
name: "Netlify",
slug: "netlify",
image: "Netlify.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdNetlify(),
docsLink: "",
},
{
name: "GitHub",
slug: "github",
image: "GitHub.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdGitHub(),
docsLink: "",
},
{
name: "Render",
slug: "render",
image: "Render.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Railway",
slug: "railway",
image: "Railway.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Fly.io",
slug: "flyio",
image: "Flyio.svg",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "AWS Parameter Store",
slug: "aws-parameter-store",
image: "Amazon Web Services.png",
isAvailable: true,
type: "custom",
clientId: "",
docsLink: "",
},
{
name: "Laravel Forge",
slug: "laravel-forge",
image: "Laravel Forge.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "AWS Secrets Manager",
slug: "aws-secret-manager",
image: "Amazon Web Services.png",
isAvailable: true,
type: "custom",
clientId: "",
docsLink: "",
},
{
name: "Azure Key Vault",
slug: "azure-key-vault",
image: "Microsoft Azure.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdAzure(),
docsLink: "",
},
{
name: "Circle CI",
slug: "circleci",
image: "Circle CI.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "GitLab",
slug: "gitlab",
image: "GitLab.png",
isAvailable: true,
type: "custom",
clientId: await getClientIdGitLab(),
docsLink: "",
},
{
name: "Terraform Cloud",
slug: "terraform-cloud",
image: "Terraform Cloud.png",
isAvailable: true,
type: "pat",
cliendId: "",
docsLink: "",
},
{
name: "Travis CI",
slug: "travisci",
image: "Travis CI.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "TeamCity",
slug: "teamcity",
image: "TeamCity.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Supabase",
slug: "supabase",
image: "Supabase.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Checkly",
slug: "checkly",
image: "Checkly.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Qovery",
slug: "qovery",
image: "Qovery.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "HashiCorp Vault",
slug: "hashicorp-vault",
image: "Vault.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "GCP Secret Manager",
slug: "gcp-secret-manager",
image: "Google Cloud Platform.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdGCPSecretManager(),
docsLink: ""
},
{
name: "Cloudflare Pages",
slug: "cloudflare-pages",
image: "Cloudflare.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "BitBucket",
slug: "bitbucket",
image: "BitBucket.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdBitBucket(),
docsLink: ""
},
{
name: "Codefresh",
slug: "codefresh",
image: "Codefresh.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Windmill",
slug: "windmill",
image: "Windmill.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Digital Ocean App Platform",
slug: "digital-ocean-app-platform",
image: "Digital Ocean.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Cloud 66",
slug: "cloud-66",
image: "Cloud 66.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: "",
},
{
name: "Northflank",
slug: "northflank",
image: "Northflank.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
]
return INTEGRATION_OPTIONS;
}
const INTEGRATION_OPTIONS = [
{
name: "Heroku",
slug: "heroku",
image: "Heroku.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdHeroku(),
docsLink: ""
},
{
name: "Vercel",
slug: "vercel",
image: "Vercel.png",
isAvailable: true,
type: "oauth",
clientId: "",
clientSlug: await getClientSlugVercel(),
docsLink: ""
},
{
name: "Netlify",
slug: "netlify",
image: "Netlify.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdNetlify(),
docsLink: ""
},
{
name: "GitHub",
slug: "github",
image: "GitHub.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdGitHub(),
docsLink: ""
},
{
name: "Render",
slug: "render",
image: "Render.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Railway",
slug: "railway",
image: "Railway.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Fly.io",
slug: "flyio",
image: "Flyio.svg",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "AWS Parameter Store",
slug: "aws-parameter-store",
image: "Amazon Web Services.png",
isAvailable: true,
type: "custom",
clientId: "",
docsLink: ""
},
{
name: "Laravel Forge",
slug: "laravel-forge",
image: "Laravel Forge.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "AWS Secrets Manager",
slug: "aws-secret-manager",
image: "Amazon Web Services.png",
isAvailable: true,
type: "custom",
clientId: "",
docsLink: ""
},
{
name: "Azure Key Vault",
slug: "azure-key-vault",
image: "Microsoft Azure.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdAzure(),
docsLink: ""
},
{
name: "Circle CI",
slug: "circleci",
image: "Circle CI.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "GitLab",
slug: "gitlab",
image: "GitLab.png",
isAvailable: true,
type: "custom",
clientId: await getClientIdGitLab(),
docsLink: ""
},
{
name: "Terraform Cloud",
slug: "terraform-cloud",
image: "Terraform Cloud.png",
isAvailable: true,
type: "pat",
cliendId: "",
docsLink: ""
},
{
name: "Travis CI",
slug: "travisci",
image: "Travis CI.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "TeamCity",
slug: "teamcity",
image: "TeamCity.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Supabase",
slug: "supabase",
image: "Supabase.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Checkly",
slug: "checkly",
image: "Checkly.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Qovery",
slug: "qovery",
image: "Qovery.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "HashiCorp Vault",
slug: "hashicorp-vault",
image: "Vault.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "GCP Secret Manager",
slug: "gcp-secret-manager",
image: "Google Cloud Platform.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdGCPSecretManager(),
docsLink: ""
},
{
name: "Cloudflare Pages",
slug: "cloudflare-pages",
image: "Cloudflare.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "BitBucket",
slug: "bitbucket",
image: "BitBucket.png",
isAvailable: true,
type: "oauth",
clientId: await getClientIdBitBucket(),
docsLink: ""
},
{
name: "Codefresh",
slug: "codefresh",
image: "Codefresh.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Windmill",
slug: "windmill",
image: "Windmill.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Digital Ocean App Platform",
slug: "digital-ocean-app-platform",
image: "Digital Ocean.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Cloud 66",
slug: "cloud-66",
image: "Cloud 66.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Northflank",
slug: "northflank",
image: "Northflank.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "Hasura Cloud",
slug: "hasura-cloud",
image: "Hasura.svg",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
}
];
return INTEGRATION_OPTIONS;
};