From 77fdb6307c091713493da852db52c188fc95b8f3 Mon Sep 17 00:00:00 2001 From: Tuan Dang Date: Sun, 23 Jul 2023 22:16:27 +0700 Subject: [PATCH] Optimize Cloud66 integration sync function --- backend/src/integrations/apps.ts | 9 +- backend/src/integrations/sync.ts | 94 ++++++++++++------- .../pages/integrations/cloud-66/authorize.tsx | 4 +- .../pages/integrations/cloud-66/create.tsx | 4 +- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/backend/src/integrations/apps.ts b/backend/src/integrations/apps.ts index 34dae9417..51cf43c45 100644 --- a/backend/src/integrations/apps.ts +++ b/backend/src/integrations/apps.ts @@ -826,7 +826,6 @@ const getAppsBitBucket = async ({ * @returns {Object[]} apps - names of Supabase apps * @returns {String} apps.name - name of Supabase app */ - const getAppsCodefresh = async ({ accessToken, }: { @@ -851,9 +850,13 @@ const getAppsCodefresh = async ({ }; /** - * Return list of projects for Cloud 66 integration + * Return list of applications for Cloud66 integration + * @param {Object} obj + * @param {String} obj.accessToken - personal access token for Cloud66 API + * @returns {Object[]} apps - Cloud66 apps + * @returns {String} apps.name - name of Cloud66 app + * @returns {String} apps.appId - uid of Cloud66 app */ - const getAppsCloud66 = async ({ accessToken }: { accessToken: string }) => { interface Cloud66Apps { uid: string; diff --git a/backend/src/integrations/sync.ts b/backend/src/integrations/sync.ts index d8e6b6116..aef9c52fe 100644 --- a/backend/src/integrations/sync.ts +++ b/backend/src/integrations/sync.ts @@ -2077,10 +2077,11 @@ const syncSecretsBitBucket = async ({ } } -/* - * Sync/push [secrets] to Codefresh with name [integration.app] +/** + * Sync/push [secrets] to Codefresh project with name [integration.app] * @param {Object} obj * @param {IIntegration} obj.integration - integration details + * @param {IIntegrationAuth} obj.integrationAuth - integration auth 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 Codefresh integration */ @@ -2110,7 +2111,14 @@ const syncSecretsCodefresh = async ({ ); }; - +/** + * Sync/push [secrets] to Cloud66 application with name [integration.app] + * @param {Object} obj + * @param {IIntegration} obj.integration - integration details + * @param {IIntegrationAuth} obj.integrationAuth - integration auth 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 Cloud66 integration + */ const syncSecretsCloud66 = async ({ integration, secrets, @@ -2133,7 +2141,7 @@ const syncSecretsCloud66 = async ({ } // get all current secrets - const currentSecrets = ( + const res = ( await standardRequest.get( `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, { @@ -2143,36 +2151,26 @@ const syncSecretsCloud66 = async ({ } } ) - ).data.response as Cloud66Secret[]; - - // filter out generated secrets - const secretsToDelete = currentSecrets.filter((s) => !s.is_generated); - - // delete all current secrets - await Promise.all( - secretsToDelete.map( - async (s) => - await standardRequest.delete( - `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${s.key}`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json" - } - } - ) - ) + ) + .data + .response + .filter((secret: Cloud66Secret) => !secret.readonly || !secret.is_generated) + .reduce( + (obj: any, secret: any) => ({ + ...obj, + [secret.key]: secret + }), + {} ); - // add new secrets - await Promise.all( - Object.entries(secrets).map( - async ([key, value]) => - await standardRequest.post( - `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, + for await (const key of Object.keys(secrets)) { + if (key in res) { + // update existing secret + await standardRequest.put( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${key}`, { key, - value + value: secrets[key] }, { headers: { @@ -2180,9 +2178,39 @@ const syncSecretsCloud66 = async ({ Accept: "application/json" } } - ) - ) - ); + ); + } else { + // create new secret + await standardRequest.post( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, + { + key, + value: secrets[key] + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); + } + } + + for await (const key of Object.keys(res)) { + if (!(key in secrets)) { + // delete secret + await standardRequest.delete( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${key}`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); + } + } }; export { syncSecrets }; diff --git a/frontend/src/pages/integrations/cloud-66/authorize.tsx b/frontend/src/pages/integrations/cloud-66/authorize.tsx index 0af32b56d..8c6434936 100644 --- a/frontend/src/pages/integrations/cloud-66/authorize.tsx +++ b/frontend/src/pages/integrations/cloud-66/authorize.tsx @@ -14,7 +14,7 @@ export default function Cloud66CreateIntegrationPage() { try { setApiKeyErrorText(""); if (apiKey.length === 0) { - setApiKeyErrorText("API Key cannot be blank"); + setApiKeyErrorText("Access token cannot be blank"); return; } @@ -42,7 +42,7 @@ export default function Cloud66CreateIntegrationPage() { Cloud 66 Integration diff --git a/frontend/src/pages/integrations/cloud-66/create.tsx b/frontend/src/pages/integrations/cloud-66/create.tsx index 326e417e5..dbf566464 100644 --- a/frontend/src/pages/integrations/cloud-66/create.tsx +++ b/frontend/src/pages/integrations/cloud-66/create.tsx @@ -113,7 +113,7 @@ export default function Cloud66CreateIntegrationPage() { placeholder="Provide a path, default is /" /> - +