@catladder/pipeline 1.170.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bash/BashExpression.d.ts +1 -6
- package/dist/bash/BashExpression.js +2 -15
- package/dist/bash/bashEscape.d.ts +34 -0
- package/dist/bash/bashEscape.js +114 -0
- package/dist/bash/bashYaml.js +25 -2
- package/dist/bash/getInjectVarsScript.js +4 -2
- package/dist/bash/index.d.ts +2 -0
- package/dist/bash/index.js +26 -0
- package/dist/build/base/createAppBuildJob.js +3 -3
- package/dist/build/base/writeDotEnv.js +6 -4
- package/dist/build/custom/testJob.js +12 -12
- package/dist/build/docker.d.ts +3 -3
- package/dist/build/node/buildJob.js +1 -1
- package/dist/build/node/cache.d.ts +2 -4
- package/dist/build/node/cache.js +3 -24
- package/dist/build/node/testJob.js +11 -11
- package/dist/build/rails/build.js +1 -1
- package/dist/build/rails/test.js +8 -8
- package/dist/build/types.d.ts +0 -10
- package/dist/constants.js +1 -1
- package/dist/context/createComponentContext.js +0 -1
- package/dist/context/getEnvConfig.js +2 -1
- package/dist/context/getEnvironment.js +1 -2
- package/dist/context/getEnvironmentVariables.d.ts +5 -6
- package/dist/context/getEnvironmentVariables.js +50 -38
- package/dist/deploy/base/deploy.js +3 -3
- package/dist/deploy/cloudRun/createJobs/getCloudRunDeployScripts.js +2 -2
- package/dist/deploy/cloudRun/index.js +2 -2
- package/dist/deploy/cloudRun/utils/getServiceName.d.ts +1 -1
- package/dist/deploy/kubernetes/cloudSql/index.d.ts +2 -2
- package/dist/deploy/kubernetes/cloudSql/index.js +3 -14
- package/dist/deploy/kubernetes/deployJob.js +1 -3
- package/dist/deploy/kubernetes/index.js +2 -2
- package/dist/deploy/kubernetes/kubeEnv.d.ts +3 -3
- package/dist/deploy/kubernetes/kubeValues.d.ts +3 -4
- package/dist/deploy/kubernetes/kubeValues.js +2 -3
- package/dist/deploy/types/base.d.ts +0 -6
- package/dist/deploy/types/kubernetes.d.ts +1 -34
- package/dist/globalScriptFunctions/index.d.ts +14 -0
- package/dist/globalScriptFunctions/index.js +37 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/pipeline/gitlab/createGitlabJobs.js +3 -5
- package/dist/pipeline/gitlab/createGitlabPipeline.d.ts +1 -0
- package/dist/pipeline/gitlab/createGitlabPipeline.js +38 -2
- package/dist/pipeline/packageManager.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/config.d.ts +6 -9
- package/dist/types/context.d.ts +2 -9
- package/dist/types/gitlab-types.d.ts +1 -0
- package/dist/types/jobs.d.ts +0 -8
- package/dist/utils/gitlab.js +4 -1
- package/dist/utils/writeFiles.js +1 -7
- package/dist/variables/VariableValue.d.ts +3 -0
- package/dist/variables/VariableValue.js +5 -0
- package/dist/variables/VariableValueContainingReferences.d.ts +24 -0
- package/dist/variables/VariableValueContainingReferences.js +97 -0
- package/dist/variables/__tests__/resolveAllReferences.test.js +219 -0
- package/dist/variables/__tests__/resolveAllReferencesOnce.test.d.ts +1 -0
- package/dist/variables/__tests__/resolveAllReferencesOnce.test.js +171 -0
- package/dist/variables/__tests__/resolveReferencesOnce.test.d.ts +1 -0
- package/dist/variables/__tests__/resolveReferencesOnce.test.js +202 -0
- package/dist/variables/__tests__/variableValue.test.d.ts +1 -0
- package/dist/variables/__tests__/variableValue.test.js +36 -0
- package/dist/variables/resolveAllReferences.d.ts +3 -0
- package/dist/{bash/replaceAsync.js → variables/resolveAllReferences.js} +60 -40
- package/dist/variables/resolveAllReferencesOnce.d.ts +5 -0
- package/dist/variables/resolveAllReferencesOnce.js +191 -0
- package/dist/variables/resolveReferencesOnce.d.ts +8 -0
- package/dist/variables/resolveReferencesOnce.js +22 -0
- package/examples/__snapshots__/cloud-run-http2.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-memory-limit.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-meteor-with-worker.test.ts.snap +312 -222
- package/examples/__snapshots__/cloud-run-nextjs.test.ts.snap +1436 -0
- package/examples/__snapshots__/cloud-run-no-cpu-throttling.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-no-service.test.ts.snap +316 -238
- package/examples/__snapshots__/cloud-run-non-public.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-post-stop-job.test.ts.snap +313 -238
- package/examples/__snapshots__/cloud-run-service-custom-vpc-connector.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-custom-vpc.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-gen2.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-increase-timout.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-with-volumes.test.ts.snap +316 -238
- package/examples/__snapshots__/cloud-run-storybook.test.ts.snap +294 -220
- package/examples/__snapshots__/cloud-run-with-ngnix.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-with-sql-reuse-db.test.ts.snap +652 -486
- package/examples/__snapshots__/cloud-run-with-sql.test.ts.snap +282 -288
- package/examples/__snapshots__/cloud-run-with-worker.test.ts.snap +312 -238
- package/examples/__snapshots__/custom-build-job-with-tests.test.ts.snap +284 -194
- package/examples/__snapshots__/custom-build-job.test.ts.snap +278 -188
- package/examples/__snapshots__/custom-deploy.test.ts.snap +220 -154
- package/examples/__snapshots__/custom-envs.test.ts.snap +216 -126
- package/examples/__snapshots__/custom-sbom-java.test.ts.snap +278 -188
- package/examples/__snapshots__/git-submodule.test.ts.snap +312 -238
- package/examples/__snapshots__/kubernetes-application-customization.test.ts.snap +231 -253
- package/examples/__snapshots__/kubernetes-with-cloud-sql.test.ts.snap +240 -262
- package/examples/__snapshots__/kubernetes-with-jobs.test.ts.snap +504 -506
- package/examples/__snapshots__/kubernetes-with-mongodb.test.ts.snap +239 -261
- package/examples/__snapshots__/local-dot-env.test.ts.snap +236 -238
- package/examples/__snapshots__/meteor-kubernetes.test.ts.snap +236 -242
- package/examples/__snapshots__/multiline-var.test.ts.snap +1355 -973
- package/examples/__snapshots__/native-app.test.ts.snap +438 -392
- package/examples/__snapshots__/node-build-with-custom-image.test.ts.snap +312 -238
- package/examples/__snapshots__/node-build-with-docker-additions.test.ts.snap +312 -238
- package/examples/__snapshots__/rails-k8s-with-worker-dockerfile.test.ts.snap +186 -188
- package/examples/__snapshots__/rails-k8s-with-worker.test.ts.snap +162 -164
- package/examples/__snapshots__/referencing-other-vars.test.ts.snap +971 -765
- package/examples/__snapshots__/wait-for-other-deploy.test.ts.snap +330 -228
- package/examples/__snapshots__/{workspace-api-www-custom-cache.test.ts.snap → workspace-api-www-turbo-cache.test.ts.snap} +457 -499
- package/examples/__snapshots__/workspace-api-www.test.ts.snap +452 -482
- package/examples/{workspace-api-www-custom-cache.test.ts → cloud-run-nextjs.test.ts} +2 -2
- package/examples/cloud-run-nextjs.ts +28 -0
- package/examples/cloud-run-with-sql.ts +0 -1
- package/examples/kubernetes-application-customization.ts +1 -0
- package/examples/kubernetes-with-cloud-sql.ts +1 -0
- package/examples/kubernetes-with-jobs.ts +1 -0
- package/examples/kubernetes-with-mongodb.ts +1 -0
- package/examples/meteor-kubernetes.ts +1 -1
- package/examples/native-app.ts +10 -7
- package/examples/rails-k8s-with-worker.ts +7 -1
- package/examples/{kubernetes-with-cloud-sql-legacy.test.ts → workspace-api-www-turbo-cache.test.ts} +2 -2
- package/examples/{workspace-api-www-custom-cache.ts → workspace-api-www-turbo-cache.ts} +4 -3
- package/examples/workspace-api-www.ts +3 -2
- package/package.json +2 -6
- package/src/bash/BashExpression.ts +0 -13
- package/src/bash/bashEscape.ts +158 -0
- package/src/bash/bashYaml.ts +36 -2
- package/src/bash/getInjectVarsScript.ts +11 -2
- package/src/bash/index.ts +2 -0
- package/src/build/base/createAppBuildJob.ts +0 -1
- package/src/build/base/writeDotEnv.ts +6 -6
- package/src/build/custom/testJob.ts +0 -1
- package/src/build/node/buildJob.ts +2 -2
- package/src/build/node/cache.ts +0 -29
- package/src/build/node/testJob.ts +0 -1
- package/src/build/rails/build.ts +0 -1
- package/src/build/rails/test.ts +0 -1
- package/src/build/types.ts +0 -13
- package/src/context/createComponentContext.ts +0 -1
- package/src/context/getEnvConfig.ts +2 -2
- package/src/context/getEnvironment.ts +1 -1
- package/src/context/getEnvironmentContext.ts +1 -1
- package/src/context/getEnvironmentVariables.ts +44 -51
- package/src/deploy/base/deploy.ts +1 -1
- package/src/deploy/cloudRun/createJobs/getCloudRunDeployScripts.ts +4 -12
- package/src/deploy/cloudRun/index.ts +2 -2
- package/src/deploy/kubernetes/cloudSql/index.ts +3 -16
- package/src/deploy/kubernetes/deployJob.ts +0 -2
- package/src/deploy/kubernetes/index.ts +2 -2
- package/src/deploy/kubernetes/kubeEnv.ts +3 -3
- package/src/deploy/kubernetes/kubeValues.ts +5 -8
- package/src/deploy/types/base.ts +0 -6
- package/src/deploy/types/kubernetes.ts +1 -36
- package/src/globalScriptFunctions/index.ts +30 -0
- package/src/index.ts +2 -0
- package/src/pipeline/gitlab/createGitlabJobs.ts +1 -4
- package/src/pipeline/gitlab/createGitlabPipeline.ts +8 -1
- package/src/pipeline/packageManager.ts +7 -5
- package/src/runner/index.ts +0 -1
- package/src/types/config.ts +6 -9
- package/src/types/context.ts +3 -9
- package/src/types/gitlab-types.ts +1 -0
- package/src/types/jobs.ts +0 -8
- package/src/utils/gitlab.ts +19 -2
- package/src/utils/writeFiles.ts +1 -2
- package/src/variables/VariableValue.ts +6 -0
- package/src/variables/VariableValueContainingReferences.ts +89 -0
- package/src/variables/__tests__/resolveAllReferences.test.ts +110 -0
- package/src/variables/__tests__/resolveAllReferencesOnce.test.ts +64 -0
- package/src/variables/__tests__/resolveReferencesOnce.test.ts +117 -0
- package/src/variables/__tests__/variableValue.test.ts +73 -0
- package/src/variables/resolveAllReferences.ts +46 -0
- package/src/variables/resolveAllReferencesOnce.ts +44 -0
- package/src/variables/resolveReferencesOnce.ts +29 -0
- package/bin/catladder-gitlab-dev.js +0 -3
- package/bin/catladder-gitlab.js +0 -3
- package/dist/bash/replaceAsync.d.ts +0 -2
- package/dist/bundles/catladder-gitlab/index.js +0 -15
- package/dist/context/__tests__/resolveReferences.test.js +0 -368
- package/dist/context/resolveReferences.d.ts +0 -6
- package/dist/context/resolveReferences.js +0 -286
- package/dist/deploy/kubernetes/processSecretsAsFiles.d.ts +0 -85
- package/dist/deploy/kubernetes/processSecretsAsFiles.js +0 -33
- package/examples/__snapshots__/kubernetes-with-cloud-sql-legacy.test.ts.snap +0 -1795
- package/examples/kubernetes-with-cloud-sql-legacy.ts +0 -35
- package/scripts/bundle +0 -2
- package/src/bash/replaceAsync.ts +0 -49
- package/src/context/__tests__/resolveReferences.test.ts +0 -148
- package/src/context/resolveReferences.ts +0 -93
- package/src/deploy/kubernetes/processSecretsAsFiles.ts +0 -35
- /package/dist/{context/__tests__/resolveReferences.test.d.ts → variables/__tests__/resolveAllReferences.test.d.ts} +0 -0
package/src/types/jobs.ts
CHANGED
|
@@ -70,14 +70,6 @@ export type CatladderJob<S = BaseStage> = {
|
|
|
70
70
|
*/
|
|
71
71
|
needs?: Array<CatladderJobNeed>;
|
|
72
72
|
|
|
73
|
-
/**
|
|
74
|
-
* @deprecated set `componentName` to `needs` if you want to wait for a job from another component
|
|
75
|
-
*/
|
|
76
|
-
needsOtherComponent?: Array<{
|
|
77
|
-
componentName: string;
|
|
78
|
-
job: string;
|
|
79
|
-
artifacts: boolean;
|
|
80
|
-
}>;
|
|
81
73
|
/**
|
|
82
74
|
* cache config, we use here the same shape as gitlab itself
|
|
83
75
|
*/
|
package/src/utils/gitlab.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { registerGlobalScriptFunction } from "../globalScriptFunctions";
|
|
2
|
+
|
|
1
3
|
export const allowFailureInScripts = (script: string[]): string[] => [
|
|
2
4
|
"set +e", // disable fail job on error
|
|
3
5
|
...script,
|
|
@@ -22,12 +24,27 @@ export const repeatOnFailure = (
|
|
|
22
24
|
`;
|
|
23
25
|
};
|
|
24
26
|
|
|
27
|
+
const start = registerGlobalScriptFunction(
|
|
28
|
+
"collapseable_section_start",
|
|
29
|
+
`local section_title="\${1}"
|
|
30
|
+
local section_description="\${2:-$section_title}"
|
|
31
|
+
echo -e "section_start:\`date +%s\`:\${section_title}[collapsed=true]\\r\\e[0K$\{section_description}"
|
|
32
|
+
`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const end = registerGlobalScriptFunction(
|
|
36
|
+
"collapseable_section_end",
|
|
37
|
+
`local section_title="\${1}"
|
|
38
|
+
echo -e "section_end:\`date +%s\`:\${section_title}\\r\\e[0K"
|
|
39
|
+
`,
|
|
40
|
+
);
|
|
41
|
+
|
|
25
42
|
export const collapseableSection =
|
|
26
43
|
(name: string, header: string) =>
|
|
27
44
|
(commands: string[]): string[] => {
|
|
28
45
|
return [
|
|
29
|
-
`
|
|
46
|
+
start.invoke(`"${name}"`, `"${header}"`),
|
|
30
47
|
...commands,
|
|
31
|
-
`
|
|
48
|
+
end.invoke(`"${name}"`),
|
|
32
49
|
];
|
|
33
50
|
};
|
package/src/utils/writeFiles.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { writeFile } from "fs/promises";
|
|
2
2
|
import { stringify } from "yaml";
|
|
3
|
-
import packageInfos from "../packageInfos";
|
|
4
3
|
|
|
5
4
|
export const getAutoGeneratedHeader = (commentChar: string) => {
|
|
6
5
|
return [
|
|
7
6
|
"-------------------------------------------------",
|
|
8
|
-
`🐱 🔨 This file is generated by catladder
|
|
7
|
+
`🐱 🔨 This file is generated by catladder`,
|
|
9
8
|
`🚨 Do not edit this file manually 🚨`,
|
|
10
9
|
"-------------------------------------------------",
|
|
11
10
|
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { BashExpression } from "../bash/BashExpression";
|
|
2
|
+
import type { EscapeOptions } from "../bash/bashEscape";
|
|
3
|
+
import { escapeBashExpression, escapeString } from "../bash/bashEscape";
|
|
4
|
+
|
|
5
|
+
export class UnresolvableReference {
|
|
6
|
+
constructor(public reference: VariableReference) {}
|
|
7
|
+
public toString() {
|
|
8
|
+
return `Unresolvable reference: ${this.reference.toString()}`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class VariableReference {
|
|
12
|
+
public componentName: string;
|
|
13
|
+
public variableName: string;
|
|
14
|
+
|
|
15
|
+
constructor(componentName: string, variableName: string) {
|
|
16
|
+
this.componentName = componentName;
|
|
17
|
+
this.variableName = variableName;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public toString() {
|
|
21
|
+
return `\${${this.componentName}:${this.variableName}}`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type VariableValuePart =
|
|
26
|
+
| string
|
|
27
|
+
| BashExpression
|
|
28
|
+
| VariableReference
|
|
29
|
+
| UnresolvableReference;
|
|
30
|
+
|
|
31
|
+
type MaybeArray<T> = T | T[];
|
|
32
|
+
export class VariableValueContainingReferences {
|
|
33
|
+
public parts: VariableValuePart[];
|
|
34
|
+
constructor(
|
|
35
|
+
parts: MaybeArray<VariableValuePart | VariableValueContainingReferences>,
|
|
36
|
+
) {
|
|
37
|
+
this.parts = (Array.isArray(parts) ? parts : [parts]).flatMap((part) =>
|
|
38
|
+
part instanceof VariableValueContainingReferences
|
|
39
|
+
? part.parts
|
|
40
|
+
: part === ""
|
|
41
|
+
? []
|
|
42
|
+
: [part],
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public toString(
|
|
47
|
+
options: EscapeOptions = {
|
|
48
|
+
quotes: false,
|
|
49
|
+
},
|
|
50
|
+
) {
|
|
51
|
+
return this.parts
|
|
52
|
+
.map((part) => {
|
|
53
|
+
if (typeof part === "string") {
|
|
54
|
+
return escapeString(part, options);
|
|
55
|
+
} else if (part instanceof BashExpression) {
|
|
56
|
+
return escapeBashExpression(part, options);
|
|
57
|
+
} else {
|
|
58
|
+
return part.toString();
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.join("");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// regex to resolve references in catladder variables
|
|
66
|
+
// those expressions have the pattern ${componentName:variableName}
|
|
67
|
+
const REGEX = /\$\{(([^:}]+):)?([^}]+)}/gm;
|
|
68
|
+
export const createVariableValueContainingReferencesFromString = (
|
|
69
|
+
value: string,
|
|
70
|
+
options: { componentName: string },
|
|
71
|
+
) => {
|
|
72
|
+
const parts: Array<VariableValuePart> = [];
|
|
73
|
+
let match: any;
|
|
74
|
+
let lastIndex = 0;
|
|
75
|
+
while ((match = REGEX.exec(value)) !== null) {
|
|
76
|
+
const [fullMatch, _, otherComponentName, variableName] = match;
|
|
77
|
+
|
|
78
|
+
parts.push(value.slice(lastIndex, match.index));
|
|
79
|
+
parts.push(
|
|
80
|
+
new VariableReference(
|
|
81
|
+
otherComponentName || options.componentName,
|
|
82
|
+
variableName,
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
lastIndex = REGEX.lastIndex;
|
|
86
|
+
}
|
|
87
|
+
parts.push(value.slice(lastIndex));
|
|
88
|
+
return new VariableValueContainingReferences(parts);
|
|
89
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VariableValueContainingReferences,
|
|
3
|
+
createVariableValueContainingReferencesFromString,
|
|
4
|
+
} from "../VariableValueContainingReferences";
|
|
5
|
+
import { resolveAllReferences } from "../resolveAllReferences";
|
|
6
|
+
|
|
7
|
+
describe("replaceAllReferences", () => {
|
|
8
|
+
it("should replace all references recursivly", async () => {
|
|
9
|
+
const values = {
|
|
10
|
+
myVar: createVariableValueContainingReferencesFromString(
|
|
11
|
+
"the 2nd component has ${component2:variable1} and self reference ${variable2}",
|
|
12
|
+
{
|
|
13
|
+
componentName: "component1",
|
|
14
|
+
},
|
|
15
|
+
),
|
|
16
|
+
myOtherVar: createVariableValueContainingReferencesFromString(
|
|
17
|
+
"the third component has ${component3:variable1}, isn't that cool?",
|
|
18
|
+
{
|
|
19
|
+
componentName: "component1",
|
|
20
|
+
},
|
|
21
|
+
),
|
|
22
|
+
myThirdVar: createVariableValueContainingReferencesFromString(
|
|
23
|
+
"value from component3: ${component3:variable3}",
|
|
24
|
+
{
|
|
25
|
+
componentName: "component1",
|
|
26
|
+
},
|
|
27
|
+
),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const getEnvVars = async (componentName: string) => {
|
|
31
|
+
return {
|
|
32
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
33
|
+
`i am variable1 from ${componentName}`,
|
|
34
|
+
{ componentName },
|
|
35
|
+
),
|
|
36
|
+
variable2: createVariableValueContainingReferencesFromString(
|
|
37
|
+
`foo from ${componentName}`,
|
|
38
|
+
{
|
|
39
|
+
componentName,
|
|
40
|
+
},
|
|
41
|
+
),
|
|
42
|
+
variable3: createVariableValueContainingReferencesFromString(
|
|
43
|
+
`i am referencing \${component1:variable1}`,
|
|
44
|
+
{ componentName },
|
|
45
|
+
),
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const result = await resolveAllReferences(values, getEnvVars);
|
|
50
|
+
expect(result).toEqual({
|
|
51
|
+
myVar: new VariableValueContainingReferences([
|
|
52
|
+
"the 2nd component has ",
|
|
53
|
+
"i am variable1 from component2",
|
|
54
|
+
" and self reference ",
|
|
55
|
+
"foo from component1",
|
|
56
|
+
]),
|
|
57
|
+
myOtherVar: new VariableValueContainingReferences([
|
|
58
|
+
"the third component has ",
|
|
59
|
+
"i am variable1 from component3",
|
|
60
|
+
", isn't that cool?",
|
|
61
|
+
]),
|
|
62
|
+
myThirdVar: new VariableValueContainingReferences([
|
|
63
|
+
"value from component3: ",
|
|
64
|
+
"i am referencing ",
|
|
65
|
+
"i am variable1 from component1",
|
|
66
|
+
]),
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("detects infinte loop", async () => {
|
|
71
|
+
const values = {
|
|
72
|
+
myVar: createVariableValueContainingReferencesFromString(
|
|
73
|
+
"i am referencing ${component2:variable1}",
|
|
74
|
+
{
|
|
75
|
+
componentName: "component1",
|
|
76
|
+
},
|
|
77
|
+
),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getEnvVars = async (componentName: string) => {
|
|
81
|
+
if (componentName === "component2") {
|
|
82
|
+
return {
|
|
83
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
84
|
+
`i am referencing \${component3:variable1}`,
|
|
85
|
+
{ componentName },
|
|
86
|
+
),
|
|
87
|
+
};
|
|
88
|
+
} else if (componentName === "component3") {
|
|
89
|
+
return {
|
|
90
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
91
|
+
`i am referencing \${component1:variable1}`,
|
|
92
|
+
{ componentName },
|
|
93
|
+
),
|
|
94
|
+
};
|
|
95
|
+
} else {
|
|
96
|
+
return {
|
|
97
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
98
|
+
`i am referencing \${component2:variable1}`,
|
|
99
|
+
{ componentName },
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// expect to throw an error
|
|
106
|
+
await expect(resolveAllReferences(values, getEnvVars)).rejects.toThrow(
|
|
107
|
+
"Infinite loop detected in these variables: myVar (last reference: ${component1:variable1})",
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VariableReference,
|
|
3
|
+
VariableValueContainingReferences,
|
|
4
|
+
createVariableValueContainingReferencesFromString,
|
|
5
|
+
} from "../VariableValueContainingReferences";
|
|
6
|
+
import { resolveAllReferencesOnce } from "../resolveAllReferencesOnce";
|
|
7
|
+
|
|
8
|
+
describe("resolveAllReferencesOnce", () => {
|
|
9
|
+
it("should replace all references", async () => {
|
|
10
|
+
const values = {
|
|
11
|
+
myVar: createVariableValueContainingReferencesFromString(
|
|
12
|
+
"the 2nd component has ${component2:variable1} and self reference ${variable2}",
|
|
13
|
+
{ componentName: "component1" },
|
|
14
|
+
),
|
|
15
|
+
myOtherVar: createVariableValueContainingReferencesFromString(
|
|
16
|
+
"the third component has ${component3:variable1}, isn't that cool?",
|
|
17
|
+
{ componentName: "component1" },
|
|
18
|
+
),
|
|
19
|
+
myThirdVar: createVariableValueContainingReferencesFromString(
|
|
20
|
+
"value from component3: ${component3:variable3}",
|
|
21
|
+
{ componentName: "component1" },
|
|
22
|
+
),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const getEnvVars = async (componentName: string) => {
|
|
26
|
+
return {
|
|
27
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
28
|
+
`i am variable1 from ${componentName}`,
|
|
29
|
+
{ componentName },
|
|
30
|
+
),
|
|
31
|
+
variable2: createVariableValueContainingReferencesFromString(
|
|
32
|
+
`foo from ${componentName}`,
|
|
33
|
+
{
|
|
34
|
+
componentName,
|
|
35
|
+
},
|
|
36
|
+
),
|
|
37
|
+
variable3: createVariableValueContainingReferencesFromString(
|
|
38
|
+
`i am referencing \${component1:variable1}`,
|
|
39
|
+
{ componentName },
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const result = await resolveAllReferencesOnce(values, getEnvVars);
|
|
45
|
+
expect(result).toEqual({
|
|
46
|
+
myVar: new VariableValueContainingReferences([
|
|
47
|
+
"the 2nd component has ",
|
|
48
|
+
"i am variable1 from component2",
|
|
49
|
+
" and self reference ",
|
|
50
|
+
"foo from component1",
|
|
51
|
+
]),
|
|
52
|
+
myOtherVar: new VariableValueContainingReferences([
|
|
53
|
+
"the third component has ",
|
|
54
|
+
"i am variable1 from component3",
|
|
55
|
+
", isn't that cool?",
|
|
56
|
+
]),
|
|
57
|
+
myThirdVar: new VariableValueContainingReferences([
|
|
58
|
+
"value from component3: ",
|
|
59
|
+
"i am referencing ",
|
|
60
|
+
new VariableReference("component1", "variable1"),
|
|
61
|
+
]),
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnresolvableReference,
|
|
3
|
+
VariableReference,
|
|
4
|
+
createVariableValueContainingReferencesFromString,
|
|
5
|
+
} from "../VariableValueContainingReferences";
|
|
6
|
+
import { resolveReferencesOnce } from "../resolveReferencesOnce";
|
|
7
|
+
|
|
8
|
+
describe("resolveReferencesOnce", () => {
|
|
9
|
+
it("should replace a reference to another component", async () => {
|
|
10
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
11
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
12
|
+
{
|
|
13
|
+
componentName: "myComponent",
|
|
14
|
+
},
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const result = resolveReferencesOnce(
|
|
18
|
+
value,
|
|
19
|
+
({ componentName, variableName }) => {
|
|
20
|
+
return createVariableValueContainingReferencesFromString(
|
|
21
|
+
`replaced ${componentName}:${variableName}`,
|
|
22
|
+
{ componentName },
|
|
23
|
+
);
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(result.parts).toEqual([
|
|
28
|
+
"the other component has ",
|
|
29
|
+
"replaced otherComponent:variableName",
|
|
30
|
+
", isn't that cool?",
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
it("should keep references in replacement", async () => {
|
|
34
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
35
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
36
|
+
{
|
|
37
|
+
componentName: "myComponent",
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const result = resolveReferencesOnce(
|
|
42
|
+
value,
|
|
43
|
+
({ componentName, variableName }) => {
|
|
44
|
+
return createVariableValueContainingReferencesFromString(
|
|
45
|
+
`replaced ${componentName}:${variableName}, contains reference to \${thirdComponent:x}`,
|
|
46
|
+
{ componentName },
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(result.parts).toEqual([
|
|
52
|
+
"the other component has ",
|
|
53
|
+
|
|
54
|
+
"replaced otherComponent:variableName, contains reference to ",
|
|
55
|
+
new VariableReference("thirdComponent", "x"),
|
|
56
|
+
", isn't that cool?",
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("can be run multiple times", async () => {
|
|
61
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
62
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
63
|
+
{
|
|
64
|
+
componentName: "myComponent",
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
const replacer = ({
|
|
68
|
+
componentName,
|
|
69
|
+
variableName,
|
|
70
|
+
}: {
|
|
71
|
+
componentName: string;
|
|
72
|
+
variableName: string;
|
|
73
|
+
}) => {
|
|
74
|
+
return createVariableValueContainingReferencesFromString(
|
|
75
|
+
componentName === "thirdComponent"
|
|
76
|
+
? "value from third component"
|
|
77
|
+
: `replaced ${componentName}:${variableName}, contains reference to \${thirdComponent:x}`,
|
|
78
|
+
{ componentName },
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
const result = resolveReferencesOnce(
|
|
82
|
+
resolveReferencesOnce(value, replacer),
|
|
83
|
+
replacer,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
expect(result.parts).toEqual([
|
|
87
|
+
"the other component has ",
|
|
88
|
+
"replaced otherComponent:variableName, contains reference to ",
|
|
89
|
+
"value from third component",
|
|
90
|
+
", isn't that cool?",
|
|
91
|
+
]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("flags unresolveable", async () => {
|
|
95
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
96
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
97
|
+
{
|
|
98
|
+
componentName: "myComponent",
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const result = resolveReferencesOnce(
|
|
103
|
+
value,
|
|
104
|
+
({ componentName, variableName }) => {
|
|
105
|
+
return null;
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
expect(result.parts).toEqual([
|
|
110
|
+
"the other component has ",
|
|
111
|
+
new UnresolvableReference(
|
|
112
|
+
new VariableReference("otherComponent", "variableName"),
|
|
113
|
+
),
|
|
114
|
+
", isn't that cool?",
|
|
115
|
+
]);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VariableReference,
|
|
3
|
+
createVariableValueContainingReferencesFromString,
|
|
4
|
+
} from "../VariableValueContainingReferences";
|
|
5
|
+
|
|
6
|
+
describe("createVarialeValueFromString", () => {
|
|
7
|
+
it("should create a VariableValue from a simple string", () => {
|
|
8
|
+
const stringValue = "hello world";
|
|
9
|
+
|
|
10
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
11
|
+
stringValue,
|
|
12
|
+
{
|
|
13
|
+
componentName: "myComponent",
|
|
14
|
+
},
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
expect(result.parts).toEqual([stringValue]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("extracts references to other components", () => {
|
|
21
|
+
const stringValue =
|
|
22
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?";
|
|
23
|
+
|
|
24
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
25
|
+
stringValue,
|
|
26
|
+
{
|
|
27
|
+
componentName: "myComponent",
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
expect(result.parts).toEqual([
|
|
32
|
+
"the other component has ",
|
|
33
|
+
new VariableReference("otherComponent", "variableName"),
|
|
34
|
+
", isn't that cool?",
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("extracts self references", () => {
|
|
39
|
+
const stringValue = "my component has ${variableName}!";
|
|
40
|
+
|
|
41
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
42
|
+
stringValue,
|
|
43
|
+
{
|
|
44
|
+
componentName: "myComponent",
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(result.parts).toEqual([
|
|
49
|
+
"my component has ",
|
|
50
|
+
new VariableReference("myComponent", "variableName"),
|
|
51
|
+
"!",
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
it("extracts multiple references", () => {
|
|
55
|
+
const stringValue =
|
|
56
|
+
"my component has ${variableName} and the other component has ${otherComponent:variableName}!";
|
|
57
|
+
|
|
58
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
59
|
+
stringValue,
|
|
60
|
+
{
|
|
61
|
+
componentName: "myComponent",
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect(result.parts).toEqual([
|
|
66
|
+
"my component has ",
|
|
67
|
+
new VariableReference("myComponent", "variableName"),
|
|
68
|
+
" and the other component has ",
|
|
69
|
+
new VariableReference("otherComponent", "variableName"),
|
|
70
|
+
"!",
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { VariableValue } from "./VariableValue";
|
|
2
|
+
import type { VariableValueContainingReferences } from "./VariableValueContainingReferences";
|
|
3
|
+
import { VariableReference } from "./VariableValueContainingReferences";
|
|
4
|
+
import { resolveAllReferencesOnce as resolveAllReferencesOnce } from "./resolveAllReferencesOnce";
|
|
5
|
+
|
|
6
|
+
export const resolveAllReferences = async (
|
|
7
|
+
values: Record<string, VariableValueContainingReferences>,
|
|
8
|
+
getEnvVars: (
|
|
9
|
+
componentName: string,
|
|
10
|
+
) => Promise<Record<string, VariableValue | null | undefined>>,
|
|
11
|
+
) => {
|
|
12
|
+
// replace until there aren't any references left
|
|
13
|
+
let result = values;
|
|
14
|
+
|
|
15
|
+
let i = 0;
|
|
16
|
+
|
|
17
|
+
while (
|
|
18
|
+
Object.values(result).some((value) =>
|
|
19
|
+
value.parts.some((part) => part instanceof VariableReference),
|
|
20
|
+
)
|
|
21
|
+
) {
|
|
22
|
+
const replaced = await resolveAllReferencesOnce(result, getEnvVars);
|
|
23
|
+
|
|
24
|
+
result = replaced;
|
|
25
|
+
i++;
|
|
26
|
+
if (i > 1000) {
|
|
27
|
+
const unresolved = Object.entries(result).filter(([key, value]) =>
|
|
28
|
+
value.parts.some((part) => part instanceof VariableReference),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
throw new Error(
|
|
32
|
+
"Infinite loop detected in these variables: " +
|
|
33
|
+
unresolved
|
|
34
|
+
.map(
|
|
35
|
+
([key, value]) =>
|
|
36
|
+
`${key} (last reference: ${value.parts.find(
|
|
37
|
+
(part) => part instanceof VariableReference,
|
|
38
|
+
)})`,
|
|
39
|
+
)
|
|
40
|
+
.join(", "),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { VariableValue } from "./VariableValue";
|
|
2
|
+
import type { VariableValueContainingReferences } from "./VariableValueContainingReferences";
|
|
3
|
+
import { VariableReference } from "./VariableValueContainingReferences";
|
|
4
|
+
import { resolveReferencesOnce } from "./resolveReferencesOnce";
|
|
5
|
+
|
|
6
|
+
export const resolveAllReferencesOnce = async (
|
|
7
|
+
values: Record<string, VariableValueContainingReferences>,
|
|
8
|
+
getEnvVars: (
|
|
9
|
+
componentName: string,
|
|
10
|
+
) => Promise<Record<string, VariableValue | undefined | null>>,
|
|
11
|
+
) => {
|
|
12
|
+
const allReferences = Object.values(values).flatMap(
|
|
13
|
+
(value) =>
|
|
14
|
+
value?.parts.filter(
|
|
15
|
+
(part) => part instanceof VariableReference,
|
|
16
|
+
) as VariableReference[],
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const allComponentsUnique = Array.from(
|
|
20
|
+
new Set(allReferences.map((reference) => reference.componentName)),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const allEnvVarsInComponents = Object.fromEntries(
|
|
24
|
+
await Promise.all(
|
|
25
|
+
allComponentsUnique.map(async (componentName) => [
|
|
26
|
+
componentName,
|
|
27
|
+
await getEnvVars(componentName),
|
|
28
|
+
]) as Array<
|
|
29
|
+
Promise<[string, Record<string, VariableValue | undefined | null>]>
|
|
30
|
+
>,
|
|
31
|
+
),
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return Object.fromEntries(
|
|
35
|
+
Object.entries(values).map(([key, value]) => [
|
|
36
|
+
key,
|
|
37
|
+
value !== null && value !== undefined
|
|
38
|
+
? resolveReferencesOnce(value, ({ componentName, variableName }) => {
|
|
39
|
+
return allEnvVarsInComponents[componentName][variableName];
|
|
40
|
+
})
|
|
41
|
+
: value,
|
|
42
|
+
]),
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { VariableValue } from "./VariableValue";
|
|
2
|
+
import {
|
|
3
|
+
UnresolvableReference,
|
|
4
|
+
VariableReference,
|
|
5
|
+
VariableValueContainingReferences,
|
|
6
|
+
} from "./VariableValueContainingReferences";
|
|
7
|
+
|
|
8
|
+
type Resolver = (args: {
|
|
9
|
+
componentName: string;
|
|
10
|
+
variableName: string;
|
|
11
|
+
}) => VariableValue | null | undefined;
|
|
12
|
+
export const resolveReferencesOnce = (
|
|
13
|
+
value: VariableValueContainingReferences,
|
|
14
|
+
resolver: Resolver,
|
|
15
|
+
) => {
|
|
16
|
+
const replacedParts = value.parts.map((part) => {
|
|
17
|
+
if (part instanceof VariableReference) {
|
|
18
|
+
const result = resolver({
|
|
19
|
+
componentName: part.componentName,
|
|
20
|
+
variableName: part.variableName,
|
|
21
|
+
});
|
|
22
|
+
return result ?? new UnresolvableReference(part);
|
|
23
|
+
} else {
|
|
24
|
+
return part;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return new VariableValueContainingReferences(replacedParts);
|
|
29
|
+
};
|
package/bin/catladder-gitlab.js
DELETED