mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 12:27:31 +00:00
Merge pull request #215 from Infisical/patch-integrations
Patch integrations
This commit is contained in:
@@ -67,8 +67,17 @@ export const createSecrets = async (req: Request, res: Response) => {
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setTimeout(async () => {
|
||||||
|
// trigger event - push secrets
|
||||||
|
await EventService.handleEvent({
|
||||||
|
event: eventPushSecrets({
|
||||||
|
workspaceId
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
// (EE) add secret versions for new secrets
|
// (EE) add secret versions for new secrets
|
||||||
EESecretService.addSecretVersions({
|
await EESecretService.addSecretVersions({
|
||||||
secretVersions: newSecrets.map(({
|
secretVersions: newSecrets.map(({
|
||||||
_id,
|
_id,
|
||||||
version,
|
version,
|
||||||
@@ -104,13 +113,6 @@ export const createSecrets = async (req: Request, res: Response) => {
|
|||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
// trigger event - push secrets
|
|
||||||
await EventService.handleEvent({
|
|
||||||
event: eventPushSecrets({
|
|
||||||
workspaceId
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const addAction = await EELogService.createActionSecret({
|
const addAction = await EELogService.createActionSecret({
|
||||||
name: ACTION_ADD_SECRETS,
|
name: ACTION_ADD_SECRETS,
|
||||||
userId: req.user._id.toString(),
|
userId: req.user._id.toString(),
|
||||||
@@ -342,11 +344,13 @@ export const updateSecrets = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
Object.keys(workspaceSecretObj).forEach(async (key) => {
|
Object.keys(workspaceSecretObj).forEach(async (key) => {
|
||||||
// trigger event - push secrets
|
// trigger event - push secrets
|
||||||
await EventService.handleEvent({
|
setTimeout(async () => {
|
||||||
event: eventPushSecrets({
|
await EventService.handleEvent({
|
||||||
workspaceId: key
|
event: eventPushSecrets({
|
||||||
})
|
workspaceId: key
|
||||||
});
|
})
|
||||||
|
});
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
const updateAction = await EELogService.createActionSecret({
|
const updateAction = await EELogService.createActionSecret({
|
||||||
name: ACTION_UPDATE_SECRETS,
|
name: ACTION_UPDATE_SECRETS,
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+291
-292
@@ -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);
|
||||||
@@ -307,188 +306,188 @@ const syncSecretsNetlify = async ({
|
|||||||
}) => {
|
}) => {
|
||||||
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',
|
||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NetlifySecret {
|
interface NetlifySecret {
|
||||||
key: string;
|
key: string;
|
||||||
values: NetlifyValue[];
|
values: NetlifyValue[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NetlifySecretsRes {
|
interface NetlifySecretsRes {
|
||||||
[index: string]: NetlifySecret;
|
[index: string]: NetlifySecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.siteId
|
site_id: integration.siteId
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
.data
|
||||||
.reduce((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
|
||||||
const deleteSecretValues: NetlifySecret[] = []; // deleteEnvVarValue
|
const deleteSecretValues: NetlifySecret[] = []; // deleteEnvVarValue
|
||||||
const updateSecrets: NetlifySecret[] = []; // setEnvVarValue
|
const updateSecrets: NetlifySecret[] = []; // setEnvVarValue
|
||||||
|
|
||||||
|
// identify secrets to create and update
|
||||||
|
Object.keys(secrets).map((key) => {
|
||||||
|
if (!(key in res)) {
|
||||||
|
// case: Infisical secret does not exist in Netlify -> create secret
|
||||||
|
newSecrets.push({
|
||||||
|
key,
|
||||||
|
values: [{
|
||||||
|
value: secrets[key],
|
||||||
|
context: integration.context
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// case: Infisical secret exists in Netlify
|
||||||
|
const contexts = res[key].values
|
||||||
|
.reduce((obj: any, value: NetlifyValue) => ({
|
||||||
|
...obj,
|
||||||
|
[value.context]: value
|
||||||
|
}), {});
|
||||||
|
|
||||||
|
if (integration.context in contexts) {
|
||||||
|
// case: Netlify secret value exists in integration context
|
||||||
|
if (secrets[key] !== contexts[integration.context].value) {
|
||||||
|
// case: Infisical and Netlify secret values are different
|
||||||
|
// -> update Netlify secret context and value
|
||||||
|
updateSecrets.push({
|
||||||
|
key,
|
||||||
|
values: [{
|
||||||
|
context: integration.context,
|
||||||
|
value: secrets[key]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// case: Netlify secret value does not exist in integration context
|
||||||
|
// -> add the new Netlify secret context and value
|
||||||
|
updateSecrets.push({
|
||||||
|
key,
|
||||||
|
values: [{
|
||||||
|
context: integration.context,
|
||||||
|
value: secrets[key]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// identify secrets to delete
|
||||||
|
// TODO: revise (patch case where 1 context was deleted but others still there
|
||||||
|
Object.keys(res).map((key) => {
|
||||||
|
// loop through each key's context
|
||||||
|
if (!(key in secrets)) {
|
||||||
|
// case: Netlify secret does not exist in Infisical
|
||||||
|
|
||||||
|
const numberOfValues = res[key].values.length;
|
||||||
|
|
||||||
|
res[key].values.forEach((value: NetlifyValue) => {
|
||||||
|
if (value.context === integration.context) {
|
||||||
|
if (numberOfValues <= 1) {
|
||||||
|
// case: Netlify secret value has less than 1 context -> delete secret
|
||||||
|
deleteSecrets.push(key);
|
||||||
|
} else {
|
||||||
|
// case: Netlify secret value has more than 1 context -> delete secret value context
|
||||||
|
deleteSecretValues.push({
|
||||||
|
key,
|
||||||
|
values: [{
|
||||||
|
id: value.id,
|
||||||
|
context: integration.context,
|
||||||
|
value: value.value
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// identify secrets to create and update
|
const syncParams = new URLSearchParams({
|
||||||
Object.keys(secrets).map((key) => {
|
site_id: integration.siteId
|
||||||
if (!(key in res)) {
|
});
|
||||||
// case: Infisical secret does not exist in Netlify -> create secret
|
|
||||||
newSecrets.push({
|
|
||||||
key,
|
|
||||||
values: [{
|
|
||||||
value: secrets[key],
|
|
||||||
context: integration.context
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// case: Infisical secret exists in Netlify
|
|
||||||
const contexts = res[key].values
|
|
||||||
.reduce((obj: any, value: NetlifyValue) => ({
|
|
||||||
...obj,
|
|
||||||
[value.context]: value
|
|
||||||
}), {});
|
|
||||||
|
|
||||||
if (integration.context in contexts) {
|
|
||||||
// case: Netlify secret value exists in integration context
|
|
||||||
if (secrets[key] !== contexts[integration.context].value) {
|
|
||||||
// case: Infisical and Netlify secret values are different
|
|
||||||
// -> update Netlify secret context and value
|
|
||||||
updateSecrets.push({
|
|
||||||
key,
|
|
||||||
values: [{
|
|
||||||
context: integration.context,
|
|
||||||
value: secrets[key]
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// case: Netlify secret value does not exist in integration context
|
|
||||||
// -> add the new Netlify secret context and value
|
|
||||||
updateSecrets.push({
|
|
||||||
key,
|
|
||||||
values: [{
|
|
||||||
context: integration.context,
|
|
||||||
value: secrets[key]
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// identify secrets to delete
|
|
||||||
// TODO: revise (patch case where 1 context was deleted but others still there
|
|
||||||
Object.keys(res).map((key) => {
|
|
||||||
// loop through each key's context
|
|
||||||
if (!(key in secrets)) {
|
|
||||||
// case: Netlify secret does not exist in Infisical
|
|
||||||
|
|
||||||
const numberOfValues = res[key].values.length;
|
|
||||||
|
|
||||||
res[key].values.forEach((value: NetlifyValue) => {
|
|
||||||
if (value.context === integration.context) {
|
|
||||||
if (numberOfValues <= 1) {
|
|
||||||
// case: Netlify secret value has less than 1 context -> delete secret
|
|
||||||
deleteSecrets.push(key);
|
|
||||||
} else {
|
|
||||||
// case: Netlify secret value has more than 1 context -> delete secret value context
|
|
||||||
deleteSecretValues.push({
|
|
||||||
key,
|
|
||||||
values: [{
|
|
||||||
id: value.id,
|
|
||||||
context: integration.context,
|
|
||||||
value: value.value
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const syncParams = new URLSearchParams({
|
if (newSecrets.length > 0) {
|
||||||
site_id: integration.siteId
|
await axios.post(
|
||||||
});
|
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`,
|
||||||
|
newSecrets,
|
||||||
|
{
|
||||||
|
params: syncParams,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${accessToken}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (newSecrets.length > 0) {
|
if (updateSecrets.length > 0) {
|
||||||
await axios.post(
|
updateSecrets.forEach(async (secret: NetlifySecret) => {
|
||||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`,
|
await axios.patch(
|
||||||
newSecrets,
|
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
|
||||||
{
|
{
|
||||||
params: syncParams,
|
context: secret.values[0].context,
|
||||||
headers: {
|
value: secret.values[0].value
|
||||||
Authorization: `Bearer ${accessToken}`
|
},
|
||||||
}
|
{
|
||||||
}
|
params: syncParams,
|
||||||
);
|
headers: {
|
||||||
}
|
Authorization: `Bearer ${accessToken}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (updateSecrets.length > 0) {
|
if (deleteSecrets.length > 0) {
|
||||||
updateSecrets.forEach(async (secret: NetlifySecret) => {
|
deleteSecrets.forEach(async (key: string) => {
|
||||||
await axios.patch(
|
await axios.delete(
|
||||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`,
|
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${key}`,
|
||||||
{
|
{
|
||||||
context: secret.values[0].context,
|
params: syncParams,
|
||||||
value: secret.values[0].value
|
headers: {
|
||||||
},
|
Authorization: `Bearer ${accessToken}`
|
||||||
{
|
}
|
||||||
params: syncParams,
|
}
|
||||||
headers: {
|
);
|
||||||
Authorization: `Bearer ${accessToken}`
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deleteSecrets.length > 0) {
|
if (deleteSecretValues.length > 0) {
|
||||||
deleteSecrets.forEach(async (key: string) => {
|
deleteSecretValues.forEach(async (secret: NetlifySecret) => {
|
||||||
await axios.delete(
|
await axios.delete(
|
||||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${key}`,
|
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}/value/${secret.values[0].id}`,
|
||||||
{
|
{
|
||||||
params: syncParams,
|
params: syncParams,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${accessToken}`
|
Authorization: `Bearer ${accessToken}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deleteSecretValues.length > 0) {
|
|
||||||
deleteSecretValues.forEach(async (secret: NetlifySecret) => {
|
|
||||||
await axios.delete(
|
|
||||||
`${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}/value/${secret.values[0].id}`,
|
|
||||||
{
|
|
||||||
params: syncParams,
|
|
||||||
headers: {
|
|
||||||
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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user