Working fixing integrations race condition

This commit is contained in:
Tuan Dang
2023-01-13 16:36:34 +07:00
parent f57f3e6475
commit 6992c51e17
2 changed files with 116 additions and 117 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ const validateSecrets = async ({
try { try {
secrets = await Secret.find({ secrets = await Secret.find({
_id: { _id: {
$in: secretIds $in: secretIds.map((secretId: string) => new Types.ObjectId(secretId))
} }
}); });
+115 -116
View File
@@ -1,4 +1,4 @@
import axios from 'axios'; import axios, { AxiosError } from 'axios';
import * as Sentry from '@sentry/node'; import * as Sentry from '@sentry/node';
import { Octokit } from '@octokit/rest'; import { Octokit } from '@octokit/rest';
// import * as sodium from 'libsodium-wrappers'; // import * as sodium from 'libsodium-wrappers';
@@ -145,7 +145,6 @@ const syncSecretsVercel = async ({
secrets: any; secrets: any;
accessToken: string; accessToken: string;
}) => { }) => {
interface VercelSecret { interface VercelSecret {
id?: string; id?: string;
type: string; type: string;
@@ -155,131 +154,131 @@ const syncSecretsVercel = async ({
} }
try { try {
// Get all (decrypted) secrets back from Vercel in // Get all (decrypted) secrets back from Vercel in
// decrypted format // decrypted format
const params: { [key: string]: string } = { const params: { [key: string]: string } = {
decrypt: 'true', decrypt: 'true',
...( integrationAuth?.teamId ? { ...( integrationAuth?.teamId ? {
teamId: integrationAuth.teamId teamId: integrationAuth.teamId
} : {}) } : {})
} }
const res = (await Promise.all((await axios.get( const res = (await Promise.all((await axios.get(
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`, `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`,
{ {
params,
headers: {
Authorization: `Bearer ${accessToken}`
}
}
))
.data
.envs
.filter((secret: VercelSecret) => secret.target.includes(integration.target))
.map(async (secret: VercelSecret) => (await axios.get(
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`,
{
params, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
} }
} }
)) )).data)
.data )).reduce((obj: any, secret: any) => ({
.envs ...obj,
.filter((secret: VercelSecret) => secret.target.includes(integration.target)) [secret.key]: secret
.map(async (secret: VercelSecret) => (await axios.get( }), {});
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`,
{ const updateSecrets: VercelSecret[] = [];
params, const deleteSecrets: VercelSecret[] = [];
headers: { const newSecrets: VercelSecret[] = [];
Authorization: `Bearer ${accessToken}`
}
}
)).data)
)).reduce((obj: any, secret: any) => ({
...obj,
[secret.key]: secret
}), {});
const updateSecrets: VercelSecret[] = [];
const deleteSecrets: VercelSecret[] = [];
const newSecrets: VercelSecret[] = [];
// Identify secrets to create // Identify secrets to create
Object.keys(secrets).map((key) => { Object.keys(secrets).map((key) => {
if (!(key in res)) { if (!(key in res)) {
// case: secret has been created // case: secret has been created
newSecrets.push({ newSecrets.push({
key: key, key: key,
value: secrets[key], value: secrets[key],
type: 'encrypted', type: 'encrypted',
target: [integration.target] target: [integration.target]
}); });
} }
}); });
// Identify secrets to update and delete // Identify secrets to update and delete
Object.keys(res).map((key) => { Object.keys(res).map((key) => {
if (key in secrets) { if (key in secrets) {
if (res[key].value !== secrets[key]) { if (res[key].value !== secrets[key]) {
// case: secret value has changed // case: secret value has changed
updateSecrets.push({ updateSecrets.push({
id: res[key].id, id: res[key].id,
key: key, key: key,
value: secrets[key], value: secrets[key],
type: 'encrypted', type: 'encrypted',
target: [integration.target] target: [integration.target]
}); });
} }
} else { } else {
// case: secret has been deleted // case: secret has been deleted
deleteSecrets.push({ deleteSecrets.push({
id: res[key].id, id: res[key].id,
key: key, key: key,
value: res[key].value, value: res[key].value,
type: 'encrypted', type: 'encrypted',
target: [integration.target], target: [integration.target],
}); });
} }
}); });
// Sync/push new secrets // Sync/push new secrets
if (newSecrets.length > 0) { if (newSecrets.length > 0) {
await axios.post( await axios.post(
`${INTEGRATION_VERCEL_API_URL}/v10/projects/${integration.app}/env`, `${INTEGRATION_VERCEL_API_URL}/v10/projects/${integration.app}/env`,
newSecrets, newSecrets,
{ {
params, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
}
} }
); }
} );
}
// Sync/push updated secrets // Sync/push updated secrets
if (updateSecrets.length > 0) { if (updateSecrets.length > 0) {
updateSecrets.forEach(async (secret: VercelSecret) => { updateSecrets.forEach(async (secret: VercelSecret) => {
const { const {
id, id,
...updatedSecret ...updatedSecret
} = secret; } = secret;
await axios.patch( await axios.patch(
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`,
updatedSecret, updatedSecret,
{ {
params, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
}
} }
); }
}); );
} });
}
// Delete secrets // Delete secrets
if (deleteSecrets.length > 0) { if (deleteSecrets.length > 0) {
deleteSecrets.forEach(async (secret: VercelSecret) => { deleteSecrets.forEach(async (secret: VercelSecret) => {
await axios.delete( await axios.delete(
`${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`,
{ {
params, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`
}
} }
); }
}); );
} });
}
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);