@firestartr/cli 1.53.0-snapshot-4 → 1.53.0-snapshot-6
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 +586 -238
- package/build/packages/cdk8s_renderer/src/claims/base/schemas/common-meta.schema.d.ts +47 -0
- package/build/packages/cdk8s_renderer/src/claims/base/schemas/index.d.ts +73 -34
- package/build/packages/cdk8s_renderer/src/claims/github/component.schema.d.ts +6 -0
- package/build/packages/cdk8s_renderer/src/claims/github/group.schema.d.ts +6 -0
- package/build/packages/cdk8s_renderer/src/claims/github/index.d.ts +24 -0
- package/build/packages/cdk8s_renderer/src/claims/github/orgwebhook.schema.d.ts +6 -0
- package/build/packages/cdk8s_renderer/src/claims/github/user.schema.d.ts +6 -0
- package/build/packages/cdk8s_renderer/src/claims/tfworkspaces/index.d.ts +2 -34
- package/build/packages/cdk8s_renderer/src/claims/tfworkspaces/terraform.schema.d.ts +2 -34
- package/build/packages/github/index.d.ts +2 -0
- package/build/packages/github/src/sticky_comment.d.ts +20 -6
- package/build/packages/operator/src/utils/index.d.ts +7 -0
- package/build/packages/provisioner/src/resources/resource.d.ts +4 -1
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -354119,7 +354119,7 @@ async function getUserInfo(name) {
|
|
|
354119
354119
|
});
|
|
354120
354120
|
|
|
354121
354121
|
;// CONCATENATED MODULE: ../github/src/sticky_comment.ts
|
|
354122
|
-
|
|
354122
|
+
const MAX_MULTIPART_COMMENTS = 100;
|
|
354123
354123
|
const locks = new Map();
|
|
354124
354124
|
async function withLock(key, fn) {
|
|
354125
354125
|
const prev = locks.get(key) ?? Promise.resolve();
|
|
@@ -354140,116 +354140,147 @@ async function withLock(key, fn) {
|
|
|
354140
354140
|
function escapeForRegex(s) {
|
|
354141
354141
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
354142
354142
|
}
|
|
354143
|
-
function
|
|
354144
|
-
return new RegExp(`<!-- sticky-id:${escapeForRegex(
|
|
354143
|
+
function multiPartIdRegex(baseKind, index) {
|
|
354144
|
+
return new RegExp(`<!-- sticky-id:${escapeForRegex(baseKind)}\\[${index}\\]=(\\d+) -->`);
|
|
354145
354145
|
}
|
|
354146
|
-
function
|
|
354147
|
-
return `<!-- sticky-id:${
|
|
354146
|
+
function multiPartIdMarker(baseKind, index, id) {
|
|
354147
|
+
return `<!-- sticky-id:${baseKind}[${index}]=${id} -->`;
|
|
354148
354148
|
}
|
|
354149
|
-
function
|
|
354150
|
-
return `<!-- sticky:kind=${
|
|
354149
|
+
function multiPartBodyMarker(baseKind, index) {
|
|
354150
|
+
return `<!-- sticky:kind=${baseKind}[${index}] -->`;
|
|
354151
354151
|
}
|
|
354152
|
-
|
|
354152
|
+
// ---- Helpers for reducing API calls and duplication ----
|
|
354153
|
+
async function getPrBody(octokit, owner, repo, pr) {
|
|
354153
354154
|
const prResp = await octokit.rest.pulls.get({ owner, repo, pull_number: pr });
|
|
354154
|
-
|
|
354155
|
-
|
|
354156
|
-
|
|
354157
|
-
|
|
354158
|
-
}
|
|
354159
|
-
async function writeStickyIdToPrBody(octokit, owner, repo, pr, kind, id) {
|
|
354160
|
-
const get = await octokit.rest.pulls.get({ owner, repo, pull_number: pr });
|
|
354161
|
-
const body = get.data?.body ?? '';
|
|
354162
|
-
const rx = prIdRegex(kind);
|
|
354163
|
-
const marker = prIdMarker(kind, id);
|
|
354164
|
-
github_src_logger.info(`writeStickyIdToPrBody: owner=${owner} repo=${repo} pr=${pr} kind=${kind} id=${id}`);
|
|
354165
|
-
const next = rx.test(body)
|
|
354166
|
-
? body.replace(rx, marker)
|
|
354167
|
-
: body
|
|
354168
|
-
? `${body}\n${marker}`
|
|
354169
|
-
: marker;
|
|
354170
|
-
if (next !== body) {
|
|
354155
|
+
return prResp.data?.body ?? '';
|
|
354156
|
+
}
|
|
354157
|
+
async function updatePrBodyIfChanged(octokit, owner, repo, pr, newBody, oldBody) {
|
|
354158
|
+
if (newBody !== oldBody) {
|
|
354171
354159
|
await octokit.rest.pulls.update({
|
|
354172
354160
|
owner,
|
|
354173
354161
|
repo,
|
|
354174
354162
|
pull_number: pr,
|
|
354175
|
-
body:
|
|
354163
|
+
body: newBody,
|
|
354176
354164
|
});
|
|
354177
354165
|
}
|
|
354178
354166
|
}
|
|
354179
|
-
async function
|
|
354180
|
-
|
|
354181
|
-
|
|
354182
|
-
|
|
354183
|
-
|
|
354184
|
-
|
|
354185
|
-
|
|
354186
|
-
|
|
354187
|
-
|
|
354188
|
-
|
|
354189
|
-
|
|
354190
|
-
|
|
354191
|
-
|
|
354192
|
-
|
|
354193
|
-
|
|
354194
|
-
|
|
354167
|
+
async function updateComment(octokit, owner, repo, commentId, body) {
|
|
354168
|
+
await octokit.rest.issues.updateComment({
|
|
354169
|
+
owner,
|
|
354170
|
+
repo,
|
|
354171
|
+
comment_id: commentId,
|
|
354172
|
+
body,
|
|
354173
|
+
});
|
|
354174
|
+
}
|
|
354175
|
+
async function createCommentAndGetId(octokit, owner, repo, pullNumber, body) {
|
|
354176
|
+
const created = await octokit.rest.issues.createComment({
|
|
354177
|
+
owner,
|
|
354178
|
+
repo,
|
|
354179
|
+
issue_number: pullNumber,
|
|
354180
|
+
body,
|
|
354181
|
+
});
|
|
354182
|
+
return created?.data?.id;
|
|
354183
|
+
}
|
|
354184
|
+
async function readMultiPartStickyIdsFromPrBody(octokit, owner, repo, pr, baseKind) {
|
|
354185
|
+
const body = await getPrBody(octokit, owner, repo, pr);
|
|
354186
|
+
const ids = new Map();
|
|
354187
|
+
// Find all indexed markers for this base kind
|
|
354188
|
+
// Break early once we encounter a gap (most comments are sequentially indexed)
|
|
354189
|
+
let consecutiveGaps = 0;
|
|
354190
|
+
for (let i = 0; i < MAX_MULTIPART_COMMENTS; i++) {
|
|
354191
|
+
const m = body.match(multiPartIdRegex(baseKind, i));
|
|
354192
|
+
if (m) {
|
|
354193
|
+
ids.set(i, Number(m[1]));
|
|
354194
|
+
consecutiveGaps = 0;
|
|
354195
|
+
}
|
|
354196
|
+
else {
|
|
354197
|
+
consecutiveGaps++;
|
|
354198
|
+
// Stop after finding 5 consecutive gaps (reasonable buffer for sparse indices)
|
|
354199
|
+
if (consecutiveGaps >= 5)
|
|
354200
|
+
break;
|
|
354195
354201
|
}
|
|
354196
|
-
|
|
354197
|
-
|
|
354198
|
-
|
|
354199
|
-
|
|
354200
|
-
|
|
354201
|
-
|
|
354202
|
-
|
|
354203
|
-
|
|
354204
|
-
|
|
354205
|
-
|
|
354206
|
-
|
|
354207
|
-
|
|
354208
|
-
|
|
354209
|
-
|
|
354210
|
-
|
|
354211
|
-
|
|
354212
|
-
|
|
354213
|
-
|
|
354214
|
-
|
|
354215
|
-
|
|
354216
|
-
|
|
354217
|
-
|
|
354218
|
-
|
|
354219
|
-
|
|
354220
|
-
|
|
354221
|
-
|
|
354222
|
-
|
|
354223
|
-
|
|
354224
|
-
|
|
354225
|
-
|
|
354226
|
-
|
|
354227
|
-
|
|
354228
|
-
|
|
354229
|
-
|
|
354230
|
-
|
|
354231
|
-
|
|
354232
|
-
|
|
354233
|
-
|
|
354202
|
+
}
|
|
354203
|
+
return ids;
|
|
354204
|
+
}
|
|
354205
|
+
async function writeMultiPartStickyIdsToPrBody(octokit, owner, repo, pr, baseKind, ids) {
|
|
354206
|
+
const oldBody = await getPrBody(octokit, owner, repo, pr);
|
|
354207
|
+
let body = oldBody;
|
|
354208
|
+
// Determine the highest index we need to clean up
|
|
354209
|
+
// Add a small buffer to catch any stragglers from previous runs
|
|
354210
|
+
const maxIndex = ids.size > 0 ? Math.max(...ids.keys()) + 5 : 5;
|
|
354211
|
+
// Remove all old markers for this base kind (only up to needed range)
|
|
354212
|
+
for (let i = 0; i <= maxIndex && i < MAX_MULTIPART_COMMENTS; i++) {
|
|
354213
|
+
const rx = multiPartIdRegex(baseKind, i);
|
|
354214
|
+
body = body.replace(rx, '');
|
|
354215
|
+
}
|
|
354216
|
+
// Add all new markers
|
|
354217
|
+
let markers = '';
|
|
354218
|
+
ids.forEach((id, index) => {
|
|
354219
|
+
markers += `${multiPartIdMarker(baseKind, index, id)}\n`;
|
|
354220
|
+
});
|
|
354221
|
+
// Clean up extra newlines
|
|
354222
|
+
markers = markers.trim();
|
|
354223
|
+
let next = body.trim();
|
|
354224
|
+
if (markers) {
|
|
354225
|
+
next = next ? `${next}\n${markers}` : markers;
|
|
354226
|
+
}
|
|
354227
|
+
await updatePrBodyIfChanged(octokit, owner, repo, pr, next, oldBody);
|
|
354228
|
+
}
|
|
354229
|
+
/**
|
|
354230
|
+
* Upsert sticky comments for one or more parts.
|
|
354231
|
+
* Always uses indexed kinds (e.g., 'logs[0]', 'logs[1]', etc.) for consistency.
|
|
354232
|
+
*
|
|
354233
|
+
* Behavior:
|
|
354234
|
+
* - Single part (bodies.length === 1): Uses indexed kind like 'logs[0]'
|
|
354235
|
+
* - Multiple parts (bodies.length > 1): Uses indexed kinds 'logs[0]', 'logs[1]', etc.
|
|
354236
|
+
* - Non-last parts include a note about continuation
|
|
354237
|
+
* - Unused parts (from previous runs) are updated with a placeholder message
|
|
354238
|
+
* - Never deletes comments
|
|
354239
|
+
*/
|
|
354240
|
+
async function upsertMultiPartStickyComments(octokit, params) {
|
|
354241
|
+
const { owner, repo, pullNumber, baseKind, bodies } = params;
|
|
354242
|
+
// Always use indexed kinds (e.g., 'logs[0]', 'logs[1]', etc.)
|
|
354243
|
+
const lockKey = `${owner}/${repo}#${pullNumber}#${baseKind}[multi]`;
|
|
354244
|
+
const totalParts = bodies.length;
|
|
354245
|
+
await withLock(lockKey, async () => {
|
|
354246
|
+
// Read existing comment IDs for this base kind
|
|
354247
|
+
const existingIds = await readMultiPartStickyIdsFromPrBody(octokit, owner, repo, pullNumber, baseKind);
|
|
354248
|
+
const newIds = new Map();
|
|
354249
|
+
// Process each part of the new content
|
|
354250
|
+
for (let partIndex = 0; partIndex < totalParts; partIndex++) {
|
|
354251
|
+
const body = bodies[partIndex];
|
|
354252
|
+
const isLastPart = partIndex === totalParts - 1;
|
|
354253
|
+
// Build the full comment body with continuation notice for non-last parts
|
|
354254
|
+
let fullBody = body;
|
|
354255
|
+
if (!isLastPart) {
|
|
354256
|
+
fullBody += `\n\n📝 **Note:** This is part ${partIndex + 1} of ${totalParts}. See next comment for continuation.`;
|
|
354257
|
+
}
|
|
354258
|
+
fullBody += `\n\n${multiPartBodyMarker(baseKind, partIndex)}`;
|
|
354259
|
+
const existingId = existingIds.get(partIndex);
|
|
354260
|
+
if (existingId) {
|
|
354261
|
+
// Update existing comment
|
|
354262
|
+
await updateComment(octokit, owner, repo, existingId, fullBody);
|
|
354263
|
+
newIds.set(partIndex, existingId);
|
|
354264
|
+
}
|
|
354265
|
+
else {
|
|
354266
|
+
// Create new comment
|
|
354267
|
+
const newId = await createCommentAndGetId(octokit, owner, repo, pullNumber, fullBody);
|
|
354268
|
+
if (newId !== undefined) {
|
|
354269
|
+
newIds.set(partIndex, newId);
|
|
354234
354270
|
}
|
|
354235
|
-
return;
|
|
354236
354271
|
}
|
|
354237
354272
|
}
|
|
354238
|
-
|
|
354239
|
-
|
|
354240
|
-
|
|
354241
|
-
|
|
354242
|
-
|
|
354243
|
-
|
|
354244
|
-
|
|
354245
|
-
|
|
354246
|
-
issue_number: pullNumber,
|
|
354247
|
-
body: fullBody,
|
|
354248
|
-
});
|
|
354249
|
-
const newId = created?.data?.id;
|
|
354250
|
-
if (newId !== undefined) {
|
|
354251
|
-
await writeStickyIdToPrBody(octokit, owner, repo, pullNumber, kind, newId);
|
|
354273
|
+
// Handle old comments that are no longer needed (when new content is shorter)
|
|
354274
|
+
// Update them with a placeholder message instead of deleting, but keep their IDs for potential reuse
|
|
354275
|
+
for (const [oldIndex, oldId] of existingIds) {
|
|
354276
|
+
if (!newIds.has(oldIndex)) {
|
|
354277
|
+
const placeholderBody = `⚠️ This comment is no longer in use as the log output has been reduced.\n\n${multiPartBodyMarker(baseKind, oldIndex)}`;
|
|
354278
|
+
await updateComment(octokit, owner, repo, oldId, placeholderBody);
|
|
354279
|
+
newIds.set(oldIndex, oldId); // Preserve ID in PR body for reuse
|
|
354280
|
+
}
|
|
354252
354281
|
}
|
|
354282
|
+
// Update PR body with all comment IDs
|
|
354283
|
+
await writeMultiPartStickyIdsToPrBody(octokit, owner, repo, pullNumber, baseKind, newIds);
|
|
354253
354284
|
});
|
|
354254
354285
|
}
|
|
354255
354286
|
|
|
@@ -354263,12 +354294,12 @@ async function commentInPR(comment, pr_number, repo, owner = 'prefapp', stickyKi
|
|
|
354263
354294
|
github_src_logger.info(`Commenting ${comment} in PR ${pr_number} of ${owner}/${repo}`);
|
|
354264
354295
|
const octokit = await getOctokitForOrg(owner);
|
|
354265
354296
|
if (stickyKind) {
|
|
354266
|
-
await
|
|
354297
|
+
await upsertMultiPartStickyComments(octokit, {
|
|
354267
354298
|
owner,
|
|
354268
354299
|
repo,
|
|
354269
354300
|
pullNumber: pr_number,
|
|
354270
|
-
|
|
354271
|
-
|
|
354301
|
+
baseKind: stickyKind,
|
|
354302
|
+
bodies: [comment],
|
|
354272
354303
|
});
|
|
354273
354304
|
}
|
|
354274
354305
|
else {
|
|
@@ -354751,12 +354782,12 @@ class GithubCheckRun {
|
|
|
354751
354782
|
return;
|
|
354752
354783
|
const base = this.checkRunComment ?? '';
|
|
354753
354784
|
const linkLine = base ? `${base}[here](${link})` : `[here](${link})`;
|
|
354754
|
-
await
|
|
354785
|
+
await upsertMultiPartStickyComments(this.octokit, {
|
|
354755
354786
|
owner: this.owner,
|
|
354756
354787
|
repo: this.repo,
|
|
354757
354788
|
pullNumber: this.pullNumber,
|
|
354758
|
-
|
|
354759
|
-
|
|
354789
|
+
baseKind: `check-run:${this.name}`,
|
|
354790
|
+
bodies: [linkLine],
|
|
354760
354791
|
});
|
|
354761
354792
|
}
|
|
354762
354793
|
}
|
|
@@ -354854,6 +354885,7 @@ async function encryptRepoSecret(owner, repo, section, plaintextValue) {
|
|
|
354854
354885
|
|
|
354855
354886
|
|
|
354856
354887
|
|
|
354888
|
+
|
|
354857
354889
|
/* harmony default export */ const github_0 = ({
|
|
354858
354890
|
org: organization,
|
|
354859
354891
|
repo: repository,
|
|
@@ -354870,6 +354902,7 @@ async function encryptRepoSecret(owner, repo, section, plaintextValue) {
|
|
|
354870
354902
|
feedback: {
|
|
354871
354903
|
createCheckRun: createCheckRun,
|
|
354872
354904
|
CheckRun: CheckRun,
|
|
354905
|
+
upsertMultiPartStickyComments: upsertMultiPartStickyComments,
|
|
354873
354906
|
},
|
|
354874
354907
|
encryption: {
|
|
354875
354908
|
encryptRepoSecret: encryptRepoSecret,
|
|
@@ -356774,6 +356807,10 @@ class SyncerInitializer extends InitializerPatches {
|
|
|
356774
356807
|
const provider = helperCTX(ctx).provider;
|
|
356775
356808
|
return claim.providers[provider].sync || {};
|
|
356776
356809
|
}
|
|
356810
|
+
function policyInfo(ctx) {
|
|
356811
|
+
const provider = helperCTX(ctx).provider;
|
|
356812
|
+
return claim.providers[provider].policy;
|
|
356813
|
+
}
|
|
356777
356814
|
return [
|
|
356778
356815
|
{
|
|
356779
356816
|
validate(cr) {
|
|
@@ -356804,21 +356841,23 @@ class SyncerInitializer extends InitializerPatches {
|
|
|
356804
356841
|
}
|
|
356805
356842
|
},
|
|
356806
356843
|
apply(cr) {
|
|
356844
|
+
cr.metadata.annotations = cr.metadata.annotations || {};
|
|
356845
|
+
// Apply general policy annotation
|
|
356846
|
+
if (policyInfo(this)) {
|
|
356847
|
+
cr.metadata.annotations['firestartr.dev/policy'] =
|
|
356848
|
+
policyInfo(this);
|
|
356849
|
+
}
|
|
356807
356850
|
if (syncInfo(this).enabled) {
|
|
356808
|
-
cr.metadata.annotations = cr.metadata.annotations || {};
|
|
356809
356851
|
cr.metadata.annotations['firestartr.dev/sync-enabled'] = 'true';
|
|
356810
356852
|
if (syncInfo(this).period) {
|
|
356811
|
-
cr.metadata.annotations = cr.metadata.annotations || {};
|
|
356812
356853
|
cr.metadata.annotations['firestartr.dev/sync-period'] =
|
|
356813
356854
|
syncInfo(this).period;
|
|
356814
356855
|
}
|
|
356815
356856
|
if (syncInfo(this).policy) {
|
|
356816
|
-
cr.metadata.annotations = cr.metadata.annotations || {};
|
|
356817
356857
|
cr.metadata.annotations['firestartr.dev/sync-policy'] =
|
|
356818
356858
|
syncInfo(this).policy;
|
|
356819
356859
|
}
|
|
356820
356860
|
if (syncInfo(this).schedule) {
|
|
356821
|
-
cr.metadata.annotations = cr.metadata.annotations || {};
|
|
356822
356861
|
cr.metadata.annotations[SYNC_SCHED_ANNOTATION] =
|
|
356823
356862
|
syncInfo(this).schedule;
|
|
356824
356863
|
cr.metadata.annotations[SYNC_SCHED_TIMEZONE_ANNOTATION] =
|
|
@@ -357539,6 +357578,69 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357539
357578
|
},
|
|
357540
357579
|
additionalProperties: false,
|
|
357541
357580
|
},
|
|
357581
|
+
PolicyType: {
|
|
357582
|
+
$id: 'firestartr.dev://common/PolicyType',
|
|
357583
|
+
type: 'string',
|
|
357584
|
+
description: 'Policy for resource management',
|
|
357585
|
+
enum: [
|
|
357586
|
+
'apply',
|
|
357587
|
+
'create-only',
|
|
357588
|
+
'create-update-only',
|
|
357589
|
+
'full-control',
|
|
357590
|
+
'observe',
|
|
357591
|
+
'observe-only',
|
|
357592
|
+
],
|
|
357593
|
+
},
|
|
357594
|
+
SyncConfig: {
|
|
357595
|
+
$id: 'firestartr.dev://common/SyncConfig',
|
|
357596
|
+
type: 'object',
|
|
357597
|
+
description: 'Sync configuration for resources',
|
|
357598
|
+
properties: {
|
|
357599
|
+
enabled: {
|
|
357600
|
+
type: 'boolean',
|
|
357601
|
+
description: 'Enable periodic sync operations',
|
|
357602
|
+
},
|
|
357603
|
+
period: {
|
|
357604
|
+
type: 'string',
|
|
357605
|
+
pattern: '^[0-9]+[smhd]$',
|
|
357606
|
+
description: 'Sync period (e.g., 1h, 30m, 5s). Must be enabled without schedule.',
|
|
357607
|
+
},
|
|
357608
|
+
schedule: {
|
|
357609
|
+
type: 'string',
|
|
357610
|
+
description: 'Cron schedule for sync operations. Must be enabled without period.',
|
|
357611
|
+
},
|
|
357612
|
+
schedule_timezone: {
|
|
357613
|
+
type: 'string',
|
|
357614
|
+
description: 'Timezone for cron schedule (e.g., UTC, America/New_York)',
|
|
357615
|
+
},
|
|
357616
|
+
policy: {
|
|
357617
|
+
type: 'string',
|
|
357618
|
+
description: 'Policy for sync operations (apply or observe)',
|
|
357619
|
+
},
|
|
357620
|
+
},
|
|
357621
|
+
additionalProperties: false,
|
|
357622
|
+
required: ['enabled'],
|
|
357623
|
+
oneOf: [
|
|
357624
|
+
{
|
|
357625
|
+
required: ['period'],
|
|
357626
|
+
},
|
|
357627
|
+
{
|
|
357628
|
+
required: ['schedule'],
|
|
357629
|
+
},
|
|
357630
|
+
{
|
|
357631
|
+
not: {
|
|
357632
|
+
anyOf: [
|
|
357633
|
+
{
|
|
357634
|
+
required: ['period'],
|
|
357635
|
+
},
|
|
357636
|
+
{
|
|
357637
|
+
required: ['schedule'],
|
|
357638
|
+
},
|
|
357639
|
+
],
|
|
357640
|
+
},
|
|
357641
|
+
},
|
|
357642
|
+
],
|
|
357643
|
+
},
|
|
357542
357644
|
},
|
|
357543
357645
|
});
|
|
357544
357646
|
|
|
@@ -357899,6 +358001,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357899
358001
|
{
|
|
357900
358002
|
type: 'object',
|
|
357901
358003
|
properties: {
|
|
358004
|
+
policy: {
|
|
358005
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358006
|
+
},
|
|
357902
358007
|
privacy: {
|
|
357903
358008
|
type: 'string',
|
|
357904
358009
|
enum: ['closed', 'secret'],
|
|
@@ -357909,6 +358014,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357909
358014
|
org: {
|
|
357910
358015
|
type: 'string',
|
|
357911
358016
|
},
|
|
358017
|
+
sync: {
|
|
358018
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358019
|
+
},
|
|
357912
358020
|
},
|
|
357913
358021
|
required: ['org', 'privacy'],
|
|
357914
358022
|
},
|
|
@@ -357934,6 +358042,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357934
358042
|
{
|
|
357935
358043
|
type: 'object',
|
|
357936
358044
|
properties: {
|
|
358045
|
+
policy: {
|
|
358046
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358047
|
+
},
|
|
357937
358048
|
role: {
|
|
357938
358049
|
type: 'string',
|
|
357939
358050
|
enum: ['admin', 'member'],
|
|
@@ -357941,6 +358052,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357941
358052
|
org: {
|
|
357942
358053
|
type: 'string',
|
|
357943
358054
|
},
|
|
358055
|
+
sync: {
|
|
358056
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358057
|
+
},
|
|
357944
358058
|
},
|
|
357945
358059
|
required: ['org', 'role'],
|
|
357946
358060
|
},
|
|
@@ -357965,6 +358079,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357965
358079
|
{
|
|
357966
358080
|
type: 'object',
|
|
357967
358081
|
properties: {
|
|
358082
|
+
policy: {
|
|
358083
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358084
|
+
},
|
|
357968
358085
|
org: {
|
|
357969
358086
|
type: 'string',
|
|
357970
358087
|
description: 'The github organization name',
|
|
@@ -357973,6 +358090,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357973
358090
|
type: 'string',
|
|
357974
358091
|
enum: ['private', 'public', 'internal'],
|
|
357975
358092
|
},
|
|
358093
|
+
sync: {
|
|
358094
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358095
|
+
},
|
|
357976
358096
|
features: {
|
|
357977
358097
|
type: 'array',
|
|
357978
358098
|
items: {
|
|
@@ -358008,6 +358128,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
358008
358128
|
{
|
|
358009
358129
|
type: 'object',
|
|
358010
358130
|
properties: {
|
|
358131
|
+
policy: {
|
|
358132
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358133
|
+
},
|
|
358011
358134
|
orgName: {
|
|
358012
358135
|
type: 'string',
|
|
358013
358136
|
description: 'Organization name on GitHub',
|
|
@@ -358041,6 +358164,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
358041
358164
|
},
|
|
358042
358165
|
required: ['url', 'contentType', 'events', 'secretRef'],
|
|
358043
358166
|
},
|
|
358167
|
+
sync: {
|
|
358168
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358169
|
+
},
|
|
358044
358170
|
},
|
|
358045
358171
|
required: ['orgName', 'webhook'],
|
|
358046
358172
|
},
|
|
@@ -358212,15 +358338,7 @@ const GithubSchemas = [
|
|
|
358212
358338
|
type: 'object',
|
|
358213
358339
|
properties: {
|
|
358214
358340
|
policy: {
|
|
358215
|
-
|
|
358216
|
-
enum: [
|
|
358217
|
-
'apply',
|
|
358218
|
-
'create-only',
|
|
358219
|
-
'create-update-only',
|
|
358220
|
-
'full-control',
|
|
358221
|
-
'observe',
|
|
358222
|
-
'observe-only',
|
|
358223
|
-
],
|
|
358341
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358224
358342
|
},
|
|
358225
358343
|
name: {
|
|
358226
358344
|
type: 'string',
|
|
@@ -358230,47 +358348,7 @@ const GithubSchemas = [
|
|
|
358230
358348
|
enum: ['remote', 'inline', 'Remote', 'Inline'],
|
|
358231
358349
|
},
|
|
358232
358350
|
sync: {
|
|
358233
|
-
|
|
358234
|
-
properties: {
|
|
358235
|
-
enabled: {
|
|
358236
|
-
type: 'boolean',
|
|
358237
|
-
},
|
|
358238
|
-
period: {
|
|
358239
|
-
type: 'string',
|
|
358240
|
-
pattern: '^[0-9]+[smhd]$',
|
|
358241
|
-
},
|
|
358242
|
-
schedule: {
|
|
358243
|
-
type: 'string',
|
|
358244
|
-
},
|
|
358245
|
-
schedule_timezone: {
|
|
358246
|
-
type: 'string',
|
|
358247
|
-
},
|
|
358248
|
-
policy: {
|
|
358249
|
-
type: 'string',
|
|
358250
|
-
},
|
|
358251
|
-
},
|
|
358252
|
-
additionalProperties: false,
|
|
358253
|
-
required: ['enabled'],
|
|
358254
|
-
oneOf: [
|
|
358255
|
-
{
|
|
358256
|
-
required: ['period'],
|
|
358257
|
-
},
|
|
358258
|
-
{
|
|
358259
|
-
required: ['schedule'],
|
|
358260
|
-
},
|
|
358261
|
-
{
|
|
358262
|
-
not: {
|
|
358263
|
-
anyOf: [
|
|
358264
|
-
{
|
|
358265
|
-
required: ['period'],
|
|
358266
|
-
},
|
|
358267
|
-
{
|
|
358268
|
-
required: ['schedule'],
|
|
358269
|
-
},
|
|
358270
|
-
],
|
|
358271
|
-
},
|
|
358272
|
-
},
|
|
358273
|
-
],
|
|
358351
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358274
358352
|
},
|
|
358275
358353
|
valuesSchema: {
|
|
358276
358354
|
type: 'string',
|
|
@@ -370377,10 +370455,15 @@ class Resource {
|
|
|
370377
370455
|
this.set('operation', operation);
|
|
370378
370456
|
this.set('deps', deps);
|
|
370379
370457
|
}
|
|
370380
|
-
async run() {
|
|
370458
|
+
async run(options) {
|
|
370381
370459
|
await this.preprocess();
|
|
370382
370460
|
await this.synth();
|
|
370383
|
-
|
|
370461
|
+
if (options?.planOnly) {
|
|
370462
|
+
await this.runTerraformPlanOnly();
|
|
370463
|
+
}
|
|
370464
|
+
else {
|
|
370465
|
+
await this.runTerraform();
|
|
370466
|
+
}
|
|
370384
370467
|
await this.postprocess();
|
|
370385
370468
|
if (this.logStream) {
|
|
370386
370469
|
this.logStream.end();
|
|
@@ -370405,6 +370488,13 @@ class Resource {
|
|
|
370405
370488
|
log(msg) {
|
|
370406
370489
|
this.logFn(msg);
|
|
370407
370490
|
}
|
|
370491
|
+
async runTerraformPlanOnly() {
|
|
370492
|
+
await this.onTFStreaming();
|
|
370493
|
+
let output = '';
|
|
370494
|
+
output += await terraformInit(this.get('main_artifact'), this.logStream);
|
|
370495
|
+
output += await terraformPlan(this.get('main_artifact'), this.logStream);
|
|
370496
|
+
this.set('output', output);
|
|
370497
|
+
}
|
|
370408
370498
|
async runTerraform() {
|
|
370409
370499
|
await this.onTFStreaming();
|
|
370410
370500
|
let output = '';
|
|
@@ -370792,7 +370882,7 @@ async function runProvisioner(data, opts) {
|
|
|
370792
370882
|
if ('logStreamCallbacksTF' in opts) {
|
|
370793
370883
|
resource.setTFStreamLogs(opts['logStreamCallbacksTF']);
|
|
370794
370884
|
}
|
|
370795
|
-
await resource.run();
|
|
370885
|
+
await resource.run({ planOnly: opts.planOnly });
|
|
370796
370886
|
return resource;
|
|
370797
370887
|
}
|
|
370798
370888
|
function createInstanceOf(entity, op, deps) {
|
|
@@ -370892,25 +370982,33 @@ async function tryPublishDestroy(item, destroyOutput) {
|
|
|
370892
370982
|
return;
|
|
370893
370983
|
}
|
|
370894
370984
|
const dividedOutput = github_0.pulls.divideCommentIntoChunks(destroyOutput, 250);
|
|
370895
|
-
|
|
370896
|
-
|
|
370897
|
-
const
|
|
370985
|
+
const commentBodies = dividedOutput.map((commentContent, index) => {
|
|
370986
|
+
const isMultiPart = dividedOutput.length > 1;
|
|
370987
|
+
const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
|
|
370988
|
+
return `<h1>
|
|
370898
370989
|
<img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Destroy Finished
|
|
370899
370990
|
</h1>
|
|
370900
370991
|
<p><b>TFWorkspace: </b>${item.metadata.name}</p>
|
|
370901
370992
|
|
|
370902
370993
|
<details id=github>
|
|
370903
|
-
<summary>DESTROY LOGS
|
|
370994
|
+
<summary>DESTROY LOGS${partIndicator}</summary>
|
|
370904
370995
|
|
|
370905
370996
|
\`\`\`shell
|
|
370906
370997
|
${commentContent}
|
|
370907
370998
|
\`\`\`
|
|
370908
370999
|
</details>`;
|
|
370909
|
-
|
|
370910
|
-
|
|
370911
|
-
|
|
370912
|
-
|
|
370913
|
-
|
|
371000
|
+
});
|
|
371001
|
+
operator_src_logger.debug(`The user feedback for item '${item.kind}/${item.metadata.name}' is being published as a comment on pull request '${lastPr.number}' for repository '${repo}' in organization '${org}'.`);
|
|
371002
|
+
// Get octokit instance for the org to use with upsertMultiPartStickyComments
|
|
371003
|
+
const octokit = await github_0.auth.getOctokitForOrg(org);
|
|
371004
|
+
await github_0.feedback.upsertMultiPartStickyComments(octokit, {
|
|
371005
|
+
owner: org,
|
|
371006
|
+
repo,
|
|
371007
|
+
pullNumber: lastPr.number,
|
|
371008
|
+
baseKind: 'tfworkspace:destroy',
|
|
371009
|
+
bodies: commentBodies,
|
|
371010
|
+
});
|
|
371011
|
+
operator_src_logger.debug(`The user feedback for the '${item.kind}/${item.metadata.name}' destroy operation has been published as a comment on pull request '${lastPr.number}'.`);
|
|
370914
371012
|
}
|
|
370915
371013
|
catch (e) {
|
|
370916
371014
|
operator_src_logger.error(`An error occurred while publishing user feedback for item '${item.kind}/${item.metadata.name}': '${e}'.`);
|
|
@@ -370919,23 +371017,31 @@ ${commentContent}
|
|
|
370919
371017
|
async function publishApply(item, applyOutput, kind) {
|
|
370920
371018
|
const { prNumber, repo, org } = extractPrInfo(item);
|
|
370921
371019
|
const dividedOutput = github_0.pulls.divideCommentIntoChunks(applyOutput, 250);
|
|
370922
|
-
|
|
370923
|
-
|
|
370924
|
-
const
|
|
371020
|
+
const commentBodies = dividedOutput.map((commentContent, index) => {
|
|
371021
|
+
const isMultiPart = dividedOutput.length > 1;
|
|
371022
|
+
const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
|
|
371023
|
+
return `<h1>
|
|
370925
371024
|
<img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Apply Finished
|
|
370926
371025
|
</h1>
|
|
370927
371026
|
<p><b>${kind}: </b>${item.metadata.name}</p>
|
|
370928
371027
|
|
|
370929
371028
|
<details id=github>
|
|
370930
|
-
<summary>APPLY LOGS
|
|
371029
|
+
<summary>APPLY LOGS${partIndicator}</summary>
|
|
370931
371030
|
|
|
370932
371031
|
\`\`\`shell
|
|
370933
371032
|
${commentContent}
|
|
370934
371033
|
\`\`\`
|
|
370935
371034
|
</details>`;
|
|
370936
|
-
|
|
370937
|
-
|
|
370938
|
-
|
|
371035
|
+
});
|
|
371036
|
+
// Get octokit instance for the org to use with upsertMultiPartStickyComments
|
|
371037
|
+
const octokit = await github_0.auth.getOctokitForOrg(org);
|
|
371038
|
+
await github_0.feedback.upsertMultiPartStickyComments(octokit, {
|
|
371039
|
+
owner: org,
|
|
371040
|
+
repo,
|
|
371041
|
+
pullNumber: prNumber,
|
|
371042
|
+
baseKind: `apply:${kind}`,
|
|
371043
|
+
bodies: commentBodies,
|
|
371044
|
+
});
|
|
370939
371045
|
}
|
|
370940
371046
|
function tryCreateErrorSummary(title, errorMsg) {
|
|
370941
371047
|
try {
|
|
@@ -370993,23 +371099,31 @@ ${message}
|
|
|
370993
371099
|
async function publishPlan(item, planOutput, prNumber, repo, org) {
|
|
370994
371100
|
try {
|
|
370995
371101
|
const dividedOutput = github_0.pulls.divideCommentIntoChunks(planOutput, 250);
|
|
370996
|
-
|
|
370997
|
-
|
|
370998
|
-
const
|
|
371102
|
+
const commentBodies = dividedOutput.map((commentContent, index) => {
|
|
371103
|
+
const isMultiPart = dividedOutput.length > 1;
|
|
371104
|
+
const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
|
|
371105
|
+
return `<h1>
|
|
370999
371106
|
<img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Plan Finished
|
|
371000
371107
|
</h1>
|
|
371001
371108
|
<p><b>TFWorkspace: </b>${item.metadata.name}</p>
|
|
371002
371109
|
|
|
371003
371110
|
<details id=github>
|
|
371004
|
-
<summary>PLAN LOGS
|
|
371111
|
+
<summary>PLAN LOGS${partIndicator}</summary>
|
|
371005
371112
|
|
|
371006
371113
|
\`\`\`shell
|
|
371007
371114
|
${commentContent}
|
|
371008
371115
|
\`\`\`
|
|
371009
371116
|
</details>`;
|
|
371010
|
-
|
|
371011
|
-
|
|
371012
|
-
|
|
371117
|
+
});
|
|
371118
|
+
// Get octokit instance for the org to use with upsertMultiPartStickyComments
|
|
371119
|
+
const octokit = await github_0.auth.getOctokitForOrg(org);
|
|
371120
|
+
await github_0.feedback.upsertMultiPartStickyComments(octokit, {
|
|
371121
|
+
owner: org,
|
|
371122
|
+
repo,
|
|
371123
|
+
pullNumber: prNumber,
|
|
371124
|
+
baseKind: 'tfworkspace:plan',
|
|
371125
|
+
bodies: commentBodies,
|
|
371126
|
+
});
|
|
371013
371127
|
}
|
|
371014
371128
|
catch (e) {
|
|
371015
371129
|
console.error(e);
|
|
@@ -371050,6 +371164,51 @@ function helperCreateCheckRunName(cmd, item) {
|
|
|
371050
371164
|
return `${item.kind} - ${cmd}`;
|
|
371051
371165
|
}
|
|
371052
371166
|
|
|
371167
|
+
;// CONCATENATED MODULE: ../operator/src/utils/index.ts
|
|
371168
|
+
const secretRegex = /\$\{\{ secrets\.(.*?) \}\}/g;
|
|
371169
|
+
function replaceConfigSecrets(config, secrets) {
|
|
371170
|
+
for (const key in config) {
|
|
371171
|
+
if (typeof config[key] === 'object' && config[key] !== null) {
|
|
371172
|
+
// If the property is an object, call this function recursively
|
|
371173
|
+
replaceConfigSecrets(config[key], secrets);
|
|
371174
|
+
}
|
|
371175
|
+
else if (typeof config[key] === 'string') {
|
|
371176
|
+
// If the property is a string and its value is equal to secrets.something,
|
|
371177
|
+
// replace the value with the value of the 'something' key in the secrets object
|
|
371178
|
+
config[key] = config[key].replace(secretRegex, (_, group1) => {
|
|
371179
|
+
if (!secrets[group1]) {
|
|
371180
|
+
throw new Error(`Secret ${group1} not found in secrets`);
|
|
371181
|
+
}
|
|
371182
|
+
return secrets[group1];
|
|
371183
|
+
});
|
|
371184
|
+
}
|
|
371185
|
+
}
|
|
371186
|
+
return config;
|
|
371187
|
+
}
|
|
371188
|
+
function replaceInlineSecrets(inline, secrets) {
|
|
371189
|
+
if (typeof inline !== 'string' || !inline)
|
|
371190
|
+
return inline;
|
|
371191
|
+
let result = inline;
|
|
371192
|
+
result = result.replace(secretRegex, (_, group1) => {
|
|
371193
|
+
if (!secrets[group1]) {
|
|
371194
|
+
throw new Error(`Secret ${group1} not found in secrets`);
|
|
371195
|
+
}
|
|
371196
|
+
return secrets[group1];
|
|
371197
|
+
});
|
|
371198
|
+
return result;
|
|
371199
|
+
}
|
|
371200
|
+
/**
|
|
371201
|
+
* Retrieves a policy annotation value from a custom resource
|
|
371202
|
+
* @param item - The CR to get the policy from
|
|
371203
|
+
* @param annotation - The annotation key to retrieve
|
|
371204
|
+
* @returns The policy value, or undefined if not set
|
|
371205
|
+
*/
|
|
371206
|
+
function getPolicy(item, annotation) {
|
|
371207
|
+
const policy = item.metadata.annotations && item.metadata.annotations[annotation];
|
|
371208
|
+
if (policy)
|
|
371209
|
+
return policy;
|
|
371210
|
+
}
|
|
371211
|
+
|
|
371053
371212
|
;// CONCATENATED MODULE: ../operator/cdktf.ts
|
|
371054
371213
|
|
|
371055
371214
|
|
|
@@ -371059,9 +371218,17 @@ function helperCreateCheckRunName(cmd, item) {
|
|
|
371059
371218
|
|
|
371060
371219
|
|
|
371061
371220
|
|
|
371221
|
+
|
|
371222
|
+
const cdktf_LAST_STATE_PR_ANNOTATION = 'firestartr.dev/last-state-pr';
|
|
371062
371223
|
function processOperation(item, op, handler) {
|
|
371063
371224
|
operator_src_logger.info(`Processing operation ${op} on ${item.kind}/${item.metadata?.name}`);
|
|
371064
371225
|
try {
|
|
371226
|
+
const policy = getPolicy(item, 'firestartr.dev/policy');
|
|
371227
|
+
// If general policy is observe/observe-only, route to observe mode instead of apply
|
|
371228
|
+
if (!policy || policy === 'observe' || policy === 'observe-only') {
|
|
371229
|
+
operator_src_logger.info(`Policy is '${policy || 'not set (default)'}', routing to observe mode`);
|
|
371230
|
+
return cdktf_observe(item, op, handler);
|
|
371231
|
+
}
|
|
371065
371232
|
switch (op) {
|
|
371066
371233
|
case OperationType.UPDATED:
|
|
371067
371234
|
return updated(item, op, handler);
|
|
@@ -371086,6 +371253,11 @@ function processOperation(item, op, handler) {
|
|
|
371086
371253
|
throw e;
|
|
371087
371254
|
}
|
|
371088
371255
|
}
|
|
371256
|
+
async function* cdktf_observe(item, op, handler) {
|
|
371257
|
+
for await (const transition of doPlan(item, op, handler)) {
|
|
371258
|
+
yield transition;
|
|
371259
|
+
}
|
|
371260
|
+
}
|
|
371089
371261
|
async function* created(item, op, handler) {
|
|
371090
371262
|
for await (const transition of doApply(item, op, handler)) {
|
|
371091
371263
|
yield transition;
|
|
@@ -371121,8 +371293,18 @@ async function* sync(item, op, handler) {
|
|
|
371121
371293
|
status: 'False',
|
|
371122
371294
|
message: 'Synth CDKTF',
|
|
371123
371295
|
};
|
|
371124
|
-
|
|
371125
|
-
|
|
371296
|
+
const syncPolicy = getPolicy(item, 'firestartr.dev/sync-policy');
|
|
371297
|
+
if (syncPolicy === 'apply') {
|
|
371298
|
+
operator_src_logger.info(`SYNC OPERATION: applying item ${item.metadata.name} with sync-policy=${syncPolicy}`);
|
|
371299
|
+
for await (const transition of doApply(item, op, handler)) {
|
|
371300
|
+
yield transition;
|
|
371301
|
+
}
|
|
371302
|
+
}
|
|
371303
|
+
else {
|
|
371304
|
+
operator_src_logger.info(`SYNC OPERATION: planning item ${item.metadata.name} with sync-policy=${syncPolicy || 'default (observe)'}`);
|
|
371305
|
+
for await (const transition of doPlan(item, op, handler)) {
|
|
371306
|
+
yield transition;
|
|
371307
|
+
}
|
|
371126
371308
|
}
|
|
371127
371309
|
yield {
|
|
371128
371310
|
item,
|
|
@@ -371161,15 +371343,14 @@ async function* markedToDeletion(item, op, handler) {
|
|
|
371161
371343
|
message: 'Destroying process started',
|
|
371162
371344
|
};
|
|
371163
371345
|
const deps = await handler.resolveReferences();
|
|
371164
|
-
const
|
|
371165
|
-
const statePr = item?.metadata?.annotations?.[annotation];
|
|
371346
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371166
371347
|
const hasStatePr = typeof statePr === 'string' && statePr.trim().length > 0;
|
|
371167
371348
|
if (!hasStatePr) {
|
|
371168
371349
|
operator_src_logger.warn(`CR ${item?.kind ?? 'UnknownKind'}/${item?.metadata?.name ?? 'unknown'} ` +
|
|
371169
|
-
`has no "${
|
|
371350
|
+
`has no "${cdktf_LAST_STATE_PR_ANNOTATION}" annotation; skipping GitHub Check Runs (synth, terraform apply).`);
|
|
371170
371351
|
}
|
|
371171
371352
|
else {
|
|
371172
|
-
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${
|
|
371353
|
+
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${cdktf_LAST_STATE_PR_ANNOTATION}" = ${statePr}`);
|
|
371173
371354
|
}
|
|
371174
371355
|
const destroyOutput = await provisioner.runProvisioner({
|
|
371175
371356
|
mainCr: item,
|
|
@@ -371204,7 +371385,7 @@ async function* markedToDeletion(item, op, handler) {
|
|
|
371204
371385
|
};
|
|
371205
371386
|
await handler.finalize(handler.pluralKind, item.metadata.namespace, item, 'firestartr.dev/finalizer');
|
|
371206
371387
|
await handler.writeTerraformOutputInTfResult(item, output);
|
|
371207
|
-
if (item.metadata.annotations[
|
|
371388
|
+
if (item.metadata.annotations[cdktf_LAST_STATE_PR_ANNOTATION] || false) {
|
|
371208
371389
|
await addDestroyCommitStatus(item, 'success', 'Destroy operation completed', `Terraform Destroy ${item.metadata.name}`);
|
|
371209
371390
|
}
|
|
371210
371391
|
void handler.success();
|
|
@@ -371285,15 +371466,14 @@ async function* doApply(item, op, handler) {
|
|
|
371285
371466
|
}
|
|
371286
371467
|
const deps = await handler.resolveReferences();
|
|
371287
371468
|
operator_src_logger.info(`Item ${item.metadata.name} has the following dependencies: ${deps}`);
|
|
371288
|
-
const
|
|
371289
|
-
const statePr = item?.metadata?.annotations?.[annotation];
|
|
371469
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371290
371470
|
const hasStatePr = typeof statePr === 'string' && statePr.trim().length > 0;
|
|
371291
371471
|
if (!hasStatePr) {
|
|
371292
371472
|
operator_src_logger.warn(`CR ${item?.kind ?? 'UnknownKind'}/${item?.metadata?.name ?? 'unknown'} ` +
|
|
371293
|
-
`has no "${
|
|
371473
|
+
`has no "${cdktf_LAST_STATE_PR_ANNOTATION}" annotation; skipping GitHub Check Runs (synth, terraform apply).`);
|
|
371294
371474
|
}
|
|
371295
371475
|
else {
|
|
371296
|
-
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${
|
|
371476
|
+
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${cdktf_LAST_STATE_PR_ANNOTATION}" = ${statePr}`);
|
|
371297
371477
|
}
|
|
371298
371478
|
const applyOutput = await provisioner.runProvisioner({
|
|
371299
371479
|
mainCr: item,
|
|
@@ -371389,6 +371569,219 @@ async function* doApply(item, op, handler) {
|
|
|
371389
371569
|
}
|
|
371390
371570
|
}
|
|
371391
371571
|
}
|
|
371572
|
+
async function* doPlan(item, op, handler) {
|
|
371573
|
+
let checkRunCtl;
|
|
371574
|
+
try {
|
|
371575
|
+
cleanTerraformState();
|
|
371576
|
+
yield {
|
|
371577
|
+
item,
|
|
371578
|
+
reason: op,
|
|
371579
|
+
type: 'PLANNING',
|
|
371580
|
+
status: 'True',
|
|
371581
|
+
message: 'Planning process started',
|
|
371582
|
+
};
|
|
371583
|
+
const deps = await handler.resolveReferences();
|
|
371584
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371585
|
+
const hasStatePr = typeof statePr === 'string' && statePr.trim().length > 0;
|
|
371586
|
+
if (!hasStatePr) {
|
|
371587
|
+
operator_src_logger.warn(`CR ${item?.kind ?? 'UnknownKind'}/${item?.metadata?.name ?? 'unknown'} ` +
|
|
371588
|
+
`has no "${cdktf_LAST_STATE_PR_ANNOTATION}" annotation; skipping GitHub Check Runs for plan.`);
|
|
371589
|
+
}
|
|
371590
|
+
else {
|
|
371591
|
+
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${cdktf_LAST_STATE_PR_ANNOTATION}" = ${statePr}`);
|
|
371592
|
+
await addPlanStatusCheck(statePr, 'CDKTF plan in progress...');
|
|
371593
|
+
}
|
|
371594
|
+
// Run provisioner in plan-only mode
|
|
371595
|
+
const planResult = await provisioner.runProvisioner({ mainCr: item, deps }, {
|
|
371596
|
+
planOnly: true,
|
|
371597
|
+
delete: 'deletionTimestamp' in item.metadata,
|
|
371598
|
+
...(hasStatePr
|
|
371599
|
+
? {
|
|
371600
|
+
logStreamCallbacksCDKTF: {
|
|
371601
|
+
prepare: async () => {
|
|
371602
|
+
checkRunCtl = await GHCheckRun('synth', item);
|
|
371603
|
+
return checkRunCtl;
|
|
371604
|
+
},
|
|
371605
|
+
},
|
|
371606
|
+
logStreamCallbacksTF: {
|
|
371607
|
+
prepare: async () => {
|
|
371608
|
+
checkRunCtl = await GHCheckRun('plan', item);
|
|
371609
|
+
return checkRunCtl;
|
|
371610
|
+
},
|
|
371611
|
+
},
|
|
371612
|
+
}
|
|
371613
|
+
: {}),
|
|
371614
|
+
});
|
|
371615
|
+
const planOutput = planResult?.output || '';
|
|
371616
|
+
// Parse terraform plan output to detect changes
|
|
371617
|
+
// Handles multiple Terraform output formats and versions
|
|
371618
|
+
const hasChanges = detectPlanChanges(planOutput);
|
|
371619
|
+
if (hasChanges) {
|
|
371620
|
+
yield {
|
|
371621
|
+
item,
|
|
371622
|
+
reason: op,
|
|
371623
|
+
type: 'OUT_OF_SYNC',
|
|
371624
|
+
status: 'True',
|
|
371625
|
+
message: 'Plan has changes',
|
|
371626
|
+
};
|
|
371627
|
+
yield {
|
|
371628
|
+
item,
|
|
371629
|
+
reason: op,
|
|
371630
|
+
type: 'PROVISIONED',
|
|
371631
|
+
status: 'False',
|
|
371632
|
+
message: 'Plan has changes',
|
|
371633
|
+
};
|
|
371634
|
+
}
|
|
371635
|
+
else {
|
|
371636
|
+
yield {
|
|
371637
|
+
item,
|
|
371638
|
+
reason: op,
|
|
371639
|
+
type: 'OUT_OF_SYNC',
|
|
371640
|
+
status: 'False',
|
|
371641
|
+
message: 'Plan has no changes',
|
|
371642
|
+
};
|
|
371643
|
+
yield {
|
|
371644
|
+
item,
|
|
371645
|
+
reason: op,
|
|
371646
|
+
type: 'PROVISIONED',
|
|
371647
|
+
status: 'True',
|
|
371648
|
+
message: 'Plan has no changes',
|
|
371649
|
+
};
|
|
371650
|
+
}
|
|
371651
|
+
// Store plan details for later reference
|
|
371652
|
+
yield {
|
|
371653
|
+
item,
|
|
371654
|
+
reason: op,
|
|
371655
|
+
type: 'LAST_PLAN_DETAILS',
|
|
371656
|
+
status: 'Unknown',
|
|
371657
|
+
message: planOutput,
|
|
371658
|
+
};
|
|
371659
|
+
yield {
|
|
371660
|
+
item,
|
|
371661
|
+
reason: op,
|
|
371662
|
+
type: 'PLANNING',
|
|
371663
|
+
status: 'False',
|
|
371664
|
+
message: 'Planning process finished',
|
|
371665
|
+
};
|
|
371666
|
+
if (hasStatePr) {
|
|
371667
|
+
await addPlanStatusCheck(statePr, hasChanges ? 'Plan has changes' : 'Plan has no changes', 'completed');
|
|
371668
|
+
}
|
|
371669
|
+
}
|
|
371670
|
+
catch (e) {
|
|
371671
|
+
operator_src_logger.error(`CDKTF plan failed: ${e}`);
|
|
371672
|
+
if (checkRunCtl) {
|
|
371673
|
+
checkRunCtl.fnOnError(e);
|
|
371674
|
+
}
|
|
371675
|
+
yield {
|
|
371676
|
+
item,
|
|
371677
|
+
reason: op,
|
|
371678
|
+
type: 'ERROR',
|
|
371679
|
+
status: 'True',
|
|
371680
|
+
message: e.toString(),
|
|
371681
|
+
};
|
|
371682
|
+
yield {
|
|
371683
|
+
item,
|
|
371684
|
+
reason: op,
|
|
371685
|
+
type: 'PLANNING',
|
|
371686
|
+
status: 'False',
|
|
371687
|
+
message: e.toString(),
|
|
371688
|
+
};
|
|
371689
|
+
yield {
|
|
371690
|
+
item,
|
|
371691
|
+
reason: op,
|
|
371692
|
+
type: 'PROVISIONED',
|
|
371693
|
+
status: 'False',
|
|
371694
|
+
message: e.toString(),
|
|
371695
|
+
};
|
|
371696
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371697
|
+
if (statePr) {
|
|
371698
|
+
const summaryText = tryCreateErrorSummary('CDKTF Plan failed', e);
|
|
371699
|
+
await addPlanStatusCheck(statePr, summaryText, 'completed', true);
|
|
371700
|
+
}
|
|
371701
|
+
await handler.writeTerraformOutputInTfResult(item, e);
|
|
371702
|
+
void handler.error();
|
|
371703
|
+
}
|
|
371704
|
+
}
|
|
371705
|
+
/**
|
|
371706
|
+
* Detects if a Terraform plan output contains changes
|
|
371707
|
+
* Handles multiple Terraform versions and output formats
|
|
371708
|
+
* @param planOutput - The text output from terraform plan
|
|
371709
|
+
* @returns true if changes are detected, false otherwise
|
|
371710
|
+
*/
|
|
371711
|
+
function detectPlanChanges(planOutput) {
|
|
371712
|
+
if (!planOutput || planOutput.trim().length === 0) {
|
|
371713
|
+
return false;
|
|
371714
|
+
}
|
|
371715
|
+
// Normalize the output for consistent matching
|
|
371716
|
+
const normalized = planOutput.toLowerCase();
|
|
371717
|
+
// Pattern 1: "Plan: X to add, Y to change, Z to destroy"
|
|
371718
|
+
// Matches: "Plan: 1 to add, 0 to change, 0 to destroy"
|
|
371719
|
+
const planPattern = /plan:\s*(\d+)\s+to\s+add,\s*(\d+)\s+to\s+change,\s*(\d+)\s+to\s+destroy/i;
|
|
371720
|
+
const planMatch = planOutput.match(planPattern);
|
|
371721
|
+
if (planMatch) {
|
|
371722
|
+
const add = Number(planMatch[1]);
|
|
371723
|
+
const change = Number(planMatch[2]);
|
|
371724
|
+
const destroy = Number(planMatch[3]);
|
|
371725
|
+
if (add > 0 || change > 0 || destroy > 0) {
|
|
371726
|
+
return true;
|
|
371727
|
+
}
|
|
371728
|
+
// Explicitly found "Plan:" with 0/0/0 - no changes
|
|
371729
|
+
return false;
|
|
371730
|
+
}
|
|
371731
|
+
// Pattern 2: Individual change indicators
|
|
371732
|
+
// Handles variations like "1 to add", "2 to change", "3 to destroy"
|
|
371733
|
+
const hasAdditions = /\d+\s+to\s+add/i.test(planOutput);
|
|
371734
|
+
const hasChanges = /\d+\s+to\s+change/i.test(planOutput);
|
|
371735
|
+
const hasDestructions = /\d+\s+to\s+destroy/i.test(planOutput);
|
|
371736
|
+
const hasImports = /\d+\s+to\s+import/i.test(planOutput);
|
|
371737
|
+
if (hasAdditions || hasChanges || hasDestructions || hasImports) {
|
|
371738
|
+
return true;
|
|
371739
|
+
}
|
|
371740
|
+
// Pattern 3: Resource-level change indicators
|
|
371741
|
+
// Matches: "# resource will be created", "# resource will be updated", etc.
|
|
371742
|
+
const resourceChangePatterns = [
|
|
371743
|
+
/will\s+be\s+(created|destroyed|updated|replaced)/i,
|
|
371744
|
+
/must\s+be\s+(created|destroyed|updated|replaced)/i,
|
|
371745
|
+
/#.*\s+(create|destroy|update|replace)/i,
|
|
371746
|
+
];
|
|
371747
|
+
for (const pattern of resourceChangePatterns) {
|
|
371748
|
+
if (pattern.test(planOutput)) {
|
|
371749
|
+
return true;
|
|
371750
|
+
}
|
|
371751
|
+
}
|
|
371752
|
+
// Pattern 4: Action symbols in plan output
|
|
371753
|
+
// Terraform uses symbols like +, -, ~, -/+ to indicate changes
|
|
371754
|
+
const actionSymbols = [
|
|
371755
|
+
/^\s*[+]\s+/m,
|
|
371756
|
+
/^\s*[-]\s+/m,
|
|
371757
|
+
/^\s*[~]\s+/m,
|
|
371758
|
+
/^\s*[-][/][+]\s+/m, // Replace
|
|
371759
|
+
];
|
|
371760
|
+
for (const pattern of actionSymbols) {
|
|
371761
|
+
if (pattern.test(planOutput)) {
|
|
371762
|
+
return true;
|
|
371763
|
+
}
|
|
371764
|
+
}
|
|
371765
|
+
// Pattern 5: No changes messages (inverse check)
|
|
371766
|
+
const noChangesPatterns = [
|
|
371767
|
+
/no\s+changes/i,
|
|
371768
|
+
/infrastructure\s+is\s+up[-\s]to[-\s]date/i,
|
|
371769
|
+
/your\s+infrastructure\s+matches\s+the\s+configuration/i,
|
|
371770
|
+
/0\s+to\s+add,\s*0\s+to\s+change,\s*0\s+to\s+destroy/i,
|
|
371771
|
+
];
|
|
371772
|
+
for (const pattern of noChangesPatterns) {
|
|
371773
|
+
if (pattern.test(planOutput)) {
|
|
371774
|
+
return false;
|
|
371775
|
+
}
|
|
371776
|
+
}
|
|
371777
|
+
// If we find "Plan:" keyword but couldn't parse it, log a warning and assume no changes
|
|
371778
|
+
if (normalized.includes('plan:')) {
|
|
371779
|
+
operator_src_logger.warn('Found "Plan:" in output but could not parse change counts. Assuming no changes.');
|
|
371780
|
+
return false;
|
|
371781
|
+
}
|
|
371782
|
+
// Default: assume no changes if we can't detect any
|
|
371783
|
+
return false;
|
|
371784
|
+
}
|
|
371392
371785
|
function cleanTerraformState() {
|
|
371393
371786
|
external_fs_.rmSync('/library/packages/provisioner/cdktf.out', {
|
|
371394
371787
|
recursive: true,
|
|
@@ -372388,40 +372781,6 @@ function tf_checkrun_helperCreateCheckRunName(cmd) {
|
|
|
372388
372781
|
return `TFWorkspace - ${cmd}`;
|
|
372389
372782
|
}
|
|
372390
372783
|
|
|
372391
|
-
;// CONCATENATED MODULE: ../operator/src/utils/index.ts
|
|
372392
|
-
const secretRegex = /\$\{\{ secrets\.(.*?) \}\}/g;
|
|
372393
|
-
function replaceConfigSecrets(config, secrets) {
|
|
372394
|
-
for (const key in config) {
|
|
372395
|
-
if (typeof config[key] === 'object' && config[key] !== null) {
|
|
372396
|
-
// If the property is an object, call this function recursively
|
|
372397
|
-
replaceConfigSecrets(config[key], secrets);
|
|
372398
|
-
}
|
|
372399
|
-
else if (typeof config[key] === 'string') {
|
|
372400
|
-
// If the property is a string and its value is equal to secrets.something,
|
|
372401
|
-
// replace the value with the value of the 'something' key in the secrets object
|
|
372402
|
-
config[key] = config[key].replace(secretRegex, (_, group1) => {
|
|
372403
|
-
if (!secrets[group1]) {
|
|
372404
|
-
throw new Error(`Secret ${group1} not found in secrets`);
|
|
372405
|
-
}
|
|
372406
|
-
return secrets[group1];
|
|
372407
|
-
});
|
|
372408
|
-
}
|
|
372409
|
-
}
|
|
372410
|
-
return config;
|
|
372411
|
-
}
|
|
372412
|
-
function replaceInlineSecrets(inline, secrets) {
|
|
372413
|
-
if (typeof inline !== 'string' || !inline)
|
|
372414
|
-
return inline;
|
|
372415
|
-
let result = inline;
|
|
372416
|
-
result = result.replace(secretRegex, (_, group1) => {
|
|
372417
|
-
if (!secrets[group1]) {
|
|
372418
|
-
throw new Error(`Secret ${group1} not found in secrets`);
|
|
372419
|
-
}
|
|
372420
|
-
return secrets[group1];
|
|
372421
|
-
});
|
|
372422
|
-
return result;
|
|
372423
|
-
}
|
|
372424
|
-
|
|
372425
372784
|
;// CONCATENATED MODULE: ../operator/src/tfworkspaces/process-operation.ts
|
|
372426
372785
|
|
|
372427
372786
|
|
|
@@ -372612,11 +372971,6 @@ async function* process_operation_renamed(item, op, handler) {
|
|
|
372612
372971
|
yield transition;
|
|
372613
372972
|
}
|
|
372614
372973
|
}
|
|
372615
|
-
function getPolicy(item, annotation) {
|
|
372616
|
-
const policy = item.metadata.annotations && item.metadata.annotations[annotation];
|
|
372617
|
-
if (policy)
|
|
372618
|
-
return policy;
|
|
372619
|
-
}
|
|
372620
372974
|
async function* process_operation_updated(item, op, handler) {
|
|
372621
372975
|
for await (const transition of process_operation_doApply(item, op, handler)) {
|
|
372622
372976
|
yield transition;
|
|
@@ -373260,7 +373614,7 @@ const processOperationPlan_TF_PROJECTS_PATH = '/tmp/tfworkspaces';
|
|
|
373260
373614
|
function processOperationPlan(item, op, handler) {
|
|
373261
373615
|
try {
|
|
373262
373616
|
processOperationPlan_clearLocalTfProjects();
|
|
373263
|
-
const policy =
|
|
373617
|
+
const policy = getPolicy(item, 'firestartr.dev/policy');
|
|
373264
373618
|
if (policy === 'observe' || policy === 'apply') {
|
|
373265
373619
|
return processOperationPlan_plan(item, op, handler);
|
|
373266
373620
|
}
|
|
@@ -373707,12 +374061,6 @@ function processOperationPlan_getErrorOutputMessage(cr, key, ref) {
|
|
|
373707
374061
|
throw new Error(`❌ Source ${cr.spec.source} not supported`);
|
|
373708
374062
|
}
|
|
373709
374063
|
}
|
|
373710
|
-
function processOperationPlan_getPolicy(item) {
|
|
373711
|
-
const policy = item.metadata.annotations &&
|
|
373712
|
-
item.metadata.annotations['firestartr.dev/policy'];
|
|
373713
|
-
if (policy)
|
|
373714
|
-
return policy;
|
|
373715
|
-
}
|
|
373716
374064
|
|
|
373717
374065
|
;// CONCATENATED MODULE: ../operator/src/ctx.ts
|
|
373718
374066
|
class Ctx {
|