timonel 2.11.0 → 2.12.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/CHANGELOG.md +11 -0
- package/README.md +3 -45
- package/dist/cli.js +57 -32
- package/dist/lib/utils/helmYamlSerializer.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
# [2.12.0](https://github.com/KenkoGeek/timonel/compare/v2.11.0...v2.12.0) (2025-09-28)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **cli:** harden flag handling and path validation ([#130](https://github.com/KenkoGeek/timonel/issues/130)) ([2186d88](https://github.com/KenkoGeek/timonel/commit/2186d886428752025e7bf531c4a6541dade683a6))
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **docs:** update references and CLI [skip ci] ([23704d3](https://github.com/KenkoGeek/timonel/commit/23704d3164cfbb92d183af40c70e27a32b566d06))
|
|
10
|
+
- **docs:** update references and CLI [skip ci] ([be4bcdc](https://github.com/KenkoGeek/timonel/commit/be4bcdca62cb3a9339e5ad70efc0ba31a6d9d5be))
|
|
11
|
+
|
|
1
12
|
# [2.11.0](https://github.com/KenkoGeek/timonel/compare/v2.10.2...v2.11.0) (2025-09-26)
|
|
2
13
|
|
|
3
14
|
### Features
|
package/README.md
CHANGED
|
@@ -38,9 +38,6 @@ npm install -g timonel
|
|
|
38
38
|
|
|
39
39
|
# Or use with pnpm
|
|
40
40
|
pnpm add -g timonel
|
|
41
|
-
|
|
42
|
-
# Verify installation
|
|
43
|
-
tl --version
|
|
44
41
|
```
|
|
45
42
|
|
|
46
43
|
### Basic Usage
|
|
@@ -157,10 +154,10 @@ If you get `Error: Cannot find module 'cdk8s'` when running `tl umbrella synth`:
|
|
|
157
154
|
"version": "1.0.0",
|
|
158
155
|
"type": "module",
|
|
159
156
|
"dependencies": {
|
|
160
|
-
"cdk8s": "^2.70.
|
|
161
|
-
"cdk8s-plus-33": "^2.3.
|
|
157
|
+
"cdk8s": "^2.70.16",
|
|
158
|
+
"cdk8s-plus-33": "^2.3.8",
|
|
162
159
|
"constructs": "^10.4.2",
|
|
163
|
-
"timonel": "^2.
|
|
160
|
+
"timonel": "^2.11.0"
|
|
164
161
|
},
|
|
165
162
|
"devDependencies": {
|
|
166
163
|
"@types/node": "^24.5.2",
|
|
@@ -176,45 +173,6 @@ npm install
|
|
|
176
173
|
tl umbrella synth # Now it works!
|
|
177
174
|
```
|
|
178
175
|
|
|
179
|
-
### Version Display Issues
|
|
180
|
-
|
|
181
|
-
If the CLI shows an incorrect version:
|
|
182
|
-
|
|
183
|
-
**Problem**: The CLI might be using cached or hardcoded version information.
|
|
184
|
-
|
|
185
|
-
**Solution**: Rebuild the project:
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
# In the Timonel project directory
|
|
189
|
-
pnpm build
|
|
190
|
-
tl --version # Should show correct version
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### TypeScript Compilation Errors
|
|
194
|
-
|
|
195
|
-
If you encounter TypeScript errors when using umbrella charts:
|
|
196
|
-
|
|
197
|
-
**Problem**: Type mismatches in subchart configurations.
|
|
198
|
-
|
|
199
|
-
**Solution**: Ensure proper type casting for version and description fields:
|
|
200
|
-
|
|
201
|
-
```typescript
|
|
202
|
-
// ✅ Correct
|
|
203
|
-
const subchart = {
|
|
204
|
-
name: 'my-service',
|
|
205
|
-
version: '1.0.0' as string,
|
|
206
|
-
description: 'My service' as string,
|
|
207
|
-
chart: myChartFunction,
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
// ❌ Incorrect
|
|
211
|
-
const subchart = {
|
|
212
|
-
name: 'my-service',
|
|
213
|
-
version: someUnknownValue, // This will cause TypeScript errors
|
|
214
|
-
chart: myChartFunction,
|
|
215
|
-
};
|
|
216
|
-
```
|
|
217
|
-
|
|
218
176
|
## 🤝 Contributing
|
|
219
177
|
|
|
220
178
|
See our [Contributing Guide](https://github.com/KenkoGeek/timonel/wiki/Contributing) for development
|
package/dist/cli.js
CHANGED
|
@@ -12,37 +12,20 @@ const UMBRELLA_FILE_NAME = 'umbrella.ts';
|
|
|
12
12
|
const PACKAGE_JSON_FILE = 'package.json';
|
|
13
13
|
function getVersion() {
|
|
14
14
|
try {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
for (const packagePath of possiblePaths) {
|
|
22
|
-
try {
|
|
23
|
-
const validatedPath = SecurityUtils.validatePath(packagePath, process.cwd());
|
|
24
|
-
if (fs.existsSync(validatedPath)) {
|
|
25
|
-
try {
|
|
26
|
-
const packageJson = JSON.parse(fs.readFileSync(validatedPath, 'utf8'));
|
|
27
|
-
return packageJson.version || 'unknown';
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
catch {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
15
|
+
const packagePath = path.resolve(__dirname, '..', PACKAGE_JSON_FILE);
|
|
16
|
+
const allowedBase = path.resolve(__dirname, '..');
|
|
17
|
+
const validatedPath = SecurityUtils.validatePath(packagePath, allowedBase);
|
|
18
|
+
const packageJson = JSON.parse(fs.readFileSync(validatedPath, 'utf8'));
|
|
19
|
+
if (packageJson.version) {
|
|
20
|
+
return packageJson.version;
|
|
37
21
|
}
|
|
38
|
-
if (process.env.npm_package_version) {
|
|
39
|
-
return process.env.npm_package_version;
|
|
40
|
-
}
|
|
41
|
-
return 'unknown';
|
|
42
22
|
}
|
|
43
23
|
catch {
|
|
44
|
-
return 'unknown';
|
|
45
24
|
}
|
|
25
|
+
if (process.env.npm_package_version) {
|
|
26
|
+
return process.env.npm_package_version;
|
|
27
|
+
}
|
|
28
|
+
return 'unknown';
|
|
46
29
|
}
|
|
47
30
|
const cliLogger = createLogger('cli');
|
|
48
31
|
function log(msg, silent = false) {
|
|
@@ -162,7 +145,23 @@ await import(pathToFileURL('${tempChartFile}').href);
|
|
|
162
145
|
}
|
|
163
146
|
}
|
|
164
147
|
async function cmdValidate(flags) {
|
|
165
|
-
const
|
|
148
|
+
const lintArgs = ['lint', '.'];
|
|
149
|
+
if (flags?.env) {
|
|
150
|
+
try {
|
|
151
|
+
const sanitizedEnv = SecurityUtils.sanitizeEnvironmentName(flags.env);
|
|
152
|
+
lintArgs.push('-f', `values-${sanitizedEnv}.yaml`);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
console.error(SecurityUtils.sanitizeLogMessage(error.message));
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (flags?.set) {
|
|
160
|
+
for (const setValue of flags.set) {
|
|
161
|
+
lintArgs.push('--set', setValue);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const result = spawnSync('helm', lintArgs, {
|
|
166
165
|
stdio: flags?.silent ? 'pipe' : 'inherit',
|
|
167
166
|
encoding: 'utf8',
|
|
168
167
|
});
|
|
@@ -180,6 +179,21 @@ async function cmdDeploy(release, namespace, flags) {
|
|
|
180
179
|
if (namespace) {
|
|
181
180
|
args.push('--namespace', namespace);
|
|
182
181
|
}
|
|
182
|
+
if (flags?.env) {
|
|
183
|
+
try {
|
|
184
|
+
const sanitizedEnv = SecurityUtils.sanitizeEnvironmentName(flags.env);
|
|
185
|
+
args.push('-f', `values-${sanitizedEnv}.yaml`);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
console.error(SecurityUtils.sanitizeLogMessage(error.message));
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (flags?.set) {
|
|
193
|
+
for (const setValue of flags.set) {
|
|
194
|
+
args.push('--set', setValue);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
183
197
|
const result = spawnSync('helm', args.filter((arg) => Boolean(arg)), {
|
|
184
198
|
stdio: flags?.silent ? 'pipe' : 'inherit',
|
|
185
199
|
encoding: 'utf8',
|
|
@@ -343,8 +357,19 @@ async function cmdUmbrellaAdd(subchartPath, silent = false) {
|
|
|
343
357
|
}
|
|
344
358
|
const config = JSON.parse(fs.readFileSync(configFile, 'utf8'));
|
|
345
359
|
const subchartName = path.basename(validSubchartPath);
|
|
346
|
-
const
|
|
360
|
+
const chartsRoot = path.join(process.cwd(), 'charts');
|
|
361
|
+
const targetSubchartPath = path.join(chartsRoot, validSubchartPath);
|
|
362
|
+
let subchartDir;
|
|
363
|
+
try {
|
|
364
|
+
subchartDir = SecurityUtils.validatePath(targetSubchartPath, chartsRoot);
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
console.error(SecurityUtils.sanitizeLogMessage(error.message));
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
347
370
|
fs.mkdirSync(subchartDir, { recursive: true });
|
|
371
|
+
const relativeSubchartPath = path.relative(chartsRoot, subchartDir) || subchartName;
|
|
372
|
+
const normalizedSubchartPath = relativeSubchartPath.split(path.sep).join('/');
|
|
348
373
|
const chartFile = path.join(subchartDir, 'chart.ts');
|
|
349
374
|
const { generateFlexibleSubchartTemplate } = await import('./lib/templates/flexible-subchart.js');
|
|
350
375
|
const subchartContent = generateFlexibleSubchartTemplate(subchartName);
|
|
@@ -352,11 +377,11 @@ async function cmdUmbrellaAdd(subchartPath, silent = false) {
|
|
|
352
377
|
config.subcharts.push({
|
|
353
378
|
name: subchartName,
|
|
354
379
|
version: getVersion(),
|
|
355
|
-
path: `./charts/${
|
|
380
|
+
path: `./charts/${normalizedSubchartPath}/chart.ts`,
|
|
356
381
|
});
|
|
357
382
|
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
358
|
-
updateUmbrellaTs(
|
|
359
|
-
log(`Subchart ${subchartName} added to umbrella at path '${
|
|
383
|
+
updateUmbrellaTs(normalizedSubchartPath, subchartName);
|
|
384
|
+
log(`Subchart ${subchartName} added to umbrella at path '${normalizedSubchartPath}'`, silent);
|
|
360
385
|
}
|
|
361
386
|
async function cmdUmbrellaSynth(outDir, flags) {
|
|
362
387
|
const umbrellaFile = path.join(process.cwd(), UMBRELLA_FILE_NAME);
|
|
@@ -217,7 +217,7 @@ function isQuotesBalanced(str) {
|
|
|
217
217
|
function validateFunctionCalls(_content) {
|
|
218
218
|
}
|
|
219
219
|
function checkCommonIssues(yaml, warnings) {
|
|
220
|
-
const deprecatedFunctions = ['template'
|
|
220
|
+
const deprecatedFunctions = ['template'];
|
|
221
221
|
for (const func of deprecatedFunctions) {
|
|
222
222
|
const pattern = new RegExp(`\\{\\{[^}]*\\b${func}\\b[^}]*\\}\\}`, 'g');
|
|
223
223
|
let match;
|
|
@@ -232,7 +232,7 @@ function checkCommonIssues(yaml, warnings) {
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
function checkQuotedExpressions(yaml, warnings) {
|
|
235
|
-
const quotedPatterns = [/'\
|
|
235
|
+
const quotedPatterns = [/'(\{\{[^}]+\}\})'/g, /"(\{\{[^}]+\}\})"/g];
|
|
236
236
|
for (const pattern of quotedPatterns) {
|
|
237
237
|
let match;
|
|
238
238
|
pattern.lastIndex = 0;
|