Skip to content

Commit f74ff54

Browse files
authored
feature: add process-templates input (#58)
Add `process-templates` input and tests. --------- Co-authored-by: korenyoni <[email protected]>
1 parent ca019e9 commit f74ff54

14 files changed

+132
-30
lines changed

action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ inputs:
1717
settings:
1818
description: The settings to extract.
1919
required: false
20+
process-templates:
21+
description: "Enable/disable processing of Go templates in Atmos stacks manifests."
22+
required: false
23+
default: "true"
2024
outputs:
2125
value:
2226
description: "The value of the setting when a single setting is returned."

atmos.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ logs:
6666
verbose: false
6767
colors: true
6868

69+
templates:
70+
settings:
71+
enabled: true
72+
sprig:
73+
enabled: true
74+
gomplate:
75+
enabled: true
76+
6977
# Custom CLI commands
7078
commands:
7179
- name: tf

dist/index.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -28877,9 +28877,9 @@ exports.NEVER = parseUtil_1.INVALID;
2887728877
Object.defineProperty(exports, "__esModule", ({ value: true }));
2887828878
exports.runAtmosDescribeComponent = void 0;
2887928879
const node_child_process_1 = __nccwpck_require__(7718);
28880-
const runAtmosDescribeComponent = async (component, stack, cwd) => {
28880+
const runAtmosDescribeComponent = async (component, stack, processTemplates, cwd) => {
2888128881
const options = cwd ? { cwd } : {};
28882-
const command = `atmos describe component ${component} -s ${stack} --format=json`;
28882+
const command = `atmos describe component ${component} -s ${stack} --format=json --process-templates=${String(processTemplates)}`;
2888328883
const atmos = (0, node_child_process_1.execSync)(command, options);
2888428884
return atmos.toString();
2888528885
};
@@ -28944,8 +28944,8 @@ exports.SettingInput = zod_1.z.object({
2894428944
outputPath: zod_1.z.string().trim().min(1)
2894528945
});
2894628946
exports.SettingsInput = zod_1.z.array(exports.SettingInput).min(1);
28947-
const getSetting = async (component, stack, settingsPath) => {
28948-
const cmdOutput = await (0, atmos_1.runAtmosDescribeComponent)(component, stack);
28947+
const getSetting = async (component, stack, settingsPath, processTemplates) => {
28948+
const cmdOutput = await (0, atmos_1.runAtmosDescribeComponent)(component, stack, processTemplates);
2894928949
const json = JSON.parse(cmdOutput);
2895028950
return (0, exports.getNestedValue)(json, settingsPath);
2895128951
};
@@ -28987,8 +28987,9 @@ const core = __importStar(__nccwpck_require__(2186));
2898728987
const _useCase_1 = __nccwpck_require__(9264);
2898828988
(async () => {
2898928989
try {
28990-
const singleResult = await (0, _useCase_1.processSingleSetting)();
28991-
const multipleResult = await (0, _useCase_1.processMultipleSettings)();
28990+
const processTemplates = core.getBooleanInput("process-templates");
28991+
const singleResult = await (0, _useCase_1.processSingleSetting)(processTemplates);
28992+
const multipleResult = await (0, _useCase_1.processMultipleSettings)(processTemplates);
2899228993
if (singleResult || multipleResult) {
2899328994
core.info("result returned successfully");
2899428995
}
@@ -29065,7 +29066,7 @@ exports.processMultipleSettings = void 0;
2906529066
const core = __importStar(__nccwpck_require__(2186));
2906629067
const _lib_1 = __nccwpck_require__(6791);
2906729068
const YAML = __importStar(__nccwpck_require__(4083));
29068-
const processMultipleSettings = async () => {
29069+
const processMultipleSettings = async (processTemplates) => {
2906929070
const settingsInput = core.getInput("settings");
2907029071
if (settingsInput) {
2907129072
const yaml = YAML.parse(settingsInput);
@@ -29075,7 +29076,7 @@ const processMultipleSettings = async () => {
2907529076
const output = await settings.reduce(async (accPromise, item) => {
2907629077
const acc = await accPromise;
2907729078
const { outputPath, ...rest } = item;
29078-
const result = await (0, _lib_1.getSetting)(item.component, item.stack, item.settingsPath);
29079+
const result = await (0, _lib_1.getSetting)(item.component, item.stack, item.settingsPath, processTemplates);
2907929080
return { ...acc, [outputPath]: result };
2908029081
}, Promise.resolve({}));
2908129082
core.setOutput("settings", JSON.stringify(output));
@@ -29121,7 +29122,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
2912129122
exports.processSingleSetting = void 0;
2912229123
const core = __importStar(__nccwpck_require__(2186));
2912329124
const _lib_1 = __nccwpck_require__(6791);
29124-
const processSingleSetting = async () => {
29125+
const processSingleSetting = async (processTemplates) => {
2912529126
const component = core.getInput("component");
2912629127
const stack = core.getInput("stack");
2912729128
const settingsPath = core.getInput("settings-path");
@@ -29132,7 +29133,7 @@ const processSingleSetting = async () => {
2913229133
};
2913329134
const parseResult = _lib_1.SingleSettingInput.safeParse(singleSetting);
2913429135
if (parseResult.success) {
29135-
const value = await (0, _lib_1.getSetting)(parseResult.data.component, parseResult.data.stack, parseResult.data["settings-path"]);
29136+
const value = await (0, _lib_1.getSetting)(parseResult.data.component, parseResult.data.stack, parseResult.data["settings-path"], processTemplates);
2913629137
core.setOutput("value", value);
2913729138
return true;
2913829139
}

dist/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/atmos.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { runAtmosDescribeComponent } from "./atmos";
22

33
describe("runAtmosDescribeComponent", () => {
44
it("should return a string", async () => {
5-
const result = JSON.parse(await runAtmosDescribeComponent("foo", "core-ue1-dev"));
5+
const result = JSON.parse(await runAtmosDescribeComponent("foo", "core-ue1-dev", true));
66
expect(result.atmos_component).toEqual("foo");
77
expect(result.atmos_stack).toEqual("core-ue1-dev");
88
});

src/lib/atmos.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { execSync } from "node:child_process";
22

3-
export const runAtmosDescribeComponent = async (component: string, stack: string, cwd?: string) => {
3+
export const runAtmosDescribeComponent = async (component: string, stack: string, processTemplates: boolean, cwd?: string) => {
44
const options = cwd ? { cwd } : {};
5-
6-
const command = `atmos describe component ${component} -s ${stack} --format=json`;
5+
const command = `atmos describe component ${component} -s ${stack} --format=json --process-templates=${String(processTemplates)}`;
76
const atmos = execSync(command, options);
87
return atmos.toString();
98
};

src/lib/settings.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ describe("getSingleSetting", () => {
2929
const settingValue = await getSetting(
3030
"foo",
3131
"core-ue1-dev",
32-
"atmos_cli_config.components.terraform.base_path"
33-
);
32+
"atmos_cli_config.components.terraform.base_path",
33+
true);
3434
expect(settingValue).toEqual("components/terraform");
3535
});
3636
});

src/lib/settings.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ export type SettingsInput = z.infer<typeof SettingsInput>;
3131
export const getSetting = async (
3232
component: string,
3333
stack: string,
34-
settingsPath: string
34+
settingsPath: string,
35+
processTemplates: boolean
3536
) => {
36-
const cmdOutput = await runAtmosDescribeComponent(component, stack);
37+
const cmdOutput = await runAtmosDescribeComponent(component, stack, processTemplates);
3738
const json = JSON.parse(cmdOutput);
3839

3940
return getNestedValue(json, settingsPath);

src/main.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import { processMultipleSettings, processSingleSetting } from "@useCase";
33

44
(async () => {
55
try {
6-
const singleResult = await processSingleSetting();
7-
const multipleResult = await processMultipleSettings();
6+
const processTemplates = core.getBooleanInput("process-templates");
7+
const singleResult = await processSingleSetting(processTemplates);
8+
const multipleResult = await processMultipleSettings(processTemplates);
89

910
if (singleResult || multipleResult) {
1011
core.info("result returned successfully");

src/useCase/process-multiple-settings.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe("multipleSettings", () => {
4646
});
4747

4848
it("should return an object", async () => {
49-
const result = await processMultipleSettings();
49+
const result = await processMultipleSettings(true);
5050
expect(outputs["settings"]).toEqual(
5151
'{"prop1":"components/terraform","secretArn":"arn:aws:secretsmanager:us-east-1:000000000000:secret:MySecret-PlMes3"}'
5252
);

src/useCase/process-multiple-settings.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as core from "@actions/core";
22
import { getSetting, SettingsInput } from "@lib";
33
import * as YAML from "yaml";
44

5-
export const processMultipleSettings = async () => {
5+
export const processMultipleSettings = async (processTemplates: boolean) => {
66
const settingsInput = core.getInput("settings");
77

88
if (settingsInput) {
@@ -18,8 +18,8 @@ export const processMultipleSettings = async () => {
1818
const result = await getSetting(
1919
item.component,
2020
item.stack,
21-
item.settingsPath
22-
);
21+
item.settingsPath,
22+
processTemplates);
2323
return { ...acc, [outputPath]: result };
2424
}, Promise.resolve({}));
2525

src/useCase/process-single-setting.test.ts

+78-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe("singleSetting", () => {
1212
const mockValues: any = {
1313
component: "foo",
1414
stack: "core-ue1-dev",
15-
"settings-path": "atmos_cli_config.components.terraform.base_path"
15+
"settings-path": "atmos_cli_config.components.terraform.base_path",
1616
};
1717

1818
jest
@@ -35,7 +35,83 @@ describe("singleSetting", () => {
3535
});
3636

3737
it("should return a value", async () => {
38-
const result = await processSingleSetting();
38+
const result = await processSingleSetting(true);
3939
expect(outputs["value"]).toEqual("components/terraform");
4040
});
4141
});
42+
43+
describe("singleSettingWithTemplatesEnabled", () => {
44+
let outputs: any = {};
45+
46+
beforeEach(() => {
47+
outputs = {};
48+
const mockValues: any = {
49+
component: "hello",
50+
stack: "core-ue1-dev",
51+
"settings-path": "settings.level1.example",
52+
};
53+
54+
jest
55+
.spyOn(core, "getInput")
56+
.mockImplementation(
57+
(name: string, options?: core.InputOptions | undefined) => {
58+
return mockValues[name];
59+
}
60+
);
61+
62+
jest
63+
.spyOn(core, "setOutput")
64+
.mockImplementation((name: string, value: any) => {
65+
outputs[name] = value;
66+
});
67+
});
68+
69+
afterEach(() => {
70+
jest.resetAllMocks();
71+
});
72+
73+
it("should return a templated value", async () => {
74+
const result = await processSingleSetting(true);
75+
expect(outputs["value"]).toEqual(
76+
"core-ue1-dev"
77+
);
78+
});
79+
});
80+
81+
describe("singleSettingWithTemplatesDisabled", () => {
82+
let outputs: any = {};
83+
84+
beforeEach(() => {
85+
outputs = {};
86+
const mockValues: any = {
87+
component: "hello",
88+
stack: "core-ue1-dev",
89+
"settings-path": "settings.level1.example"
90+
};
91+
92+
jest
93+
.spyOn(core, "getInput")
94+
.mockImplementation(
95+
(name: string, options?: core.InputOptions | undefined) => {
96+
return mockValues[name];
97+
}
98+
);
99+
100+
jest
101+
.spyOn(core, "setOutput")
102+
.mockImplementation((name: string, value: any) => {
103+
outputs[name] = value;
104+
});
105+
});
106+
107+
afterEach(() => {
108+
jest.resetAllMocks();
109+
});
110+
111+
it("should return a template placeholder", async () => {
112+
const result = await processSingleSetting(false);
113+
expect(outputs["value"]).toEqual(
114+
"{{ (printf \"%s-%s-%s\" .vars.tenant .vars.environment .vars.stage) }}"
115+
);
116+
});
117+
});

src/useCase/process-single-setting.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as core from "@actions/core";
22
import { getSetting, SingleSettingInput } from "@lib";
33
import * as YAML from "yaml";
44

5-
export const processSingleSetting = async () => {
5+
export const processSingleSetting = async (processTemplates: boolean) => {
66
const component = core.getInput("component");
77
const stack = core.getInput("stack");
88
const settingsPath = core.getInput("settings-path");
@@ -19,8 +19,8 @@ export const processSingleSetting = async () => {
1919
const value = await getSetting(
2020
parseResult.data.component,
2121
parseResult.data.stack,
22-
parseResult.data["settings-path"]
23-
);
22+
parseResult.data["settings-path"],
23+
processTemplates);
2424
core.setOutput("value", value);
2525
return true;
2626
}

stacks/orgs/demo/dev/templates.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
components:
2+
terraform:
3+
hello:
4+
settings:
5+
level1:
6+
example: '{{ (printf "%s-%s-%s" .vars.tenant .vars.environment .vars.stage) }}'
7+
vars:
8+
namespace: demo
9+
tenant: core
10+
environment: ue1
11+
stage: dev
12+
hello: world

0 commit comments

Comments
 (0)