@firestartr/cli 1.55.0-snapshot-0 → 1.55.0-snapshot-2

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/build/index.js CHANGED
@@ -355878,7 +355878,7 @@ function createCodeOwnersData(claim, additionalRules) {
355878
355878
  message = concatLine(message, `\n${paddedAsterisk}${resolveCodeownersRef(claim.owner, claim.providers.github.org)}`);
355879
355879
  }
355880
355880
  if (claim.platformOwner) {
355881
- message = concatLine(message, `\n${paddedAsterisk}${resolveCodeownersRef(claim.platformOwner, claim.providers.github.org)}`);
355881
+ message = concatLine(message, `\n${'/.github/'.padEnd(25)}${resolveCodeownersRef(claim.platformOwner, claim.providers.github.org)}`);
355882
355882
  }
355883
355883
  if (additionalRules) {
355884
355884
  for (const rule of additionalRules) {
@@ -357903,7 +357903,7 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
357903
357903
  },
357904
357904
  owner: {
357905
357905
  type: 'string',
357906
- pattern: '^(user|group):[a-zA-Z0-9_-]+$',
357906
+ pattern: '^(user|group):\\S+$',
357907
357907
  },
357908
357908
  },
357909
357909
  required: ['description', 'owner'],
@@ -359701,6 +359701,9 @@ var ajv_default = /*#__PURE__*/__nccwpck_require__.n(dist_ajv);
359701
359701
  $arg: {
359702
359702
  type: 'string',
359703
359703
  },
359704
+ $template: {
359705
+ type: 'string',
359706
+ },
359704
359707
  $default: {
359705
359708
  type: ['string', 'array', 'boolean'],
359706
359709
  },
@@ -360681,8 +360684,24 @@ function buildContext(entity, args, firestartrConfig, featureArgs) {
360681
360684
  });
360682
360685
  context.firestartrConfig = firestartrConfig;
360683
360686
  context.traceability = featureArgs['traceability'] || {};
360687
+ buildTemplateArgs(args, context);
360684
360688
  return context;
360685
360689
  }
360690
+ /**
360691
+ * Mutates the provided context object by adding properties for each argument
360692
+ * that has a `$template`, using the current context to render the template content.
360693
+ *
360694
+ * @param args - Argument definitions, where each entry may contain a `$template` key.
360695
+ * @param context - The context object to be mutated with rendered template values.
360696
+ * @returns void
360697
+ */
360698
+ function buildTemplateArgs(args, context) {
360699
+ Object.entries(args).forEach(([key, arg]) => {
360700
+ if ('$template' in arg) {
360701
+ context[key] = renderContent(arg['$template'], context);
360702
+ }
360703
+ });
360704
+ }
360686
360705
  function expandFiles(featurePath, configData, context) {
360687
360706
  let files = [];
360688
360707
  for (const tpl of configData.filesTemplates) {
@@ -360692,7 +360711,17 @@ function expandFiles(featurePath, configData, context) {
360692
360711
  context.config.files = context.config.files.concat(files).flat(Infinity);
360693
360712
  }
360694
360713
  function expandFilesTemplate(featurePath, tplPath, context) {
360695
- const template = external_fs_default().readFileSync(external_path_default().join(featurePath, tplPath)).toString();
360714
+ const templatePath = external_path_default().join(featurePath, tplPath);
360715
+ features_renderer_src_logger.debug(`Expanding files section with template located at ${templatePath}`);
360716
+ let template;
360717
+ try {
360718
+ template = external_fs_default().readFileSync(templatePath).toString();
360719
+ }
360720
+ catch (err) {
360721
+ const message = err && err.message ? err.message : String(err);
360722
+ features_renderer_src_logger.error(`Failed to read template file at "${templatePath}": ${message}`);
360723
+ throw new Error(`Failed to read template file at "${templatePath}": ${message}`);
360724
+ }
360696
360725
  const renderedTemplate = renderContent(template, context);
360697
360726
  const data = catalog_common.io.fromYaml(renderedTemplate) || { files: [] };
360698
360727
  if (!data.files)
@@ -367709,12 +367738,28 @@ async function addDestroyCommitStatus(cr, state, description = '', context = '')
367709
367738
  async function addPlanStatusCheck(prUrl, summary, status = 'in_progress', isFailure = false) {
367710
367739
  try {
367711
367740
  operator_src_logger.debug(`The ctl is checking the length of the plan summary, which is '${summary.length}'.`);
367712
- if (summary.length > MAX_CHARS_OUPUT_PLAN) {
367741
+ // Determine if we should wrap in fences
367742
+ const shouldWrap = status === 'completed' && !summary.includes('```');
367743
+ const FENCE_OVERHEAD = 17; // "```terraform\n" + "\n```"
367744
+ let processedSummary = summary;
367745
+ if (shouldWrap) {
367746
+ // Truncate accounting for fence overhead
367747
+ const maxBodyLength = MAX_CHARS_OUPUT_PLAN - FENCE_OVERHEAD;
367748
+ if (summary.length > maxBodyLength) {
367749
+ const mustDrop = summary.length - maxBodyLength;
367750
+ processedSummary = summary.substring(mustDrop);
367751
+ operator_src_logger.debug(`The ctl found the plan summary too lengthy (length: '${summary.length}'). The summary must drop because '${mustDrop}'.`);
367752
+ }
367753
+ // Wrap in fences
367754
+ processedSummary = `\`\`\`terraform\n${processedSummary}\n\`\`\``;
367755
+ }
367756
+ else if (summary.length > MAX_CHARS_OUPUT_PLAN) {
367757
+ // Truncate without wrapping
367713
367758
  const mustDrop = summary.length - MAX_CHARS_OUPUT_PLAN;
367714
- summary = summary.substring(mustDrop);
367759
+ processedSummary = summary.substring(mustDrop);
367715
367760
  operator_src_logger.debug(`The ctl found the plan summary too lengthy (length: '${summary.length}'). The summary must drop because '${mustDrop}'.`);
367716
367761
  }
367717
- await ctl_addStatusCheck({ summary, title: 'Terraform Plan Results' }, isFailure, 'terraform_plan', prUrl, status);
367762
+ await ctl_addStatusCheck({ summary: processedSummary, title: 'Terraform Plan Results' }, isFailure, 'terraform_plan', prUrl, status);
367718
367763
  }
367719
367764
  catch (e) {
367720
367765
  operator_src_logger.error(`The ctl encountered an error while adding plan status for PR '${prUrl}' with status '${status}'. Is Failure: '${isFailure}'. Error: '${e}'.`);
@@ -367854,29 +367899,91 @@ async function observe(plural, namespace, onAdd, onChange, onDelete, _onRename)
367854
367899
  }
367855
367900
  }
367856
367901
 
367902
+ ;// CONCATENATED MODULE: ../operator/src/high_priority_status.ts
367903
+
367904
+ const SORTED_PRIORITIES = [
367905
+ 'PROVISIONING',
367906
+ 'ERROR',
367907
+ 'OUT_OF_SYNC',
367908
+ 'PLANNING',
367909
+ 'DELETING',
367910
+ 'SYNCHRONIZED',
367911
+ 'PROVISIONED',
367912
+ 'DELETED',
367913
+ ];
367914
+ function setHighPriorityStatus(item) {
367915
+ const highPriorityCondition = conditionsSorter(item.status?.conditions || []);
367916
+ let highPriorityState = null;
367917
+ if (highPriorityCondition) {
367918
+ highPriorityState = {
367919
+ type: highPriorityCondition.type,
367920
+ reason: highPriorityCondition.reason,
367921
+ };
367922
+ }
367923
+ else {
367924
+ highPriorityState = {
367925
+ type: 'UNKNOWN',
367926
+ reason: 'AwaitingReconciliation',
367927
+ };
367928
+ }
367929
+ item.status.highPriorityState = highPriorityState.type;
367930
+ item.status.highPriorityReason = highPriorityState.reason;
367931
+ operator_src_logger.silly(`${item.kind}/${item.metadata.name} - Set HighPriorityStatus to ${item.status.highPriorityState} - ${item.status.highPriorityReason}`);
367932
+ }
367933
+ function conditionsSorter(conditions) {
367934
+ if (conditions.length === 0)
367935
+ return null;
367936
+ const getPriority = (type) => {
367937
+ const index = SORTED_PRIORITIES.indexOf(type);
367938
+ return index === -1 ? Number.MAX_SAFE_INTEGER : index;
367939
+ };
367940
+ return conditions
367941
+ .filter((condition) => {
367942
+ return condition.status === 'True';
367943
+ })
367944
+ .sort((a, b) => {
367945
+ const priorityA = getPriority(a.type);
367946
+ const priorityB = getPriority(b.type);
367947
+ return priorityA - priorityB;
367948
+ })[0];
367949
+ }
367950
+
367857
367951
  ;// CONCATENATED MODULE: ../operator/src/status.ts
367858
367952
 
367859
367953
 
367860
- async function needsProvisioningOnCreate(cr) {
367954
+
367955
+ async function upsertInitialStatus(pluralKind, namespace, item) {
367956
+ item = await getItemByItemPath(`${namespace}/${pluralKind}/${item.metadata.name}`);
367957
+ if (!('status' in item))
367958
+ item.status = {};
367959
+ if (!('conditions' in item.status))
367960
+ item.status.conditions = [];
367961
+ await writePrioritizedStatus(pluralKind, namespace, item);
367962
+ }
367963
+ async function needsProvisioningOnCreateOrUpdate(cr) {
367861
367964
  const fCrLog = (cr) => `The item ${cr.kind}: ${cr.metadata.name}`;
367862
367965
  // NO STATUS
367863
367966
  if (!('status' in cr) || !('conditions' in cr.status)) {
367864
367967
  operator_src_logger.debug(`The custom resource '${cr.kind}/${cr.metadata.name}' is missing a status and any conditions.`);
367865
- return true;
367968
+ return { needs: true, reason: 'CREATED' };
367866
367969
  }
367867
367970
  // ERROR
367868
367971
  const errCond = getConditionByType(cr.status.conditions, 'ERROR');
367869
367972
  if (errCond && errCond.status === 'True') {
367870
367973
  operator_src_logger.debug(`Skipping the provisioning process for custom resource '${cr.kind}/${cr.metadata.name}' due to a status error.`);
367871
- return false;
367974
+ return { needs: false };
367872
367975
  }
367873
367976
  // PROVISIONED
367874
367977
  const provCond = getConditionByType(cr.status.conditions, 'PROVISIONED');
367875
- if (provCond &&
367876
- provCond.status === 'True' &&
367877
- provCond.observedGeneration >= cr.metadata.generation) {
367878
- operator_src_logger.debug(`The custom resource '${cr.kind}/${cr.metadata.name}' is already provisioned; skipping the process.`);
367879
- return false;
367978
+ if (provCond && provCond.status === 'True') {
367979
+ if (provCond.observedGeneration >= cr.metadata.generation) {
367980
+ operator_src_logger.debug(`The custom resource '${cr.kind}/${cr.metadata.name}' is already provisioned; skipping the process.`);
367981
+ return { needs: false };
367982
+ }
367983
+ else {
367984
+ operator_src_logger.debug(`The custom resource '${cr.kind}/${cr.metadata.name}' is already provisioned but it has spec changes not observed; handling.`);
367985
+ return { needs: true, reason: 'UPDATED' };
367986
+ }
367880
367987
  }
367881
367988
  // DELETED
367882
367989
  const delCond = getConditionByType(cr.status.conditions, 'DELETED');
@@ -367884,16 +367991,16 @@ async function needsProvisioningOnCreate(cr) {
367884
367991
  delCond.status === 'True' &&
367885
367992
  delCond.observedGeneration >= cr.metadata.generation) {
367886
367993
  operator_src_logger.debug(`The custom resource '${cr.kind}/${cr.metadata.name}' has already been deleted; no action is required.`);
367887
- return false;
367994
+ return { needs: false };
367888
367995
  }
367889
367996
  // PROVISIONING
367890
367997
  const provisioningCondition = getConditionByType(cr.status.conditions, 'PROVISIONING');
367891
367998
  if (provisioningCondition && provisioningCondition.status === 'True') {
367892
367999
  operator_src_logger.debug(`The custom resource '${cr.kind}/${cr.metadata.name}' is currently in a provisioning or reprovisioning state.`);
367893
- return true;
368000
+ return { needs: true, reason: 'UPDATED' };
367894
368001
  }
367895
368002
  operator_src_logger.debug(`Skipping the provisioning process for custom resource '${cr.kind}/${cr.metadata.name}' because its current state is not handled.`);
367896
- return false;
368003
+ return { needs: false };
367897
368004
  }
367898
368005
  async function updateSyncTransition(itemPath, reason, lastSyncTime, nextSyncTime, message, status) {
367899
368006
  operator_src_logger.info(`The item at '${itemPath}' transitioned to a new SYNCHRONIZED condition of '${status}'. The reason for the change is '${reason}' with the message: '${message}'.`);
@@ -367915,7 +368022,11 @@ async function updateSyncTransition(itemPath, reason, lastSyncTime, nextSyncTime
367915
368022
  };
367916
368023
  k8sItem.status.conditions = updateConditionByType(k8sItem.status.conditions, 'SYNCHRONIZED', conditionObject);
367917
368024
  const itemParameters = itemPath.split('/');
367918
- await writeStatus(itemParameters[1], itemParameters[0], k8sItem);
368025
+ await writePrioritizedStatus(itemParameters[1], itemParameters[0], k8sItem);
368026
+ }
368027
+ async function writePrioritizedStatus(kind, namespace, item) {
368028
+ setHighPriorityStatus(item);
368029
+ await writeStatus(kind, namespace, item);
367919
368030
  }
367920
368031
  async function updateTransition(itemPath, reason, type, statusValue, message = '', updateStatusOnly = false) {
367921
368032
  operator_src_logger.info(`The item at '${itemPath}' transitioned to a new status of '${statusValue}' (type: '${type}'). The reason for the change is '${reason}' with the message: '${message}'. This was a status-only update: '${updateStatusOnly}'.`);
@@ -367933,7 +368044,7 @@ async function updateTransition(itemPath, reason, type, statusValue, message = '
367933
368044
  }
367934
368045
  k8sItem.status.conditions = updateConditionByType(k8sItem.status.conditions, type, conditionObject);
367935
368046
  const itemParameters = itemPath.split('/');
367936
- await writeStatus(itemParameters[1], itemParameters[0], k8sItem);
368047
+ await writePrioritizedStatus(itemParameters[1], itemParameters[0], k8sItem);
367937
368048
  }
367938
368049
  function getRelevantCondition(conditionList, type) {
367939
368050
  const condition = getConditionByType(conditionList, type);
@@ -368628,6 +368739,7 @@ async function observeKind(pluralKind, namespace, queue, compute) {
368628
368739
  async (item) => {
368629
368740
  operator_src_logger.info(`The informer has detected a new item, '${item.metadata.name}', for '${pluralKind}' in namespace '${namespace}'.`);
368630
368741
  await handleUpsertFinalizer(pluralKind, namespace, item);
368742
+ await upsertInitialStatus(pluralKind, namespace, item);
368631
368743
  const workItem = await inform(pluralKind, item, 'onAdd', getLastWorkItem(pluralKind, lastWorkItems, item));
368632
368744
  syncCtl.addItem(informer_itemPath(pluralKind, item));
368633
368745
  if (workItem) {
@@ -368784,6 +368896,7 @@ function setLastWorkItem(kind, workItemsMap, item, workItem) {
368784
368896
  */
368785
368897
  async function inform(pluralKind, item, op, lastWorkItem = null) {
368786
368898
  let workItem = lastWorkItem;
368899
+ let needed;
368787
368900
  if (getKindFromPlural(pluralKind) !== item.kind)
368788
368901
  return null;
368789
368902
  switch (op) {
@@ -368800,8 +368913,9 @@ async function inform(pluralKind, item, op, lastWorkItem = null) {
368800
368913
  };
368801
368914
  return workItem;
368802
368915
  case 'onRename':
368803
- if (await needsProvisioningOnCreate(item)) {
368804
- operator_src_logger.debug(`The informer is triggering a new provisioning process for the renamed item '${item.kind}/${item.metadata.name}'.`);
368916
+ needed = await needsProvisioningOnCreateOrUpdate(item);
368917
+ if (needed.needs) {
368918
+ operator_src_logger.debug(`The informer is triggering a new provisioning process for the renamed item '${item.kind}/${item.metadata.name}'. Reason: ${needed.reason}.`);
368805
368919
  workItem = {
368806
368920
  operation: OperationType.RENAMED,
368807
368921
  item,
@@ -368825,9 +368939,12 @@ async function inform(pluralKind, item, op, lastWorkItem = null) {
368825
368939
  };
368826
368940
  return workItem;
368827
368941
  case 'onAdd':
368828
- if (await needsProvisioningOnCreate(item)) {
368942
+ needed = await needsProvisioningOnCreateOrUpdate(item);
368943
+ if (needed.needs) {
368829
368944
  workItem = {
368830
- operation: OperationType.CREATED,
368945
+ operation: needed.reason === 'CREATED'
368946
+ ? OperationType.CREATED
368947
+ : OperationType.UPDATED,
368831
368948
  item,
368832
368949
  workStatus: WorkStatus.PENDING,
368833
368950
  onDelete: function () { },
@@ -369408,6 +369525,58 @@ async function deadLetterHandler(workItem) {
369408
369525
  }
369409
369526
  }
369410
369527
 
369528
+ ;// CONCATENATED MODULE: ../operator/src/signals.ts
369529
+
369530
+ const DEFAULT_TERMINATION_GRACE_PERIOD = 2 * 60; // two minutes
369531
+ /**
369532
+ * Initializes process signal handlers used by the operator.
369533
+ *
369534
+ * Currently this sets up handling for `SIGTERM`, using the callback
369535
+ * associated with the `"SIGTERM"` key from the provided {@link CallbacksMap}
369536
+ * to start the shutdown sequence. The returned {@link CallbacksMap} contains
369537
+ * handler-specific callbacks (such as `"FINISH_OK"`) that callers can invoke
369538
+ * to indicate that it is safe for the process to exit.
369539
+ *
369540
+ * @param callbacks A map of signal names to shutdown callbacks. The `"SIGTERM"`
369541
+ * entry (if present) is invoked when a `SIGTERM` signal is received to
369542
+ * perform any necessary cleanup before process termination.
369543
+ * @returns A {@link CallbacksMap} with control callbacks that allow the caller
369544
+ * to signal when shutdown has completed and the process may safely exit.
369545
+ */
369546
+ function initSignalsHandler(callbacks) {
369547
+ operator_src_logger.info('Starting signals handler');
369548
+ const handlerCallbacks = new Map();
369549
+ initSigtermHandler(callbacks.get('SIGTERM'), handlerCallbacks);
369550
+ return handlerCallbacks;
369551
+ }
369552
+ function initSigtermHandler(callback, handlerCallbacks) {
369553
+ const raw_timeout_to_exit = Number(process.env['FIRESTARTR_TERMINATION_GRACE_PERIOD'] ||
369554
+ DEFAULT_TERMINATION_GRACE_PERIOD);
369555
+ const timeout_to_exit = raw_timeout_to_exit - Math.round(Math.min(5, raw_timeout_to_exit * 0.1));
369556
+ // The switch to control if it is safe to exit
369557
+ let finish = false;
369558
+ handlerCallbacks.set('FINISH_OK', () => {
369559
+ finish = true;
369560
+ });
369561
+ process.on('SIGTERM', async () => {
369562
+ operator_src_logger.info('The controller received a SIGTERM signal');
369563
+ // we signal to the callback the sigterm
369564
+ callback();
369565
+ const timeoutCb = setTimeout(() => {
369566
+ operator_src_logger.error('The controller could not shutdown properly. Timeout');
369567
+ process.exit(1);
369568
+ }, timeout_to_exit * 1000);
369569
+ // we wait
369570
+ while (!finish) {
369571
+ await new Promise((resolve) => setTimeout(resolve, 1000));
369572
+ }
369573
+ // all is clear!
369574
+ clearTimeout(timeoutCb);
369575
+ operator_src_logger.info('The controller has properly shutdown. Exiting');
369576
+ process.exit(0);
369577
+ });
369578
+ }
369579
+
369411
369580
  ;// CONCATENATED MODULE: ../operator/src/processItem.ts
369412
369581
 
369413
369582
 
@@ -369415,6 +369584,7 @@ async function deadLetterHandler(workItem) {
369415
369584
 
369416
369585
 
369417
369586
 
369587
+
369418
369588
  const queue = [];
369419
369589
  const WEIGHTS = {
369420
369590
  RENAMED: 15,
@@ -369524,7 +369694,15 @@ async function processItem_loop() {
369524
369694
  .filter((w) => !w.isBlocked)
369525
369695
  .find((w) => w.workStatus === WorkStatus.PENDING);
369526
369696
  loopWorkItemDebug(queue);
369697
+ let podIsTerminating = false;
369698
+ const handlerCallbacks = initSignalsHandler(new Map([['SIGTERM', () => (podIsTerminating = true)]]));
369527
369699
  while (1) {
369700
+ if (podIsTerminating) {
369701
+ operator_src_logger.info('The processor is going to shutdown (pod is terminating)');
369702
+ // we notify the handler that is ok to shutdown
369703
+ handlerCallbacks.get('FINISH_OK')();
369704
+ break;
369705
+ }
369528
369706
  const w = nextWorkItem();
369529
369707
  if (w) {
369530
369708
  const logMessage = `${new Date().toISOString()} : Processing OPERATION: ${w.operation} ITEM: ${w.item.kind}/${w.item.metadata.name}`;
@@ -369984,9 +370162,10 @@ var actions_repository_oidc_subject_claim_customization_template = __nccwpck_req
369984
370162
  function provisionOIDCSubjectClaim(scope, repo, fsGithubRepository) {
369985
370163
  const tfStateKey = `_${fsGithubRepository.getTfStateKey()}-oidc-subject-claim-template`;
369986
370164
  const claimKeys = fsGithubRepository.spec.actions.oidc.includeClaimKeys;
370165
+ const useDefault = fsGithubRepository.spec.actions.oidc.useDefault;
369987
370166
  const config = {
369988
370167
  repository: repo.name,
369989
- useDefault: claimKeys.length < 1,
370168
+ useDefault,
369990
370169
  };
369991
370170
  if (claimKeys.length > 0) {
369992
370171
  config['includeClaimKeys'] = claimKeys;
@@ -371590,19 +371769,19 @@ if (process.env.RUN_PROVISIONER) {
371590
371769
 
371591
371770
 
371592
371771
  const LAST_STATE_PR_ANNOTATION = 'firestartr.dev/last-state-pr';
371593
- async function tryPublishApply(item, planOutput, kind) {
371772
+ async function tryPublishApply(item, planOutput, kind, isSuccess = true) {
371594
371773
  try {
371595
371774
  if (!(LAST_STATE_PR_ANNOTATION in item.metadata.annotations)) {
371596
371775
  operator_src_logger.debug(`The user feedback for the '${kind}/${item.metadata.name}' apply operation could not be published because the last state was not found.`);
371597
371776
  return;
371598
371777
  }
371599
- await publishApply(item, planOutput, kind);
371778
+ await publishApply(item, planOutput, kind, isSuccess);
371600
371779
  }
371601
371780
  catch (e) {
371602
371781
  operator_src_logger.error(`The user feedback for the '${kind}/${item.metadata.name}' apply operation failed to publish due to an error: '${e}'.`);
371603
371782
  }
371604
371783
  }
371605
- async function tryPublishDestroy(item, destroyOutput) {
371784
+ async function tryPublishDestroy(item, destroyOutput, isSuccess = true) {
371606
371785
  let lastPr = null;
371607
371786
  try {
371608
371787
  const { repo, org } = extractPrInfo(item);
@@ -371621,11 +371800,13 @@ async function tryPublishDestroy(item, destroyOutput) {
371621
371800
  return;
371622
371801
  }
371623
371802
  const dividedOutput = github_0.pulls.divideCommentIntoChunks(destroyOutput, 250);
371803
+ const statusEmoji = isSuccess ? '✅' : '❌';
371804
+ const statusText = isSuccess ? 'Succeeded' : 'Failed';
371624
371805
  const commentBodies = dividedOutput.map((commentContent, index) => {
371625
371806
  const isMultiPart = dividedOutput.length > 1;
371626
371807
  const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
371627
371808
  return `<h1>
371628
- <img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Destroy Finished
371809
+ <img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Destroy ${statusText} ${statusEmoji}
371629
371810
  </h1>
371630
371811
  <p><b>TFWorkspace: </b>${item.metadata.name}</p>
371631
371812
 
@@ -371653,14 +371834,16 @@ ${commentContent}
371653
371834
  operator_src_logger.error(`An error occurred while publishing user feedback for item '${item.kind}/${item.metadata.name}': '${e}'.`);
371654
371835
  }
371655
371836
  }
371656
- async function publishApply(item, applyOutput, kind) {
371837
+ async function publishApply(item, applyOutput, kind, isSuccess = true) {
371657
371838
  const { prNumber, repo, org } = extractPrInfo(item);
371658
371839
  const dividedOutput = github_0.pulls.divideCommentIntoChunks(applyOutput, 250);
371840
+ const statusEmoji = isSuccess ? '✅' : '❌';
371841
+ const statusText = isSuccess ? 'Succeeded' : 'Failed';
371659
371842
  const commentBodies = dividedOutput.map((commentContent, index) => {
371660
371843
  const isMultiPart = dividedOutput.length > 1;
371661
371844
  const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
371662
371845
  return `<h1>
371663
- <img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Apply Finished
371846
+ <img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Apply ${statusText} ${statusEmoji}
371664
371847
  </h1>
371665
371848
  <p><b>${kind}: </b>${item.metadata.name}</p>
371666
371849
 
@@ -371735,14 +371918,16 @@ ${message}
371735
371918
  `;
371736
371919
  await github_0.pulls.commentInPR(comment, prNumber, repo, org, 'logs');
371737
371920
  }
371738
- async function publishPlan(item, planOutput, prNumber, repo, org) {
371921
+ async function publishPlan(item, planOutput, prNumber, repo, org, isSuccess = true) {
371739
371922
  try {
371740
371923
  const dividedOutput = github_0.pulls.divideCommentIntoChunks(planOutput, 250);
371924
+ const statusEmoji = isSuccess ? '✅' : '❌';
371925
+ const statusText = isSuccess ? 'Succeeded' : 'Failed';
371741
371926
  const commentBodies = dividedOutput.map((commentContent, index) => {
371742
371927
  const isMultiPart = dividedOutput.length > 1;
371743
371928
  const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
371744
371929
  return `<h1>
371745
- <img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Plan Finished
371930
+ <img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Plan ${statusText} ${statusEmoji}
371746
371931
  </h1>
371747
371932
  <p><b>TFWorkspace: </b>${item.metadata.name}</p>
371748
371933
 
@@ -371980,7 +372165,6 @@ async function* cdktf_markedToDeletion(item, op, handler) {
371980
372165
  : {}),
371981
372166
  });
371982
372167
  const output = destroyOutput.output;
371983
- await tryPublishDestroy(item, output);
371984
372168
  yield {
371985
372169
  item,
371986
372170
  reason: op,
@@ -371993,15 +372177,24 @@ async function* cdktf_markedToDeletion(item, op, handler) {
371993
372177
  if (item.metadata.annotations['firestartr.dev/last-state-pr'] || false) {
371994
372178
  await addDestroyCommitStatus(item, 'success', 'Destroy operation completed', `Terraform Destroy ${item.metadata.name}`);
371995
372179
  }
372180
+ await tryPublishDestroy(item, output, true);
371996
372181
  void handler.success();
371997
372182
  }
371998
372183
  catch (e) {
371999
372184
  error = true;
372185
+ let errorMsg;
372186
+ if (typeof e === 'object' && 'output' in e) {
372187
+ errorMsg = e.output;
372188
+ }
372189
+ else {
372190
+ errorMsg = e;
372191
+ }
372000
372192
  // if there is a current checkRun working
372001
372193
  // we close it with an error
372002
372194
  if (checkRunCtl)
372003
- checkRunCtl.fnOnError(e);
372004
- await handler.writeTerraformOutputInTfResult(item, e);
372195
+ checkRunCtl.fnOnError(errorMsg);
372196
+ await tryPublishDestroy(item, errorMsg, false);
372197
+ await handler.writeTerraformOutputInTfResult(item, errorMsg);
372005
372198
  void handler.error();
372006
372199
  }
372007
372200
  finally {
@@ -372109,7 +372302,6 @@ async function* doApply(item, op, handler) {
372109
372302
  }
372110
372303
  : {}),
372111
372304
  });
372112
- await tryPublishApply(item, applyOutput?.data?.output, item.kind);
372113
372305
  const terraformOutputJson = await provisioner.runTerraform(item, ['output', '-json'], null);
372114
372306
  if (!terraformOutputJson) {
372115
372307
  throw new Error(`Terraform output is empty for ${item.kind}/${item.metadata.name}`);
@@ -372138,7 +372330,8 @@ async function* doApply(item, op, handler) {
372138
372330
  message: 'doApply',
372139
372331
  };
372140
372332
  await handler.writeTerraformOutputInTfResult(item, output);
372141
- handler.success();
372333
+ await tryPublishApply(item, applyOutput?.data?.output, item.kind, true);
372334
+ void handler.success();
372142
372335
  }
372143
372336
  catch (e) {
372144
372337
  error = true;
@@ -373725,7 +373918,6 @@ async function* process_operation_markedToDeletion(item, op, handler) {
373725
373918
  const deps = await handler.resolveReferences();
373726
373919
  const context = buildProvisionerContext(item, deps);
373727
373920
  const destroyOutput = await runTerraformProvisioner(context, 'destroy');
373728
- await tryPublishDestroy(item, destroyOutput);
373729
373921
  yield {
373730
373922
  item,
373731
373923
  reason: op,
@@ -373745,11 +373937,20 @@ async function* process_operation_markedToDeletion(item, op, handler) {
373745
373937
  if (item.metadata.annotations['firestartr.dev/last-state-pr'] || false) {
373746
373938
  await addDestroyCommitStatus(item, 'success', 'Destroy operation completed', `Terraform Destroy ${item.metadata.name}`);
373747
373939
  }
373940
+ await tryPublishDestroy(item, destroyOutput, true);
373748
373941
  void handler.success();
373749
373942
  }
373750
373943
  catch (e) {
373751
373944
  error = true;
373752
- await handler.writeTerraformOutputInTfResult(item, e);
373945
+ let errorMsg;
373946
+ if (typeof e === 'object' && 'output' in e) {
373947
+ errorMsg = e.output;
373948
+ }
373949
+ else {
373950
+ errorMsg = e;
373951
+ }
373952
+ await tryPublishDestroy(item, errorMsg, false);
373953
+ await handler.writeTerraformOutputInTfResult(item, errorMsg);
373753
373954
  if (item.metadata.annotations['firestartr.dev/last-state-pr'] || false) {
373754
373955
  await addDestroyCommitStatus(item, 'failure', 'Destroy operation failed', `Terraform Destroy ${item.metadata.name}`);
373755
373956
  }
@@ -373834,7 +374035,6 @@ async function* process_operation_doApply(item, op, handler) {
373834
374035
  operator_src_logger.info(`The Terraform processor is applying and assessing dependencies for item '${item.kind}/${item.metadata.name}' with dependencies: '${deps}'.`);
373835
374036
  const context = buildProvisionerContext(item, deps);
373836
374037
  const applyOutput = await runTerraformProvisioner(context, 'apply', checkRunCtl);
373837
- await tryPublishApply(item, applyOutput, 'TFWorkspace');
373838
374038
  const terraformOutputJson = await runTerraformProvisioner(context, 'output');
373839
374039
  if (!terraformOutputJson) {
373840
374040
  throw new Error(`Terraform output is empty for ${item.kind}/${item.metadata.name}`);
@@ -373865,17 +374065,25 @@ async function* process_operation_doApply(item, op, handler) {
373865
374065
  message: 'doApply',
373866
374066
  };
373867
374067
  await handler.writeTerraformOutputInTfResult(item, output);
374068
+ await tryPublishApply(item, applyOutput, 'TFWorkspace', true);
373868
374069
  handler.success();
373869
374070
  }
373870
374071
  catch (e) {
373871
374072
  error = true;
373872
- checkRunCtl.fnOnError(e);
374073
+ let errorMsg;
374074
+ if (typeof e === 'object' && 'output' in e) {
374075
+ errorMsg = e.output;
374076
+ }
374077
+ else {
374078
+ errorMsg = e;
374079
+ }
374080
+ checkRunCtl.fnOnError(errorMsg);
373873
374081
  console.error(e);
373874
- await tryPublishApply(item, e, 'TFWorkspace');
374082
+ await tryPublishApply(item, errorMsg, 'TFWorkspace', false);
373875
374083
  operator_src_logger.error(`The Terraform processor encountered an error during operation '${op}' for item '${item.kind}/${item.metadata.name}': '${e}'.`);
373876
374084
  handler.error();
373877
- if (e) {
373878
- await handler.writeTerraformOutputInTfResult(item, e);
374085
+ if (errorMsg) {
374086
+ await handler.writeTerraformOutputInTfResult(item, errorMsg);
373879
374087
  }
373880
374088
  }
373881
374089
  finally {
@@ -374122,7 +374330,6 @@ function clearLocalTfProjects() {
374122
374330
  external_fs_.rmSync(TF_PROJECTS_PATH, { recursive: true, force: true });
374123
374331
  }
374124
374332
  function getErrorOutputMessage(cr, key, ref) {
374125
- const result = '';
374126
374333
  if (cr.spec.source === 'Remote') {
374127
374334
  return `
374128
374335
 
@@ -374341,8 +374548,6 @@ async function* doPlanPlainTextFormat(item, op, handler, action) {
374341
374548
  await addPlanStatusCheck(item.metadata.annotations['firestartr.dev/last-state-pr'], 'Terraform plan in progress...');
374342
374549
  }
374343
374550
  const tfPlanOutput = await runTerraformProvisioner(context, action);
374344
- const { prNumber, repo, org } = extractPrInfo(item, 'firestartr.dev/pull-request-plan');
374345
- await publishPlan(item, tfPlanOutput, prNumber, repo, org);
374346
374551
  yield {
374347
374552
  item,
374348
374553
  reason: op,
@@ -374367,11 +374572,13 @@ async function* doPlanPlainTextFormat(item, op, handler, action) {
374367
374572
  if (item.metadata.annotations['firestartr.dev/last-state-pr'] || false) {
374368
374573
  await addPlanStatusCheck(item.metadata.annotations['firestartr.dev/last-state-pr'], tfPlanOutput, 'completed');
374369
374574
  }
374575
+ const { prNumber, repo, org } = extractPrInfo(item, 'firestartr.dev/pull-request-plan');
374576
+ await publishPlan(item, tfPlanOutput, prNumber, repo, org, true);
374370
374577
  }
374371
374578
  catch (e) {
374372
374579
  error = true;
374373
374580
  const { prNumber, repo, org } = extractPrInfo(item, 'firestartr.dev/pull-request-plan');
374374
- await publishPlan(item, JSON.stringify(e), prNumber, repo, org);
374581
+ await publishPlan(item, JSON.stringify(e), prNumber, repo, org, false);
374375
374582
  operator_src_logger.error('TFWORKSPACE_PROCESSOR_PLAN_OBSERVING_ERROR', {
374376
374583
  metadata: { item, error: e },
374377
374584
  });
@@ -375977,6 +376184,10 @@ const crs_analyzerSubcommand = {
375977
376184
  },
375978
376185
  };
375979
376186
 
376187
+ ;// CONCATENATED MODULE: ./package.json
376188
+ const package_namespaceObject = JSON.parse('{"i8":"1.55.0-snapshot-2"}');
376189
+ ;// CONCATENATED MODULE: ../../package.json
376190
+ const package_namespaceObject_1 = {"i8":"1.54.0"};
375980
376191
  ;// CONCATENATED MODULE: ./src/subcommands/index.ts
375981
376192
 
375982
376193
 
@@ -375985,6 +376196,8 @@ const crs_analyzerSubcommand = {
375985
376196
 
375986
376197
 
375987
376198
 
376199
+
376200
+
375988
376201
  const SUBCOMMANDS = {
375989
376202
  import: importSubcommand,
375990
376203
  importer: importSubcommand,
@@ -376022,6 +376235,9 @@ function showSubcommandsHelp() {
376022
376235
  console.log('AVAILABLE COMMANDS');
376023
376236
  console.table(commandsList);
376024
376237
  }
376238
+ function showCliVersion() {
376239
+ console.log(`CLI Version: ${package_namespaceObject.i8}. Firestartr Version: ${package_namespaceObject_1.i8}`);
376240
+ }
376025
376241
 
376026
376242
  ;// CONCATENATED MODULE: ./src/command_line.ts
376027
376243
 
@@ -376042,6 +376258,9 @@ class CommandLine {
376042
376258
  case 'help':
376043
376259
  showSubcommandsHelp();
376044
376260
  break;
376261
+ case 'version':
376262
+ showCliVersion();
376263
+ break;
376045
376264
  default: {
376046
376265
  // Get the subcommand data
376047
376266
  const subcommandData = validateAndGetSubcommand(subcommand);
@@ -1,3 +1,4 @@
1
1
  import { Subcommand } from '../types';
2
2
  export declare function validateAndGetSubcommand(name: string): Subcommand;
3
3
  export declare function showSubcommandsHelp(): void;
4
+ export declare function showCliVersion(): void;
@@ -66,6 +66,9 @@ declare const _default: {
66
66
  $arg: {
67
67
  type: string;
68
68
  };
69
+ $template: {
70
+ type: string;
71
+ };
69
72
  $default: {
70
73
  type: string[];
71
74
  };
@@ -0,0 +1 @@
1
+ export declare function setHighPriorityStatus(item: any): void;
@@ -0,0 +1,17 @@
1
+ export type CallbacksMap = Map<string, () => void>;
2
+ /**
3
+ * Initializes process signal handlers used by the operator.
4
+ *
5
+ * Currently this sets up handling for `SIGTERM`, using the callback
6
+ * associated with the `"SIGTERM"` key from the provided {@link CallbacksMap}
7
+ * to start the shutdown sequence. The returned {@link CallbacksMap} contains
8
+ * handler-specific callbacks (such as `"FINISH_OK"`) that callers can invoke
9
+ * to indicate that it is safe for the process to exit.
10
+ *
11
+ * @param callbacks A map of signal names to shutdown callbacks. The `"SIGTERM"`
12
+ * entry (if present) is invoked when a `SIGTERM` signal is received to
13
+ * perform any necessary cleanup before process termination.
14
+ * @returns A {@link CallbacksMap} with control callbacks that allow the caller
15
+ * to signal when shutdown has completed and the process may safely exit.
16
+ */
17
+ export declare function initSignalsHandler(callbacks: CallbacksMap): CallbacksMap;
@@ -1,4 +1,10 @@
1
- export declare function needsProvisioningOnCreate(cr: any): Promise<boolean>;
1
+ export type NeedsCreationOrUpdate = {
2
+ needs: boolean;
3
+ reason?: string;
4
+ };
5
+ export declare function upsertInitialStatus(pluralKind: string, namespace: string, item: any): Promise<void>;
6
+ export declare function needsProvisioningOnCreateOrUpdate(cr: any): Promise<NeedsCreationOrUpdate>;
2
7
  export declare function updateSyncTransition(itemPath: string, reason: string, lastSyncTime: string, nextSyncTime: string, message: string, status: string): Promise<void>;
8
+ export declare function writePrioritizedStatus(kind: string, namespace: string, item: any): Promise<void>;
3
9
  export declare function updateTransition(itemPath: string, reason: string, type: string, statusValue: string, message?: string, updateStatusOnly?: boolean): Promise<void>;
4
10
  export declare function getConditionByType(conditionList: Array<any>, type: string): any;
@@ -1,6 +1,6 @@
1
- export declare function tryPublishApply(item: any, planOutput: string, kind: string): Promise<void>;
2
- export declare function tryPublishDestroy(item: any, destroyOutput: string): Promise<void>;
3
- export declare function publishApply(item: any, applyOutput: string, kind: string): Promise<void>;
1
+ export declare function tryPublishApply(item: any, planOutput: string, kind: string, isSuccess?: boolean): Promise<void>;
2
+ export declare function tryPublishDestroy(item: any, destroyOutput: string, isSuccess?: boolean): Promise<void>;
3
+ export declare function publishApply(item: any, applyOutput: string, kind: string, isSuccess?: boolean): Promise<void>;
4
4
  export declare function tryCreateErrorSummary(title: string, errorMsg: string): string;
5
5
  export declare function extractPrInfo(item: any, annotation?: 'firestartr.dev/last-state-pr' | 'firestartr.dev/pull-request-plan'): {
6
6
  prNumber: number;
@@ -9,4 +9,4 @@ export declare function extractPrInfo(item: any, annotation?: 'firestartr.dev/la
9
9
  };
10
10
  export declare function tryPublishError(item: any, reason: string, message: string): Promise<void>;
11
11
  export declare function publishError(item: any, reason: string, message: string): Promise<void>;
12
- export declare function publishPlan(item: any, planOutput: string, prNumber: number, repo: string, org: string): Promise<void>;
12
+ export declare function publishPlan(item: any, planOutput: string, prNumber: number, repo: string, org: string, isSuccess?: boolean): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firestartr/cli",
3
- "version": "1.55.0-snapshot-0",
3
+ "version": "1.55.0-snapshot-2",
4
4
  "private": false,
5
5
  "description": "Commandline tool",
6
6
  "main": "build/main.js",