diff --git a/backend/src/services/integration-auth/integration-sync-secret.ts b/backend/src/services/integration-auth/integration-sync-secret.ts index 9d8ee8895..123578e70 100644 --- a/backend/src/services/integration-auth/integration-sync-secret.ts +++ b/backend/src/services/integration-auth/integration-sync-secret.ts @@ -1363,38 +1363,41 @@ const syncSecretsGitHub = async ({ } } - for await (const encryptedSecret of encryptedSecrets) { - if ( - !(encryptedSecret.name in secrets) && - !(appendices?.prefix !== undefined && !encryptedSecret.name.startsWith(appendices?.prefix)) && - !(appendices?.suffix !== undefined && !encryptedSecret.name.endsWith(appendices?.suffix)) - ) { - switch (integration.scope) { - case GithubScope.Org: { - await octokit.request("DELETE /orgs/{org}/actions/secrets/{secret_name}", { - org: integration.owner as string, - secret_name: encryptedSecret.name - }); - break; - } - case GithubScope.Env: { - await octokit.request( - "DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}", - { - repository_id: Number(integration.appId), - environment_name: integration.targetEnvironmentId as string, + const metadata = z.record(z.any()).parse(integration.metadata); + if (!metadata.shouldDisableDelete) { + for await (const encryptedSecret of encryptedSecrets) { + if ( + !(encryptedSecret.name in secrets) && + !(appendices?.prefix !== undefined && !encryptedSecret.name.startsWith(appendices?.prefix)) && + !(appendices?.suffix !== undefined && !encryptedSecret.name.endsWith(appendices?.suffix)) + ) { + switch (integration.scope) { + case GithubScope.Org: { + await octokit.request("DELETE /orgs/{org}/actions/secrets/{secret_name}", { + org: integration.owner as string, secret_name: encryptedSecret.name - } - ); - break; - } - default: { - await octokit.request("DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", { - owner: integration.owner as string, - repo: integration.app as string, - secret_name: encryptedSecret.name - }); - break; + }); + break; + } + case GithubScope.Env: { + await octokit.request( + "DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}", + { + repository_id: Number(integration.appId), + environment_name: integration.targetEnvironmentId as string, + secret_name: encryptedSecret.name + } + ); + break; + } + default: { + await octokit.request("DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", { + owner: integration.owner as string, + repo: integration.app as string, + secret_name: encryptedSecret.name + }); + break; + } } } } diff --git a/frontend/src/pages/integrations/github/create.tsx b/frontend/src/pages/integrations/github/create.tsx index e42a7e9eb..2a92b07e6 100644 --- a/frontend/src/pages/integrations/github/create.tsx +++ b/frontend/src/pages/integrations/github/create.tsx @@ -33,6 +33,7 @@ import { Input, Select, SelectItem, + Switch, Tab, TabList, TabPanel, @@ -59,7 +60,7 @@ const schema = yup.object({ selectedSourceEnvironment: yup.string().trim().required("Project Environment is required"), secretPath: yup.string().trim().required("Secrets Path is required"), secretSuffix: yup.string().trim().optional(), - + shouldDisableDelete: yup.boolean().optional(), scope: yup.mixed().oneOf(targetEnv.slice()).required(), repoIds: yup.mixed().when("scope", { @@ -98,7 +99,6 @@ type FormData = yup.InferType; export default function GitHubCreateIntegrationPage() { const router = useRouter(); const { mutateAsync } = useCreateIntegration(); - const integrationAuthId = (queryString.parse(router.asPath.split("?")[1]).integrationAuthId as string) ?? ""; @@ -120,7 +120,8 @@ export default function GitHubCreateIntegrationPage() { defaultValues: { secretPath: "/", scope: "github-repo", - repoIds: [] + repoIds: [], + shouldDisableDelete: false } }); @@ -177,7 +178,8 @@ export default function GitHubCreateIntegrationPage() { app: targetApp.name, // repo name owner: targetApp.owner, // repo owner metadata: { - secretSuffix: data.secretSuffix + secretSuffix: data.secretSuffix, + shouldDisableDelete: data.shouldDisableDelete } }); }) @@ -194,7 +196,8 @@ export default function GitHubCreateIntegrationPage() { scope: data.scope, owner: integrationAuthOrgs?.find((e) => e.orgId === data.orgId)?.name, metadata: { - secretSuffix: data.secretSuffix + secretSuffix: data.secretSuffix, + shouldDisableDelete: data.shouldDisableDelete } }); break; @@ -211,7 +214,8 @@ export default function GitHubCreateIntegrationPage() { owner: repoOwner, targetEnvironmentId: data.envId, metadata: { - secretSuffix: data.secretSuffix + secretSuffix: data.secretSuffix, + shouldDisableDelete: data.shouldDisableDelete } }); break; @@ -546,6 +550,21 @@ export default function GitHubCreateIntegrationPage() { animate={{ opacity: 1, translateX: 0 }} exit={{ opacity: 0, translateX: 30 }} > +
+ ( + onChange(isChecked)} + isChecked={value} + > + Disable secrets deletion on Github + + )} + /> +