cloudmason2 2.0.202609012352 → 2.1.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.
@@ -83,10 +83,18 @@ exports.main = async function(args){
83
83
  }
84
84
 
85
85
  // --- IV UPLOAD STACK ---
86
- // Only alteration to the template: set the AmiId parameter's Default to the new AMI
86
+ // Two alterations to the template: the Build.App.Version mapping gets the full version so the
87
+ // stack can hand it to the app, and the AmiId parameter's Default is set to the new AMI
87
88
  let finalStack = stackText;
89
+ const buildVersion = setBuildVersion(finalStack, fullVersion);
90
+ finalStack = buildVersion.text;
91
+ if (buildVersion.updated){
92
+ console.log(`Set Mappings.Build.App.Version to ${fullVersion}`);
93
+ } else {
94
+ console.log('No Mappings.Build.App.Version in stack. Version not stamped');
95
+ }
88
96
  if (ami_id){
89
- const amiDefault = setAmiDefault(stackText, ami_id);
97
+ const amiDefault = setAmiDefault(finalStack, ami_id);
90
98
  finalStack = amiDefault.text;
91
99
  if (amiDefault.updated){
92
100
  console.log(`Set AmiId parameter Default to ${ami_id}`);
@@ -271,6 +279,41 @@ function setAmiDefault(stackText, amiId){
271
279
  return { text: lines.join('\n'), updated: true };
272
280
  }
273
281
 
282
+ // Set Mappings.Build.App.Version to the full version, touching nothing else in the template.
283
+ // A mapping rather than a parameter because a stack update keeps previous parameter values
284
+ // (launch passes UsePreviousValue, the console pre-fills them) while a mapping is always read
285
+ // from the template being deployed. Apps read it in UserData with !FindInMap [Build, App, Version].
286
+ // JSON templates are parsed; YAML templates get a single-line text edit.
287
+ function setBuildVersion(stackText, version){
288
+ if (stackText.trim().startsWith('{')){
289
+ const tpl = JSON.parse(stackText);
290
+ if (!tpl.Mappings || !tpl.Mappings.Build || !tpl.Mappings.Build.App){ return { text: stackText, updated: false } }
291
+ tpl.Mappings.Build.App.Version = version;
292
+ return { text: JSON.stringify(tpl, null, 4), updated: true };
293
+ }
294
+
295
+ const lines = stackText.split(/\r?\n/);
296
+ // Walk Mappings -> Build -> App -> Version: each key sits inside the previous one's block,
297
+ // which ends at the first line indented at or above the parent key
298
+ let line = lines.findIndex(l=>{ return /^Mappings:\s*(#.*)?$/.test(l) });
299
+ if (line === -1){ return { text: stackText, updated: false } }
300
+ let indent = 0;
301
+ for (const key of ['Build', 'App', 'Version']){
302
+ let found = -1;
303
+ for (let i=line+1; i<lines.length; i++){
304
+ if (lines[i].trim() === '' || /^\s*#/.test(lines[i])){ continue }
305
+ const lineIndent = lines[i].match(/^\s*/)[0].length;
306
+ if (lineIndent <= indent){ break }
307
+ if (new RegExp(`^\\s+${key}:`).test(lines[i])){ found = i; indent = lineIndent; break }
308
+ }
309
+ if (found === -1){ return { text: stackText, updated: false } }
310
+ line = found;
311
+ }
312
+ // Quote the value: the timestamp segment makes it look like a number to YAML otherwise
313
+ lines[line] = lines[line].replace(/^(\s+Version:).*$/, `$1 '${version}'`);
314
+ return { text: lines.join('\n'), updated: true };
315
+ }
316
+
274
317
  async function putManifest(s3, bucket, appPrefix, manifest){
275
318
  await s3.send(new PutObjectCommand({
276
319
  Bucket: bucket,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudmason2",
3
- "version": "2.0.202609012352",
3
+ "version": "2.1.0",
4
4
  "description": "",
5
5
  "main": "main.js",
6
6
  "files": [