diff --git a/.changeset/short-cloths-decide.md b/.changeset/short-cloths-decide.md new file mode 100644 index 0000000000..ae8b9f6c6d --- /dev/null +++ b/.changeset/short-cloths-decide.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-github': patch +--- + +Made "github:deployKey:create" action idempotent diff --git a/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts index 7e674a3e52..7eba3b94c8 100644 --- a/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts +++ b/plugins/scaffolder-backend-module-github/src/actions/githubDeployKey.ts @@ -126,20 +126,35 @@ export function createGithubDeployKeyAction(options: { const client = new Octokit(octokitOptions); - await client.rest.repos.createDeployKey({ - owner: owner, - repo: repo, - title: deployKeyName, - key: publicKey, + await ctx.checkpoint({ + key: `create.deploy.key.${owner}.${repo}.${publicKey}`, + fn: async () => { + await client.rest.repos.createDeployKey({ + owner: owner, + repo: repo, + title: deployKeyName, + key: publicKey, + }); + }, }); - const publicKeyResponse = await client.rest.actions.getRepoPublicKey({ - owner: owner, - repo: repo, + + const { key, keyId } = await ctx.checkpoint({ + key: `get.repo.public.key.${owner}.${repo}`, + fn: async () => { + const publicKeyResponse = await client.rest.actions.getRepoPublicKey({ + owner: owner, + repo: repo, + }); + return { + key: publicKeyResponse.data.key, + keyId: publicKeyResponse.data.key_id, + }; + }, }); await Sodium.ready; const binaryKey = Sodium.from_base64( - publicKeyResponse.data.key, + key, Sodium.base64_variants.ORIGINAL, ); const binarySecret = Sodium.from_string(privateKey); @@ -152,12 +167,17 @@ export function createGithubDeployKeyAction(options: { Sodium.base64_variants.ORIGINAL, ); - await client.rest.actions.createOrUpdateRepoSecret({ - owner: owner, - repo: repo, - secret_name: privateKeySecretName, - encrypted_value: encryptedBase64Secret, - key_id: publicKeyResponse.data.key_id, + await ctx.checkpoint({ + key: `create.or.update.repo.secret.${owner}.${repo}.${keyId}`, + fn: async () => { + await client.rest.actions.createOrUpdateRepoSecret({ + owner: owner, + repo: repo, + secret_name: privateKeySecretName, + encrypted_value: encryptedBase64Secret, + key_id: keyId, + }); + }, }); ctx.output('privateKeySecretName', privateKeySecretName);