@catladder/cli
Version:
Panter cli tool for cloud CI/CD and DevOps
193 lines (172 loc) • 4.83 kB
text/typescript
import type {
Config,
EnvironmentEnvVars,
VariableValue,
} from "@catladder/pipeline";
import {
readConfig,
getAllEnvs,
getEnvironment as _getEnvironment,
createComponentContext,
getSecretVarName,
} from "@catladder/pipeline";
import type { IO } from "../core/types";
import { getAllVariables, getVariableValueByRawName } from "../utils/gitlab";
import { getGitRoot } from "../utils/projects";
export { parseChoice } from "./parseChoice";
let currentConfig: Config | null = null;
const loadConfig = async () => {
const gitRoot = await getGitRoot();
if (!gitRoot) {
return;
}
const result = await readConfig(gitRoot);
if (!result) {
return;
}
currentConfig = result.config;
};
export const getProjectConfig = async () => {
if (!currentConfig) {
await loadConfig();
}
return currentConfig as Config;
};
export const getProjectComponents = async () => {
const config = await getProjectConfig();
if (!config) return [];
return Object.keys(config.components);
};
export const getPipelineContextByChoice = async (
env: string,
componentName: string,
) => {
const config = await getProjectConfig();
return await createComponentContext({
config,
componentName,
env,
});
};
export const getAllComponentsWithAllEnvsFlat = async (): Promise<
Array<{ env: string; componentName: string }>
> => {
const config = await getProjectConfig();
if (!config) {
return [];
}
return getAllComponentsWithAllEnvsFlatFromConfig(config);
};
export const getAllComponentsWithAllEnvsHierarchical = async (): Promise<{
[componentName: string]: string[];
}> => {
const config = await getProjectConfig();
if (!config) {
return {};
}
return Object.fromEntries(
Object.keys(config.components).map((componentName) => [
componentName,
getAllEnvs(config, componentName),
]),
);
};
export const getAllPipelineContexts = async (
onlyComponent?: string | string[],
{ includeLocal = false }: { includeLocal?: boolean } = {},
) => {
const onlyComponentsArray = onlyComponent
? Array.isArray(onlyComponent)
? onlyComponent
: [onlyComponent]
: null;
return Promise.all(
(await getAllComponentsWithAllEnvsFlat())
.filter((c) => includeLocal || c.env !== "local")
.filter(
(c) =>
!onlyComponentsArray || onlyComponentsArray.includes(c.componentName),
)
.map(({ env, componentName }) =>
getPipelineContextByChoice(env, componentName),
),
);
};
export const getEnvironment = async (env: string, componentName: string) => {
const config = await getProjectConfig();
return _getEnvironment({ config, componentName, env });
};
export const getGitlabVar = async (
io: IO,
env: string,
componentName: string,
variableName: string,
) => {
const rawVariableName = getSecretVarName(env, componentName, variableName);
return await getVariableValueByRawName(io, rawVariableName);
};
const resolveSecrets = async (
io: IO | null,
varSets: EnvironmentEnvVars[],
): Promise<Record<string, string>> => {
const allVariablesInGitlab = await getAllVariables(io);
return Object.fromEntries(
varSets.flatMap(({ envVars, secretEnvVarKeys }) =>
Object.entries(envVars)
.filter(
([key, value]) =>
value !== undefined &&
value !== null &&
!secretEnvVarKeys.find((k) => k.key === key)?.hidden,
)
.map(([key, value]) => [
key,
allVariablesInGitlab.reduce(
(acc, curr) =>
acc.replace(new RegExp("\\$" + curr.key, "g"), curr.value),
`${value}`,
),
]),
),
);
};
export const getEnvVarsResolved = async (
io: IO | null,
env: string,
componentName: string | null,
) => {
if (!componentName) {
return {};
}
const envionment = await getEnvironment(env, componentName);
// in the pipeline the secrets alreadyy exists and bash will expand them
// but here we need to manually load them
return resolveSecrets(io, [
{
envVars: envionment.envVars,
secretEnvVarKeys: envionment.secretEnvVarKeys,
},
]);
};
/**
*
* is used to get job only vars that should also be editable locally with catladder.
*/
export const getJobOnlyEnvVarsResolved = async (
io: IO,
env: string,
componentName: string,
) => {
const envionment = await getEnvironment(env, componentName);
return resolveSecrets(io, [
envionment.jobOnlyVars.build,
envionment.jobOnlyVars.deploy,
]);
};
function getAllComponentsWithAllEnvsFlatFromConfig(
config: Config,
): { env: string; componentName: string }[] {
return Object.keys(config.components).flatMap((componentName) =>
getAllEnvs(config, componentName).map((env) => ({ env, componentName })),
);
}