fetch apps from circleci

This commit is contained in:
Aashish-Upadhyay-101
2023-02-04 16:50:34 +05:45
parent 5ba851adff
commit b0ffac2f00
4 changed files with 538 additions and 455 deletions
+35 -1
View File
@@ -15,6 +15,7 @@ import {
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_RENDER_API_URL, INTEGRATION_RENDER_API_URL,
INTEGRATION_FLYIO_API_URL, INTEGRATION_FLYIO_API_URL,
INTEGRATION_CIRCLECI_API_URL,
} from "../variables"; } from "../variables";
/** /**
@@ -313,7 +314,40 @@ const getAppsFlyio = async ({ accessToken }: { accessToken: string }) => {
}; };
const getAppsCircleci = async ({ accessToken }: { accessToken: string }) => { const getAppsCircleci = async ({ accessToken }: { accessToken: string }) => {
return []; // in place of accessToken we have to send Circle-Token i.e. Personal API token from CircleCi
let apps: any;
try {
const circleciOrganizationDetail = (
await axios.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, {
headers: {
"Circle-Token": accessToken,
},
})
).data;
const { slug } = circleciOrganizationDetail;
const res = (
await axios.get(
`${INTEGRATION_CIRCLECI_API_URL}/v2/pipeline/?org-slug=${slug}`,
{
headers: {
"Circle-Token": accessToken,
},
}
)
).data.items;
apps = res.map((a: any) => ({
name: a?.project_slug?.split("/")[2],
}));
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error("Failed to get Render services");
}
return apps;
}; };
export { getApps }; export { getApps };
+203 -157
View File
@@ -1,10 +1,10 @@
import axios from 'axios'; import axios 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';
import sodium from 'libsodium-wrappers'; import sodium from "libsodium-wrappers";
// const sodium = require('libsodium-wrappers'); // const sodium = require('libsodium-wrappers');
import { IIntegration, IIntegrationAuth } from '../models'; import { IIntegration, IIntegrationAuth } from "../models";
import { import {
INTEGRATION_HEROKU, INTEGRATION_HEROKU,
INTEGRATION_VERCEL, INTEGRATION_VERCEL,
@@ -12,13 +12,15 @@ import {
INTEGRATION_GITHUB, INTEGRATION_GITHUB,
INTEGRATION_RENDER, INTEGRATION_RENDER,
INTEGRATION_FLYIO, INTEGRATION_FLYIO,
INTEGRATION_CIRCLECI,
INTEGRATION_HEROKU_API_URL, INTEGRATION_HEROKU_API_URL,
INTEGRATION_VERCEL_API_URL, INTEGRATION_VERCEL_API_URL,
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_RENDER_API_URL, INTEGRATION_RENDER_API_URL,
INTEGRATION_FLYIO_API_URL INTEGRATION_FLYIO_API_URL,
} from '../variables'; INTEGRATION_CIRCLECI_API_URL,
import { access, appendFile } from 'fs'; } from "../variables";
import { access, appendFile } from "fs";
/** /**
* Sync/push [secrets] to [app] in integration named [integration] * Sync/push [secrets] to [app] in integration named [integration]
@@ -32,7 +34,7 @@ const syncSecrets = async ({
integration, integration,
integrationAuth, integrationAuth,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration; integration: IIntegration;
integrationAuth: IIntegrationAuth; integrationAuth: IIntegrationAuth;
@@ -45,7 +47,7 @@ const syncSecrets = async ({
await syncSecretsHeroku({ await syncSecretsHeroku({
integration, integration,
secrets, secrets,
accessToken accessToken,
}); });
break; break;
case INTEGRATION_VERCEL: case INTEGRATION_VERCEL:
@@ -53,7 +55,7 @@ const syncSecrets = async ({
integration, integration,
integrationAuth, integrationAuth,
secrets, secrets,
accessToken accessToken,
}); });
break; break;
case INTEGRATION_NETLIFY: case INTEGRATION_NETLIFY:
@@ -61,35 +63,41 @@ const syncSecrets = async ({
integration, integration,
integrationAuth, integrationAuth,
secrets, secrets,
accessToken accessToken,
}); });
break; break;
case INTEGRATION_GITHUB: case INTEGRATION_GITHUB:
await syncSecretsGitHub({ await syncSecretsGitHub({
integration, integration,
secrets, secrets,
accessToken accessToken,
}); });
break; break;
case INTEGRATION_RENDER: case INTEGRATION_RENDER:
await syncSecretsRender({ await syncSecretsRender({
integration, integration,
secrets, secrets,
accessToken accessToken,
}); });
break; break;
case INTEGRATION_FLYIO: case INTEGRATION_FLYIO:
await syncSecretsFlyio({ await syncSecretsFlyio({
integration, integration,
secrets, secrets,
accessToken accessToken,
}); });
break; break;
// case INTEGRATION_CIRCLECI:
// await syncSecretsCircleci({
// integration,
// secrets,
// accessToken,
// });
} }
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to integration'); throw new Error("Failed to sync secrets to integration");
} }
}; };
@@ -103,7 +111,7 @@ const syncSecrets = async ({
const syncSecretsHeroku = async ({ const syncSecretsHeroku = async ({
integration, integration,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration; integration: IIntegration;
secrets: any; secrets: any;
@@ -115,9 +123,9 @@ const syncSecretsHeroku = async ({
`${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, `${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`,
{ {
headers: { headers: {
Accept: 'application/vnd.heroku+json; version=3', Accept: "application/vnd.heroku+json; version=3",
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
) )
).data; ).data;
@@ -133,15 +141,15 @@ const syncSecretsHeroku = async ({
secrets, secrets,
{ {
headers: { headers: {
Accept: 'application/vnd.heroku+json; version=3', Accept: "application/vnd.heroku+json; version=3",
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to Heroku'); throw new Error("Failed to sync secrets to Heroku");
} }
}; };
@@ -155,10 +163,10 @@ const syncSecretsVercel = async ({
integration, integration,
integrationAuth, integrationAuth,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration, integration: IIntegration;
integrationAuth: IIntegrationAuth, integrationAuth: IIntegrationAuth;
secrets: any; secrets: any;
accessToken: string; accessToken: string;
}) => { }) => {
@@ -174,37 +182,52 @@ const syncSecretsVercel = async ({
// 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, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
},
} }
} )
)) ).data.envs
.data .filter((secret: VercelSecret) =>
.envs secret.target.includes(integration.targetEnvironment)
.filter((secret: VercelSecret) => secret.target.includes(integration.targetEnvironment)) )
.map(async (secret: VercelSecret) => (await axios.get( .map(
async (secret: VercelSecret) =>
(
await axios.get(
`${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}`,
},
} }
} )
)).data) ).data
)).reduce((obj: any, secret: any) => ({ )
)
).reduce(
(obj: any, secret: any) => ({
...obj, ...obj,
[secret.key]: secret [secret.key]: secret,
}), {}); }),
{}
);
const updateSecrets: VercelSecret[] = []; const updateSecrets: VercelSecret[] = [];
const deleteSecrets: VercelSecret[] = []; const deleteSecrets: VercelSecret[] = [];
@@ -217,8 +240,8 @@ const syncSecretsVercel = async ({
newSecrets.push({ newSecrets.push({
key: key, key: key,
value: secrets[key], value: secrets[key],
type: 'encrypted', type: "encrypted",
target: [integration.targetEnvironment] target: [integration.targetEnvironment],
}); });
} }
}); });
@@ -232,8 +255,8 @@ const syncSecretsVercel = async ({
id: res[key].id, id: res[key].id,
key: key, key: key,
value: secrets[key], value: secrets[key],
type: 'encrypted', type: "encrypted",
target: [integration.targetEnvironment] target: [integration.targetEnvironment],
}); });
} }
} else { } else {
@@ -242,7 +265,7 @@ const syncSecretsVercel = async ({
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.targetEnvironment], target: [integration.targetEnvironment],
}); });
} }
@@ -256,8 +279,8 @@ const syncSecretsVercel = async ({
{ {
params, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
} }
@@ -265,18 +288,15 @@ const syncSecretsVercel = async ({
// 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, ...updatedSecret } = secret;
id,
...updatedSecret
} = 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}`,
} },
} }
); );
}); });
@@ -290,8 +310,8 @@ const syncSecretsVercel = async ({
{ {
params, params,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
}); });
@@ -299,9 +319,9 @@ const syncSecretsVercel = async ({
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to Vercel'); throw new Error("Failed to sync secrets to Vercel");
} }
} };
/** /**
* Sync/push [secrets] to Netlify site with id [integration.appId] * Sync/push [secrets] to Netlify site with id [integration.appId]
@@ -315,7 +335,7 @@ const syncSecretsNetlify = async ({
integration, integration,
integrationAuth, integrationAuth,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration; integration: IIntegration;
integrationAuth: IIntegrationAuth; integrationAuth: IIntegrationAuth;
@@ -323,7 +343,6 @@ const syncSecretsNetlify = async ({
accessToken: string; accessToken: string;
}) => { }) => {
try { try {
interface NetlifyValue { interface NetlifyValue {
id?: string; id?: string;
context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production', context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production',
@@ -340,24 +359,27 @@ const syncSecretsNetlify = async ({
} }
const getParams = new URLSearchParams({ const getParams = new URLSearchParams({
context_name: 'all', // integration.context or all context_name: "all", // integration.context or all
site_id: integration.appId site_id: integration.appId,
}); });
const res = (await axios.get( const res = (
await axios.get(
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`,
{ {
params: getParams, params: getParams,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
},
} }
} )
)) ).data.reduce(
.data (obj: any, secret: any) => ({
.reduce((obj: any, secret: any) => ({
...obj, ...obj,
[secret.key]: secret [secret.key]: secret,
}), {}); }),
{}
);
const newSecrets: NetlifySecret[] = []; // createEnvVars const newSecrets: NetlifySecret[] = []; // createEnvVars
const deleteSecrets: string[] = []; // deleteEnvVar const deleteSecrets: string[] = []; // deleteEnvVar
@@ -370,18 +392,22 @@ const syncSecretsNetlify = async ({
// case: Infisical secret does not exist in Netlify -> create secret // case: Infisical secret does not exist in Netlify -> create secret
newSecrets.push({ newSecrets.push({
key, key,
values: [{ values: [
{
value: secrets[key], value: secrets[key],
context: integration.targetEnvironment context: integration.targetEnvironment,
}] },
],
}); });
} else { } else {
// case: Infisical secret exists in Netlify // case: Infisical secret exists in Netlify
const contexts = res[key].values const contexts = res[key].values.reduce(
.reduce((obj: any, value: NetlifyValue) => ({ (obj: any, value: NetlifyValue) => ({
...obj, ...obj,
[value.context]: value [value.context]: value,
}), {}); }),
{}
);
if (integration.targetEnvironment in contexts) { if (integration.targetEnvironment in contexts) {
// case: Netlify secret value exists in integration context // case: Netlify secret value exists in integration context
@@ -390,10 +416,12 @@ const syncSecretsNetlify = async ({
// -> update Netlify secret context and value // -> update Netlify secret context and value
updateSecrets.push({ updateSecrets.push({
key, key,
values: [{ values: [
{
context: integration.targetEnvironment, context: integration.targetEnvironment,
value: secrets[key] value: secrets[key],
}] },
],
}); });
} }
} else { } else {
@@ -401,14 +429,16 @@ const syncSecretsNetlify = async ({
// -> add the new Netlify secret context and value // -> add the new Netlify secret context and value
updateSecrets.push({ updateSecrets.push({
key, key,
values: [{ values: [
{
context: integration.targetEnvironment, context: integration.targetEnvironment,
value: secrets[key] value: secrets[key],
}] },
],
}); });
} }
} }
}) });
// identify secrets to delete // identify secrets to delete
// TODO: revise (patch case where 1 context was deleted but others still there // TODO: revise (patch case where 1 context was deleted but others still there
@@ -428,11 +458,13 @@ const syncSecretsNetlify = async ({
// case: Netlify secret value has more than 1 context -> delete secret value context // case: Netlify secret value has more than 1 context -> delete secret value context
deleteSecretValues.push({ deleteSecretValues.push({
key, key,
values: [{ values: [
{
id: value.id, id: value.id,
context: integration.targetEnvironment, context: integration.targetEnvironment,
value: value.value value: value.value,
}] },
],
}); });
} }
} }
@@ -441,7 +473,7 @@ const syncSecretsNetlify = async ({
}); });
const syncParams = new URLSearchParams({ const syncParams = new URLSearchParams({
site_id: integration.appId site_id: integration.appId,
}); });
if (newSecrets.length > 0) { if (newSecrets.length > 0) {
@@ -451,8 +483,8 @@ const syncSecretsNetlify = async ({
{ {
params: syncParams, params: syncParams,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
} }
@@ -463,13 +495,13 @@ const syncSecretsNetlify = async ({
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`, `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
{ {
context: secret.values[0].context, context: secret.values[0].context,
value: secret.values[0].value value: secret.values[0].value,
}, },
{ {
params: syncParams, params: syncParams,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
}); });
@@ -482,8 +514,8 @@ const syncSecretsNetlify = async ({
{ {
params: syncParams, params: syncParams,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
}); });
@@ -496,8 +528,8 @@ const syncSecretsNetlify = async ({
{ {
params: syncParams, params: syncParams,
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
}); });
@@ -505,9 +537,9 @@ const syncSecretsNetlify = async ({
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to Heroku'); throw new Error("Failed to sync secrets to Heroku");
} }
} };
/** /**
* Sync/push [secrets] to GitHub repo with name [integration.app] * Sync/push [secrets] to GitHub repo with name [integration.app]
@@ -520,14 +552,13 @@ const syncSecretsNetlify = async ({
const syncSecretsGitHub = async ({ const syncSecretsGitHub = async ({
integration, integration,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration; integration: IIntegration;
secrets: any; secrets: any;
accessToken: string; accessToken: string;
}) => { }) => {
try { try {
interface GitHubRepoKey { interface GitHubRepoKey {
key_id: string; key_id: string;
key: string; key: string;
@@ -546,41 +577,42 @@ const syncSecretsGitHub = async ({
const deleteSecrets: GitHubSecret[] = []; const deleteSecrets: GitHubSecret[] = [];
const octokit = new Octokit({ const octokit = new Octokit({
auth: accessToken auth: accessToken,
}); });
// const user = (await octokit.request('GET /user', {})).data; // const user = (await octokit.request('GET /user', {})).data;
const repoPublicKey: GitHubRepoKey = (await octokit.request( const repoPublicKey: GitHubRepoKey = (
'GET /repos/{owner}/{repo}/actions/secrets/public-key', await octokit.request(
"GET /repos/{owner}/{repo}/actions/secrets/public-key",
{ {
owner: integration.owner, owner: integration.owner,
repo: integration.app repo: integration.app,
} }
)).data; )
).data;
// Get local copy of decrypted secrets. We cannot decrypt them as we dont have access to GH private key // Get local copy of decrypted secrets. We cannot decrypt them as we dont have access to GH private key
const encryptedSecrets: GitHubSecretRes = (await octokit.request( const encryptedSecrets: GitHubSecretRes = (
'GET /repos/{owner}/{repo}/actions/secrets', await octokit.request("GET /repos/{owner}/{repo}/actions/secrets", {
{
owner: integration.owner, owner: integration.owner,
repo: integration.app repo: integration.app,
} })
)) ).data.secrets.reduce(
.data (obj: any, secret: any) => ({
.secrets
.reduce((obj: any, secret: any) => ({
...obj, ...obj,
[secret.name]: secret [secret.name]: secret,
}), {}); }),
{}
);
Object.keys(encryptedSecrets).map(async (key) => { Object.keys(encryptedSecrets).map(async (key) => {
if (!(key in secrets)) { if (!(key in secrets)) {
await octokit.request( await octokit.request(
'DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}', "DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}",
{ {
owner: integration.owner, owner: integration.owner,
repo: integration.app, repo: integration.app,
secret_name: key secret_name: key,
} }
); );
} }
@@ -606,13 +638,13 @@ const syncSecretsGitHub = async ({
); );
await octokit.request( await octokit.request(
'PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}', "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}",
{ {
owner: integration.owner, owner: integration.owner,
repo: integration.app, repo: integration.app,
secret_name: key, secret_name: key,
encrypted_value: encryptedSecret, encrypted_value: encryptedSecret,
key_id: repoPublicKey.key_id key_id: repoPublicKey.key_id,
} }
); );
}); });
@@ -620,7 +652,7 @@ const syncSecretsGitHub = async ({
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to GitHub'); throw new Error("Failed to sync secrets to GitHub");
} }
}; };
@@ -634,7 +666,7 @@ const syncSecretsGitHub = async ({
const syncSecretsRender = async ({ const syncSecretsRender = async ({
integration, integration,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration; integration: IIntegration;
secrets: any; secrets: any;
@@ -645,20 +677,20 @@ const syncSecretsRender = async ({
`${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`, `${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`,
Object.keys(secrets).map((key) => ({ Object.keys(secrets).map((key) => ({
key, key,
value: secrets[key] value: secrets[key],
})), })),
{ {
headers: { headers: {
Authorization: `Bearer ${accessToken}` Authorization: `Bearer ${accessToken}`,
} },
} }
); );
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to Render'); throw new Error("Failed to sync secrets to Render");
} }
} };
/** /**
* Sync/push [secrets] to Fly.io app * Sync/push [secrets] to Fly.io app
@@ -670,7 +702,7 @@ const syncSecretsRender = async ({
const syncSecretsFlyio = async ({ const syncSecretsFlyio = async ({
integration, integration,
secrets, secrets,
accessToken accessToken,
}: { }: {
integration: IIntegration; integration: IIntegration;
secrets: any; secrets: any;
@@ -700,19 +732,22 @@ const syncSecretsFlyio = async ({
await axios({ await axios({
url: INTEGRATION_FLYIO_API_URL, url: INTEGRATION_FLYIO_API_URL,
method: 'post', method: "post",
headers: { headers: {
'Authorization': 'Bearer ' + accessToken Authorization: "Bearer " + accessToken,
}, },
data: { data: {
query: SetSecrets, query: SetSecrets,
variables: { variables: {
input: { input: {
appId: integration.app, appId: integration.app,
secrets: Object.entries(secrets).map(([key, value]) => ({ key, value })) secrets: Object.entries(secrets).map(([key, value]) => ({
} key,
} value,
} })),
},
},
},
}); });
// get secrets // get secrets
@@ -732,20 +767,22 @@ const syncSecretsFlyio = async ({
} }
}`; }`;
const getSecretsRes = (await axios({ const getSecretsRes = (
method: 'post', await axios({
method: "post",
url: INTEGRATION_FLYIO_API_URL, url: INTEGRATION_FLYIO_API_URL,
headers: { headers: {
'Authorization': 'Bearer ' + accessToken, Authorization: "Bearer " + accessToken,
'Content-Type': 'application/json' "Content-Type": "application/json",
}, },
data: { data: {
query: GetSecrets, query: GetSecrets,
variables: { variables: {
appName: integration.app appName: integration.app,
} },
} },
})).data.data.app.secrets; })
).data.data.app.secrets;
const deleteSecretsKeys = getSecretsRes const deleteSecretsKeys = getSecretsRes
.filter((secret: FlyioSecret) => !(secret.name in secrets)) .filter((secret: FlyioSecret) => !(secret.name in secrets))
@@ -771,28 +808,37 @@ const syncSecretsFlyio = async ({
}`; }`;
await axios({ await axios({
method: 'post', method: "post",
url: INTEGRATION_FLYIO_API_URL, url: INTEGRATION_FLYIO_API_URL,
headers: { headers: {
'Authorization': 'Bearer ' + accessToken, Authorization: "Bearer " + accessToken,
'Content-Type': 'application/json' "Content-Type": "application/json",
}, },
data: { data: {
query: DeleteSecrets, query: DeleteSecrets,
variables: { variables: {
input: { input: {
appId: integration.app, appId: integration.app,
keys: deleteSecretsKeys keys: deleteSecretsKeys,
} },
} },
} },
}); });
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
Sentry.captureException(err); Sentry.captureException(err);
throw new Error('Failed to sync secrets to Fly.io'); throw new Error("Failed to sync secrets to Fly.io");
} }
} };
// const syncSecretsCircleci = async ({
// integration,
// secrets,
// accessToken,
// }: {
// integration: IIntegration;
// secrets: any;
// accessToken: string;
// }) => {};
export { syncSecrets }; export { syncSecrets };
+2
View File
@@ -24,6 +24,7 @@ import {
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_RENDER_API_URL, INTEGRATION_RENDER_API_URL,
INTEGRATION_FLYIO_API_URL, INTEGRATION_FLYIO_API_URL,
INTEGRATION_CIRCLECI_API_URL,
INTEGRATION_OPTIONS, INTEGRATION_OPTIONS,
} from "./integration"; } from "./integration";
import { OWNER, ADMIN, MEMBER, INVITED, ACCEPTED } from "./organization"; import { OWNER, ADMIN, MEMBER, INVITED, ACCEPTED } from "./organization";
@@ -69,6 +70,7 @@ export {
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_RENDER_API_URL, INTEGRATION_RENDER_API_URL,
INTEGRATION_FLYIO_API_URL, INTEGRATION_FLYIO_API_URL,
INTEGRATION_CIRCLECI_API_URL,
EVENT_PUSH_SECRETS, EVENT_PUSH_SECRETS,
EVENT_PULL_SECRETS, EVENT_PULL_SECRETS,
ACTION_ADD_SECRETS, ACTION_ADD_SECRETS,
+2 -1
View File
@@ -40,7 +40,7 @@ const INTEGRATION_VERCEL_API_URL = "https://api.vercel.com";
const INTEGRATION_NETLIFY_API_URL = "https://api.netlify.com"; const INTEGRATION_NETLIFY_API_URL = "https://api.netlify.com";
const INTEGRATION_RENDER_API_URL = "https://api.render.com"; const INTEGRATION_RENDER_API_URL = "https://api.render.com";
const INTEGRATION_FLYIO_API_URL = "https://api.fly.io/graphql"; const INTEGRATION_FLYIO_API_URL = "https://api.fly.io/graphql";
const INTEGRATION_CIRCLECI_API_URL = "https://circleci.com/api/v2"; const INTEGRATION_CIRCLECI_API_URL = "https://circleci.com/api";
const INTEGRATION_OPTIONS = [ const INTEGRATION_OPTIONS = [
{ {
@@ -164,5 +164,6 @@ export {
INTEGRATION_NETLIFY_API_URL, INTEGRATION_NETLIFY_API_URL,
INTEGRATION_RENDER_API_URL, INTEGRATION_RENDER_API_URL,
INTEGRATION_FLYIO_API_URL, INTEGRATION_FLYIO_API_URL,
INTEGRATION_CIRCLECI_API_URL,
INTEGRATION_OPTIONS, INTEGRATION_OPTIONS,
}; };