mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 14:26:25 +00:00
misc: unified to a single integration
This commit is contained in:
@@ -2245,185 +2245,184 @@ const syncSecretsCircleCI = async ({
|
||||
secrets: Record<string, { value: string; comment?: string }>;
|
||||
accessToken: string;
|
||||
}) => {
|
||||
const getProjectSlug = async () => {
|
||||
const requestConfig = {
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
};
|
||||
enum CircleCiScope {
|
||||
Project = "project",
|
||||
Context = "context"
|
||||
}
|
||||
|
||||
try {
|
||||
const projectDetails = (
|
||||
await request.get<{ slug: string }>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${integration.appId}`,
|
||||
requestConfig
|
||||
)
|
||||
).data;
|
||||
|
||||
return projectDetails.slug;
|
||||
} catch (err) {
|
||||
if (err instanceof AxiosError) {
|
||||
if (err.response?.data?.message !== "Not Found") {
|
||||
throw new Error("Failed to get project slug from CircleCI during first attempt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility with old CircleCI integrations where we don't keep track of the organization name, so we can't filter by organization
|
||||
try {
|
||||
const circleCiOrganization = (
|
||||
await request.get<{ slug: string; name: string }[]>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/me/collaborations`,
|
||||
requestConfig
|
||||
)
|
||||
).data;
|
||||
|
||||
// Case 1: This is a new integration where the organization name is stored under `integration.owner`
|
||||
if (integration.owner) {
|
||||
const org = circleCiOrganization.find((o) => o.name === integration.owner);
|
||||
if (org) {
|
||||
return `${org.slug}/${integration.app}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: This is an old integration where the organization name is not stored, so we have to assume the first organization is the correct one
|
||||
return `${circleCiOrganization[0].slug}/${integration.app}`;
|
||||
} catch (err) {
|
||||
throw new Error("Failed to get project slug from CircleCI during second attempt.");
|
||||
}
|
||||
};
|
||||
|
||||
const projectSlug = await getProjectSlug();
|
||||
|
||||
// sync secrets to CircleCI
|
||||
await Promise.all(
|
||||
Object.keys(secrets).map(async (key) =>
|
||||
request.post(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${projectSlug}/envvar`,
|
||||
{
|
||||
name: key,
|
||||
value: secrets[key].value
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// get secrets from CircleCI
|
||||
const getSecretsRes = (
|
||||
await request.get<{ items: { name: string }[] }>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${projectSlug}/envvar`,
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
).data?.items;
|
||||
|
||||
// delete secrets from CircleCI
|
||||
await Promise.all(
|
||||
getSecretsRes.map(async (sec) => {
|
||||
if (!(sec.name in secrets)) {
|
||||
return request.delete(`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${projectSlug}/envvar/${sec.name}`, {
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sync/push [secrets] to CircleCI Context
|
||||
*/
|
||||
const syncSecretsCircleCIContext = async ({
|
||||
integration,
|
||||
secrets,
|
||||
accessToken
|
||||
}: {
|
||||
integration: TIntegrations;
|
||||
secrets: Record<string, { value: string; comment?: string }>;
|
||||
accessToken: string;
|
||||
}) => {
|
||||
// sync secrets to CircleCI
|
||||
await Promise.all(
|
||||
Object.keys(secrets).map(async (key) =>
|
||||
request.put(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/context/${integration.appId}/environment-variable/${key}`,
|
||||
{
|
||||
value: secrets[key].value
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// get secrets from CircleCI
|
||||
const getSecretsRes = async () => {
|
||||
type EnvVars = {
|
||||
variable: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
context_id: string;
|
||||
};
|
||||
|
||||
type ResponseSchema = {
|
||||
items: EnvVars[];
|
||||
next_page_token: string | null;
|
||||
};
|
||||
|
||||
let nextPageToken: string | null | undefined;
|
||||
const envVars: EnvVars[] = [];
|
||||
|
||||
while (nextPageToken !== null) {
|
||||
const res = await request.get<ResponseSchema>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/context/${integration.appId}/environment-variable`,
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
envVars.push(...res.data.items);
|
||||
nextPageToken = res.data.next_page_token;
|
||||
}
|
||||
|
||||
return envVars;
|
||||
};
|
||||
|
||||
// delete secrets from CircleCI
|
||||
await Promise.all(
|
||||
(await getSecretsRes()).map(async (sec) => {
|
||||
if (!(sec.variable in secrets)) {
|
||||
return request.delete(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/context/${integration.appId}/environment-variable/${sec.variable}`,
|
||||
if (integration.scope === CircleCiScope.Context) {
|
||||
// sync secrets to CircleCI
|
||||
await Promise.all(
|
||||
Object.keys(secrets).map(async (key) =>
|
||||
request.put(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/context/${integration.appId}/environment-variable/${key}`,
|
||||
{
|
||||
value: secrets[key].value
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// get secrets from CircleCI
|
||||
const getSecretsRes = async () => {
|
||||
type EnvVars = {
|
||||
variable: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
context_id: string;
|
||||
};
|
||||
|
||||
type ResponseSchema = {
|
||||
items: EnvVars[];
|
||||
next_page_token: string | null;
|
||||
};
|
||||
|
||||
let nextPageToken: string | null | undefined;
|
||||
const envVars: EnvVars[] = [];
|
||||
|
||||
while (nextPageToken !== null) {
|
||||
const res = await request.get<ResponseSchema>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/context/${integration.appId}/environment-variable`,
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Accept-Encoding": "application/json"
|
||||
},
|
||||
params: nextPageToken
|
||||
? new URLSearchParams({
|
||||
"page-token": nextPageToken
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
);
|
||||
|
||||
envVars.push(...res.data.items);
|
||||
nextPageToken = res.data.next_page_token;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return envVars;
|
||||
};
|
||||
|
||||
// delete secrets from CircleCI
|
||||
await Promise.all(
|
||||
(await getSecretsRes()).map(async (sec) => {
|
||||
if (!(sec.variable in secrets)) {
|
||||
return request.delete(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/context/${integration.appId}/environment-variable/${sec.variable}`,
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
const getProjectSlug = async () => {
|
||||
const requestConfig = {
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const projectDetails = (
|
||||
await request.get<{ slug: string }>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${integration.appId}`,
|
||||
requestConfig
|
||||
)
|
||||
).data;
|
||||
|
||||
return projectDetails.slug;
|
||||
} catch (err) {
|
||||
if (err instanceof AxiosError) {
|
||||
if (err.response?.data?.message !== "Not Found") {
|
||||
throw new Error("Failed to get project slug from CircleCI during first attempt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For backwards compatibility with old CircleCI integrations where we don't keep track of the organization name, so we can't filter by organization
|
||||
try {
|
||||
const circleCiOrganization = (
|
||||
await request.get<{ slug: string; name: string }[]>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/me/collaborations`,
|
||||
requestConfig
|
||||
)
|
||||
).data;
|
||||
|
||||
// Case 1: This is a new integration where the organization name is stored under `integration.owner`
|
||||
if (integration.owner) {
|
||||
const org = circleCiOrganization.find((o) => o.name === integration.owner);
|
||||
if (org) {
|
||||
return `${org.slug}/${integration.app}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Case 2: This is an old integration where the organization name is not stored, so we have to assume the first organization is the correct one
|
||||
return `${circleCiOrganization[0].slug}/${integration.app}`;
|
||||
} catch (err) {
|
||||
throw new Error("Failed to get project slug from CircleCI during second attempt.");
|
||||
}
|
||||
};
|
||||
|
||||
const projectSlug = await getProjectSlug();
|
||||
|
||||
// sync secrets to CircleCI
|
||||
await Promise.all(
|
||||
Object.keys(secrets).map(async (key) =>
|
||||
request.post(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${projectSlug}/envvar`,
|
||||
{
|
||||
name: key,
|
||||
value: secrets[key].value
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// get secrets from CircleCI
|
||||
const getSecretsRes = (
|
||||
await request.get<{ items: { name: string }[] }>(
|
||||
`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${projectSlug}/envvar`,
|
||||
{
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Accept-Encoding": "application/json"
|
||||
}
|
||||
}
|
||||
)
|
||||
).data?.items;
|
||||
|
||||
// delete secrets from CircleCI
|
||||
await Promise.all(
|
||||
getSecretsRes.map(async (sec) => {
|
||||
if (!(sec.name in secrets)) {
|
||||
return request.delete(`${IntegrationUrls.CIRCLECI_API_URL}/v2/project/${projectSlug}/envvar/${sec.name}`, {
|
||||
headers: {
|
||||
"Circle-Token": accessToken,
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -4516,13 +4515,6 @@ export const syncIntegrationSecrets = async ({
|
||||
accessToken
|
||||
});
|
||||
break;
|
||||
case Integrations.CIRCLECI_CONTEXT:
|
||||
await syncSecretsCircleCIContext({
|
||||
integration,
|
||||
secrets,
|
||||
accessToken
|
||||
});
|
||||
break;
|
||||
case Integrations.DATABRICKS:
|
||||
await syncSecretsDatabricks({
|
||||
integration,
|
||||
|
||||
Reference in New Issue
Block a user