Merge pull request #1172 from Shraeyas/cloudflare-workers

Add Integration for Cloudflare Workers
This commit is contained in:
vmatsiiako
2023-11-22 22:05:35 -08:00
committed by GitHub
9 changed files with 391 additions and 0 deletions
+42
View File
@@ -10,6 +10,8 @@ import {
INTEGRATION_CIRCLECI_API_URL,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_PAGES_API_URL,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CLOUDFLARE_WORKERS_API_URL,
INTEGRATION_CLOUD_66,
INTEGRATION_CLOUD_66_API_URL,
INTEGRATION_CODEFRESH,
@@ -186,6 +188,12 @@ const getApps = async ({
accountId: accessId
});
break;
case INTEGRATION_CLOUDFLARE_WORKERS:
apps = await getAppsCloudflareWorkers({
accessToken,
accountId: accessId
});
break;
case INTEGRATION_NORTHFLANK:
apps = await getAppsNorthflank({
accessToken
@@ -968,6 +976,40 @@ const getAppsCloudflarePages = async ({
return apps;
};
/**
* Return list of projects for the Cloudflare Workers integration
* @param {Object} obj
* @param {String} obj.accessToken - api key for the Cloudflare API
* @returns {Object[]} apps - Cloudflare Workers projects
* @returns {String} apps.id - Id of Cloudflare Workers project
* @returns {String} apps.name - Id of Cloudflare Workers project (Cloudflare workers API does not return the name)
*/
const getAppsCloudflareWorkers = async ({
accessToken,
accountId
}: {
accessToken: string;
accountId?: string;
}) => {
const { data } = await standardRequest.get(
`${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accountId}/workers/services`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
}
}
);
const apps = data.result.map((a: any) => {
return {
name: a.id,
appId: a.id
};
});
return apps;
};
/**
* Return list of repositories for the BitBucket integration based on provided BitBucket workspace
* @param {Object} obj
+102
View File
@@ -18,6 +18,8 @@ import {
INTEGRATION_CIRCLECI_API_URL,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_PAGES_API_URL,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CLOUDFLARE_WORKERS_API_URL,
INTEGRATION_CLOUD_66,
INTEGRATION_CLOUD_66_API_URL,
INTEGRATION_CODEFRESH,
@@ -262,6 +264,14 @@ const syncSecrets = async ({
accessToken
});
break;
case INTEGRATION_CLOUDFLARE_WORKERS:
await syncSecretsCloudflareWorkers({
integration,
secrets,
accessId,
accessToken
});
break;
case INTEGRATION_CODEFRESH:
await syncSecretsCodefresh({
integration,
@@ -2746,6 +2756,98 @@ const syncSecretsCloudflarePages = async ({
);
};
/**
* Sync/push [secrets] to Cloudflare Workers project with name [integration.app]
* @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 - API token for Cloudflare workers
*/
const syncSecretsCloudflareWorkers = async ({
integration,
secrets,
accessId,
accessToken
}: {
integration: IIntegration;
secrets: Record<string, { value: string; comment?: string }>;
accessId: string | null;
accessToken: string;
}) => {
// get secrets from cloudflare workers
const getSecretsRes = (
await standardRequest.get(
`${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accessId}/workers/scripts/${integration.app}/secrets`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
}
}
)
).data.result;
const secretsObj: any = getSecretKeyValuePair(secrets);
for (const [key, val] of Object.entries(secretsObj)) {
secretsObj[key] = { type: "secret_text", value: val };
}
// get deleted secrets list
const deletedSecretKeys: string[] = [];
if (getSecretsRes) {
getSecretsRes.forEach((secretRes: any) => {
if (!(Object.keys(secrets).includes(secretRes.name))) {
deletedSecretKeys.push(secretRes.name);
}
})
}
deletedSecretKeys.forEach(async (secretKey) => {
await standardRequest.delete(
`${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accessId}/workers/scripts/${integration.app}/secrets/${secretKey}`,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
}
}
);
});
interface ConvertedSecret {
name: string;
text: string;
type: string;
}
interface SecretsObj {
[key: string]: {
type: string;
value: string;
};
}
const data: ConvertedSecret[] = Object.entries(secretsObj as SecretsObj).map(([name, secret]) => ({
name,
text: secret.value,
type: "secret_text"
}));
data.forEach(async (secret) => {
await standardRequest.put(
`${INTEGRATION_CLOUDFLARE_WORKERS_API_URL}/client/v4/accounts/${accessId}/workers/scripts/${integration.app}/secrets`,
secret,
{
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
}
}
);
})
};
/**
* Sync/push [secrets] to BitBucket repo with name [integration.app]
* @param {Object} obj
@@ -6,6 +6,7 @@ import {
INTEGRATION_CHECKLY,
INTEGRATION_CIRCLECI,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CLOUD_66,
INTEGRATION_CODEFRESH,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
@@ -71,6 +72,7 @@ export interface IIntegration {
| "teamcity"
| "hashicorp-vault"
| "cloudflare-pages"
| "cloudflare-workers"
| "bitbucket"
| "codefresh"
| "digital-ocean-app-platform"
@@ -179,6 +181,7 @@ const integrationSchema = new Schema<IIntegration>(
INTEGRATION_TEAMCITY,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
@@ -8,6 +8,7 @@ import {
INTEGRATION_BITBUCKET,
INTEGRATION_CIRCLECI,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CLOUD_66,
INTEGRATION_CODEFRESH,
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
@@ -55,6 +56,7 @@ export interface IIntegrationAuth extends Document {
| "checkly"
| "qovery"
| "cloudflare-pages"
| "cloudflare-workers"
| "codefresh"
| "digital-ocean-app-platform"
| "bitbucket"
@@ -113,6 +115,7 @@ const integrationAuthSchema = new Schema<IIntegrationAuth>(
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
+12
View File
@@ -32,6 +32,7 @@ export const INTEGRATION_QOVERY = "qovery";
export const INTEGRATION_TERRAFORM_CLOUD = "terraform-cloud";
export const INTEGRATION_HASHICORP_VAULT = "hashicorp-vault";
export const INTEGRATION_CLOUDFLARE_PAGES = "cloudflare-pages";
export const INTEGRATION_CLOUDFLARE_WORKERS = "cloudflare-workers";
export const INTEGRATION_BITBUCKET = "bitbucket";
export const INTEGRATION_CODEFRESH = "codefresh";
export const INTEGRATION_WINDMILL = "windmill";
@@ -59,6 +60,7 @@ export const INTEGRATION_SET = new Set([
INTEGRATION_TERRAFORM_CLOUD,
INTEGRATION_HASHICORP_VAULT,
INTEGRATION_CLOUDFLARE_PAGES,
INTEGRATION_CLOUDFLARE_WORKERS,
INTEGRATION_CODEFRESH,
INTEGRATION_WINDMILL,
INTEGRATION_BITBUCKET,
@@ -101,6 +103,7 @@ export const INTEGRATION_CHECKLY_API_URL = "https://api.checklyhq.com";
export const INTEGRATION_QOVERY_API_URL = "https://api.qovery.com";
export const INTEGRATION_TERRAFORM_CLOUD_API_URL = "https://app.terraform.io";
export const INTEGRATION_CLOUDFLARE_PAGES_API_URL = "https://api.cloudflare.com";
export const INTEGRATION_CLOUDFLARE_WORKERS_API_URL = "https://api.cloudflare.com";
export const INTEGRATION_BITBUCKET_API_URL = "https://api.bitbucket.org";
export const INTEGRATION_CODEFRESH_API_URL = "https://g.codefresh.io/api";
export const INTEGRATION_WINDMILL_API_URL = "https://app.windmill.dev/api";
@@ -316,6 +319,15 @@ export const getIntegrationOptions = async () => {
clientId: "",
docsLink: ""
},
{
name: "Cloudflare Workers",
slug: "cloudflare-workers",
image: "Cloudflare.png",
isAvailable: true,
type: "pat",
clientId: "",
docsLink: ""
},
{
name: "BitBucket",
slug: "bitbucket",