@firestartr/cli 1.53.0-snapshot-4 → 1.53.0-snapshot-5
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 +576 -234
- 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,
|
|
@@ -357539,6 +357572,69 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357539
357572
|
},
|
|
357540
357573
|
additionalProperties: false,
|
|
357541
357574
|
},
|
|
357575
|
+
PolicyType: {
|
|
357576
|
+
$id: 'firestartr.dev://common/PolicyType',
|
|
357577
|
+
type: 'string',
|
|
357578
|
+
description: 'Policy for resource management',
|
|
357579
|
+
enum: [
|
|
357580
|
+
'apply',
|
|
357581
|
+
'create-only',
|
|
357582
|
+
'create-update-only',
|
|
357583
|
+
'full-control',
|
|
357584
|
+
'observe',
|
|
357585
|
+
'observe-only',
|
|
357586
|
+
],
|
|
357587
|
+
},
|
|
357588
|
+
SyncConfig: {
|
|
357589
|
+
$id: 'firestartr.dev://common/SyncConfig',
|
|
357590
|
+
type: 'object',
|
|
357591
|
+
description: 'Sync configuration for resources',
|
|
357592
|
+
properties: {
|
|
357593
|
+
enabled: {
|
|
357594
|
+
type: 'boolean',
|
|
357595
|
+
description: 'Enable periodic sync operations',
|
|
357596
|
+
},
|
|
357597
|
+
period: {
|
|
357598
|
+
type: 'string',
|
|
357599
|
+
pattern: '^[0-9]+[smhd]$',
|
|
357600
|
+
description: 'Sync period (e.g., 1h, 30m, 5s). Must be enabled without schedule.',
|
|
357601
|
+
},
|
|
357602
|
+
schedule: {
|
|
357603
|
+
type: 'string',
|
|
357604
|
+
description: 'Cron schedule for sync operations. Must be enabled without period.',
|
|
357605
|
+
},
|
|
357606
|
+
schedule_timezone: {
|
|
357607
|
+
type: 'string',
|
|
357608
|
+
description: 'Timezone for cron schedule (e.g., UTC, America/New_York)',
|
|
357609
|
+
},
|
|
357610
|
+
policy: {
|
|
357611
|
+
type: 'string',
|
|
357612
|
+
description: 'Policy for sync operations (apply or observe)',
|
|
357613
|
+
},
|
|
357614
|
+
},
|
|
357615
|
+
additionalProperties: false,
|
|
357616
|
+
required: ['enabled'],
|
|
357617
|
+
oneOf: [
|
|
357618
|
+
{
|
|
357619
|
+
required: ['period'],
|
|
357620
|
+
},
|
|
357621
|
+
{
|
|
357622
|
+
required: ['schedule'],
|
|
357623
|
+
},
|
|
357624
|
+
{
|
|
357625
|
+
not: {
|
|
357626
|
+
anyOf: [
|
|
357627
|
+
{
|
|
357628
|
+
required: ['period'],
|
|
357629
|
+
},
|
|
357630
|
+
{
|
|
357631
|
+
required: ['schedule'],
|
|
357632
|
+
},
|
|
357633
|
+
],
|
|
357634
|
+
},
|
|
357635
|
+
},
|
|
357636
|
+
],
|
|
357637
|
+
},
|
|
357542
357638
|
},
|
|
357543
357639
|
});
|
|
357544
357640
|
|
|
@@ -357899,6 +357995,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357899
357995
|
{
|
|
357900
357996
|
type: 'object',
|
|
357901
357997
|
properties: {
|
|
357998
|
+
policy: {
|
|
357999
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358000
|
+
},
|
|
357902
358001
|
privacy: {
|
|
357903
358002
|
type: 'string',
|
|
357904
358003
|
enum: ['closed', 'secret'],
|
|
@@ -357909,6 +358008,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357909
358008
|
org: {
|
|
357910
358009
|
type: 'string',
|
|
357911
358010
|
},
|
|
358011
|
+
sync: {
|
|
358012
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358013
|
+
},
|
|
357912
358014
|
},
|
|
357913
358015
|
required: ['org', 'privacy'],
|
|
357914
358016
|
},
|
|
@@ -357934,6 +358036,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357934
358036
|
{
|
|
357935
358037
|
type: 'object',
|
|
357936
358038
|
properties: {
|
|
358039
|
+
policy: {
|
|
358040
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358041
|
+
},
|
|
357937
358042
|
role: {
|
|
357938
358043
|
type: 'string',
|
|
357939
358044
|
enum: ['admin', 'member'],
|
|
@@ -357941,6 +358046,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357941
358046
|
org: {
|
|
357942
358047
|
type: 'string',
|
|
357943
358048
|
},
|
|
358049
|
+
sync: {
|
|
358050
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358051
|
+
},
|
|
357944
358052
|
},
|
|
357945
358053
|
required: ['org', 'role'],
|
|
357946
358054
|
},
|
|
@@ -357965,6 +358073,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357965
358073
|
{
|
|
357966
358074
|
type: 'object',
|
|
357967
358075
|
properties: {
|
|
358076
|
+
policy: {
|
|
358077
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358078
|
+
},
|
|
357968
358079
|
org: {
|
|
357969
358080
|
type: 'string',
|
|
357970
358081
|
description: 'The github organization name',
|
|
@@ -357973,6 +358084,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
357973
358084
|
type: 'string',
|
|
357974
358085
|
enum: ['private', 'public', 'internal'],
|
|
357975
358086
|
},
|
|
358087
|
+
sync: {
|
|
358088
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358089
|
+
},
|
|
357976
358090
|
features: {
|
|
357977
358091
|
type: 'array',
|
|
357978
358092
|
items: {
|
|
@@ -358008,6 +358122,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
358008
358122
|
{
|
|
358009
358123
|
type: 'object',
|
|
358010
358124
|
properties: {
|
|
358125
|
+
policy: {
|
|
358126
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358127
|
+
},
|
|
358011
358128
|
orgName: {
|
|
358012
358129
|
type: 'string',
|
|
358013
358130
|
description: 'Organization name on GitHub',
|
|
@@ -358041,6 +358158,9 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq
|
|
|
358041
358158
|
},
|
|
358042
358159
|
required: ['url', 'contentType', 'events', 'secretRef'],
|
|
358043
358160
|
},
|
|
358161
|
+
sync: {
|
|
358162
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358163
|
+
},
|
|
358044
358164
|
},
|
|
358045
358165
|
required: ['orgName', 'webhook'],
|
|
358046
358166
|
},
|
|
@@ -358212,15 +358332,7 @@ const GithubSchemas = [
|
|
|
358212
358332
|
type: 'object',
|
|
358213
358333
|
properties: {
|
|
358214
358334
|
policy: {
|
|
358215
|
-
|
|
358216
|
-
enum: [
|
|
358217
|
-
'apply',
|
|
358218
|
-
'create-only',
|
|
358219
|
-
'create-update-only',
|
|
358220
|
-
'full-control',
|
|
358221
|
-
'observe',
|
|
358222
|
-
'observe-only',
|
|
358223
|
-
],
|
|
358335
|
+
$ref: 'firestartr.dev://common/PolicyType',
|
|
358224
358336
|
},
|
|
358225
358337
|
name: {
|
|
358226
358338
|
type: 'string',
|
|
@@ -358230,47 +358342,7 @@ const GithubSchemas = [
|
|
|
358230
358342
|
enum: ['remote', 'inline', 'Remote', 'Inline'],
|
|
358231
358343
|
},
|
|
358232
358344
|
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
|
-
],
|
|
358345
|
+
$ref: 'firestartr.dev://common/SyncConfig',
|
|
358274
358346
|
},
|
|
358275
358347
|
valuesSchema: {
|
|
358276
358348
|
type: 'string',
|
|
@@ -370377,10 +370449,15 @@ class Resource {
|
|
|
370377
370449
|
this.set('operation', operation);
|
|
370378
370450
|
this.set('deps', deps);
|
|
370379
370451
|
}
|
|
370380
|
-
async run() {
|
|
370452
|
+
async run(options) {
|
|
370381
370453
|
await this.preprocess();
|
|
370382
370454
|
await this.synth();
|
|
370383
|
-
|
|
370455
|
+
if (options?.planOnly) {
|
|
370456
|
+
await this.runTerraformPlanOnly();
|
|
370457
|
+
}
|
|
370458
|
+
else {
|
|
370459
|
+
await this.runTerraform();
|
|
370460
|
+
}
|
|
370384
370461
|
await this.postprocess();
|
|
370385
370462
|
if (this.logStream) {
|
|
370386
370463
|
this.logStream.end();
|
|
@@ -370405,6 +370482,13 @@ class Resource {
|
|
|
370405
370482
|
log(msg) {
|
|
370406
370483
|
this.logFn(msg);
|
|
370407
370484
|
}
|
|
370485
|
+
async runTerraformPlanOnly() {
|
|
370486
|
+
await this.onTFStreaming();
|
|
370487
|
+
let output = '';
|
|
370488
|
+
output += await terraformInit(this.get('main_artifact'), this.logStream);
|
|
370489
|
+
output += await terraformPlan(this.get('main_artifact'), this.logStream);
|
|
370490
|
+
this.set('output', output);
|
|
370491
|
+
}
|
|
370408
370492
|
async runTerraform() {
|
|
370409
370493
|
await this.onTFStreaming();
|
|
370410
370494
|
let output = '';
|
|
@@ -370792,7 +370876,7 @@ async function runProvisioner(data, opts) {
|
|
|
370792
370876
|
if ('logStreamCallbacksTF' in opts) {
|
|
370793
370877
|
resource.setTFStreamLogs(opts['logStreamCallbacksTF']);
|
|
370794
370878
|
}
|
|
370795
|
-
await resource.run();
|
|
370879
|
+
await resource.run({ planOnly: opts.planOnly });
|
|
370796
370880
|
return resource;
|
|
370797
370881
|
}
|
|
370798
370882
|
function createInstanceOf(entity, op, deps) {
|
|
@@ -370892,25 +370976,33 @@ async function tryPublishDestroy(item, destroyOutput) {
|
|
|
370892
370976
|
return;
|
|
370893
370977
|
}
|
|
370894
370978
|
const dividedOutput = github_0.pulls.divideCommentIntoChunks(destroyOutput, 250);
|
|
370895
|
-
|
|
370896
|
-
|
|
370897
|
-
const
|
|
370979
|
+
const commentBodies = dividedOutput.map((commentContent, index) => {
|
|
370980
|
+
const isMultiPart = dividedOutput.length > 1;
|
|
370981
|
+
const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
|
|
370982
|
+
return `<h1>
|
|
370898
370983
|
<img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Destroy Finished
|
|
370899
370984
|
</h1>
|
|
370900
370985
|
<p><b>TFWorkspace: </b>${item.metadata.name}</p>
|
|
370901
370986
|
|
|
370902
370987
|
<details id=github>
|
|
370903
|
-
<summary>DESTROY LOGS
|
|
370988
|
+
<summary>DESTROY LOGS${partIndicator}</summary>
|
|
370904
370989
|
|
|
370905
370990
|
\`\`\`shell
|
|
370906
370991
|
${commentContent}
|
|
370907
370992
|
\`\`\`
|
|
370908
370993
|
</details>`;
|
|
370909
|
-
|
|
370910
|
-
|
|
370911
|
-
|
|
370912
|
-
|
|
370913
|
-
|
|
370994
|
+
});
|
|
370995
|
+
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}'.`);
|
|
370996
|
+
// Get octokit instance for the org to use with upsertMultiPartStickyComments
|
|
370997
|
+
const octokit = await github_0.auth.getOctokitForOrg(org);
|
|
370998
|
+
await github_0.feedback.upsertMultiPartStickyComments(octokit, {
|
|
370999
|
+
owner: org,
|
|
371000
|
+
repo,
|
|
371001
|
+
pullNumber: lastPr.number,
|
|
371002
|
+
baseKind: 'tfworkspace:destroy',
|
|
371003
|
+
bodies: commentBodies,
|
|
371004
|
+
});
|
|
371005
|
+
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
371006
|
}
|
|
370915
371007
|
catch (e) {
|
|
370916
371008
|
operator_src_logger.error(`An error occurred while publishing user feedback for item '${item.kind}/${item.metadata.name}': '${e}'.`);
|
|
@@ -370919,23 +371011,31 @@ ${commentContent}
|
|
|
370919
371011
|
async function publishApply(item, applyOutput, kind) {
|
|
370920
371012
|
const { prNumber, repo, org } = extractPrInfo(item);
|
|
370921
371013
|
const dividedOutput = github_0.pulls.divideCommentIntoChunks(applyOutput, 250);
|
|
370922
|
-
|
|
370923
|
-
|
|
370924
|
-
const
|
|
371014
|
+
const commentBodies = dividedOutput.map((commentContent, index) => {
|
|
371015
|
+
const isMultiPart = dividedOutput.length > 1;
|
|
371016
|
+
const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
|
|
371017
|
+
return `<h1>
|
|
370925
371018
|
<img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Apply Finished
|
|
370926
371019
|
</h1>
|
|
370927
371020
|
<p><b>${kind}: </b>${item.metadata.name}</p>
|
|
370928
371021
|
|
|
370929
371022
|
<details id=github>
|
|
370930
|
-
<summary>APPLY LOGS
|
|
371023
|
+
<summary>APPLY LOGS${partIndicator}</summary>
|
|
370931
371024
|
|
|
370932
371025
|
\`\`\`shell
|
|
370933
371026
|
${commentContent}
|
|
370934
371027
|
\`\`\`
|
|
370935
371028
|
</details>`;
|
|
370936
|
-
|
|
370937
|
-
|
|
370938
|
-
|
|
371029
|
+
});
|
|
371030
|
+
// Get octokit instance for the org to use with upsertMultiPartStickyComments
|
|
371031
|
+
const octokit = await github_0.auth.getOctokitForOrg(org);
|
|
371032
|
+
await github_0.feedback.upsertMultiPartStickyComments(octokit, {
|
|
371033
|
+
owner: org,
|
|
371034
|
+
repo,
|
|
371035
|
+
pullNumber: prNumber,
|
|
371036
|
+
baseKind: `apply:${kind}`,
|
|
371037
|
+
bodies: commentBodies,
|
|
371038
|
+
});
|
|
370939
371039
|
}
|
|
370940
371040
|
function tryCreateErrorSummary(title, errorMsg) {
|
|
370941
371041
|
try {
|
|
@@ -370993,23 +371093,31 @@ ${message}
|
|
|
370993
371093
|
async function publishPlan(item, planOutput, prNumber, repo, org) {
|
|
370994
371094
|
try {
|
|
370995
371095
|
const dividedOutput = github_0.pulls.divideCommentIntoChunks(planOutput, 250);
|
|
370996
|
-
|
|
370997
|
-
|
|
370998
|
-
const
|
|
371096
|
+
const commentBodies = dividedOutput.map((commentContent, index) => {
|
|
371097
|
+
const isMultiPart = dividedOutput.length > 1;
|
|
371098
|
+
const partIndicator = isMultiPart ? ` (Part ${index + 1})` : '';
|
|
371099
|
+
return `<h1>
|
|
370999
371100
|
<img width="25" src="https://raw.githubusercontent.com/firestartr-pro/docs/refs/heads/main/logos/square-nobg.png"> Plan Finished
|
|
371000
371101
|
</h1>
|
|
371001
371102
|
<p><b>TFWorkspace: </b>${item.metadata.name}</p>
|
|
371002
371103
|
|
|
371003
371104
|
<details id=github>
|
|
371004
|
-
<summary>PLAN LOGS
|
|
371105
|
+
<summary>PLAN LOGS${partIndicator}</summary>
|
|
371005
371106
|
|
|
371006
371107
|
\`\`\`shell
|
|
371007
371108
|
${commentContent}
|
|
371008
371109
|
\`\`\`
|
|
371009
371110
|
</details>`;
|
|
371010
|
-
|
|
371011
|
-
|
|
371012
|
-
|
|
371111
|
+
});
|
|
371112
|
+
// Get octokit instance for the org to use with upsertMultiPartStickyComments
|
|
371113
|
+
const octokit = await github_0.auth.getOctokitForOrg(org);
|
|
371114
|
+
await github_0.feedback.upsertMultiPartStickyComments(octokit, {
|
|
371115
|
+
owner: org,
|
|
371116
|
+
repo,
|
|
371117
|
+
pullNumber: prNumber,
|
|
371118
|
+
baseKind: 'tfworkspace:plan',
|
|
371119
|
+
bodies: commentBodies,
|
|
371120
|
+
});
|
|
371013
371121
|
}
|
|
371014
371122
|
catch (e) {
|
|
371015
371123
|
console.error(e);
|
|
@@ -371050,6 +371158,51 @@ function helperCreateCheckRunName(cmd, item) {
|
|
|
371050
371158
|
return `${item.kind} - ${cmd}`;
|
|
371051
371159
|
}
|
|
371052
371160
|
|
|
371161
|
+
;// CONCATENATED MODULE: ../operator/src/utils/index.ts
|
|
371162
|
+
const secretRegex = /\$\{\{ secrets\.(.*?) \}\}/g;
|
|
371163
|
+
function replaceConfigSecrets(config, secrets) {
|
|
371164
|
+
for (const key in config) {
|
|
371165
|
+
if (typeof config[key] === 'object' && config[key] !== null) {
|
|
371166
|
+
// If the property is an object, call this function recursively
|
|
371167
|
+
replaceConfigSecrets(config[key], secrets);
|
|
371168
|
+
}
|
|
371169
|
+
else if (typeof config[key] === 'string') {
|
|
371170
|
+
// If the property is a string and its value is equal to secrets.something,
|
|
371171
|
+
// replace the value with the value of the 'something' key in the secrets object
|
|
371172
|
+
config[key] = config[key].replace(secretRegex, (_, group1) => {
|
|
371173
|
+
if (!secrets[group1]) {
|
|
371174
|
+
throw new Error(`Secret ${group1} not found in secrets`);
|
|
371175
|
+
}
|
|
371176
|
+
return secrets[group1];
|
|
371177
|
+
});
|
|
371178
|
+
}
|
|
371179
|
+
}
|
|
371180
|
+
return config;
|
|
371181
|
+
}
|
|
371182
|
+
function replaceInlineSecrets(inline, secrets) {
|
|
371183
|
+
if (typeof inline !== 'string' || !inline)
|
|
371184
|
+
return inline;
|
|
371185
|
+
let result = inline;
|
|
371186
|
+
result = result.replace(secretRegex, (_, group1) => {
|
|
371187
|
+
if (!secrets[group1]) {
|
|
371188
|
+
throw new Error(`Secret ${group1} not found in secrets`);
|
|
371189
|
+
}
|
|
371190
|
+
return secrets[group1];
|
|
371191
|
+
});
|
|
371192
|
+
return result;
|
|
371193
|
+
}
|
|
371194
|
+
/**
|
|
371195
|
+
* Retrieves a policy annotation value from a custom resource
|
|
371196
|
+
* @param item - The CR to get the policy from
|
|
371197
|
+
* @param annotation - The annotation key to retrieve
|
|
371198
|
+
* @returns The policy value, or undefined if not set
|
|
371199
|
+
*/
|
|
371200
|
+
function getPolicy(item, annotation) {
|
|
371201
|
+
const policy = item.metadata.annotations && item.metadata.annotations[annotation];
|
|
371202
|
+
if (policy)
|
|
371203
|
+
return policy;
|
|
371204
|
+
}
|
|
371205
|
+
|
|
371053
371206
|
;// CONCATENATED MODULE: ../operator/cdktf.ts
|
|
371054
371207
|
|
|
371055
371208
|
|
|
@@ -371059,9 +371212,17 @@ function helperCreateCheckRunName(cmd, item) {
|
|
|
371059
371212
|
|
|
371060
371213
|
|
|
371061
371214
|
|
|
371215
|
+
|
|
371216
|
+
const cdktf_LAST_STATE_PR_ANNOTATION = 'firestartr.dev/last-state-pr';
|
|
371062
371217
|
function processOperation(item, op, handler) {
|
|
371063
371218
|
operator_src_logger.info(`Processing operation ${op} on ${item.kind}/${item.metadata?.name}`);
|
|
371064
371219
|
try {
|
|
371220
|
+
const policy = getPolicy(item, 'firestartr.dev/policy');
|
|
371221
|
+
// If general policy is observe/observe-only, route to observe mode instead of apply
|
|
371222
|
+
if (!policy || policy === 'observe' || policy === 'observe-only') {
|
|
371223
|
+
operator_src_logger.info(`Policy is '${policy || 'not set (default)'}', routing to observe mode`);
|
|
371224
|
+
return cdktf_observe(item, op, handler);
|
|
371225
|
+
}
|
|
371065
371226
|
switch (op) {
|
|
371066
371227
|
case OperationType.UPDATED:
|
|
371067
371228
|
return updated(item, op, handler);
|
|
@@ -371086,6 +371247,11 @@ function processOperation(item, op, handler) {
|
|
|
371086
371247
|
throw e;
|
|
371087
371248
|
}
|
|
371088
371249
|
}
|
|
371250
|
+
async function* cdktf_observe(item, op, handler) {
|
|
371251
|
+
for await (const transition of doPlan(item, op, handler)) {
|
|
371252
|
+
yield transition;
|
|
371253
|
+
}
|
|
371254
|
+
}
|
|
371089
371255
|
async function* created(item, op, handler) {
|
|
371090
371256
|
for await (const transition of doApply(item, op, handler)) {
|
|
371091
371257
|
yield transition;
|
|
@@ -371121,8 +371287,18 @@ async function* sync(item, op, handler) {
|
|
|
371121
371287
|
status: 'False',
|
|
371122
371288
|
message: 'Synth CDKTF',
|
|
371123
371289
|
};
|
|
371124
|
-
|
|
371125
|
-
|
|
371290
|
+
const syncPolicy = getPolicy(item, 'firestartr.dev/sync-policy');
|
|
371291
|
+
if (syncPolicy === 'apply') {
|
|
371292
|
+
operator_src_logger.info(`SYNC OPERATION: applying item ${item.metadata.name} with sync-policy=${syncPolicy}`);
|
|
371293
|
+
for await (const transition of doApply(item, op, handler)) {
|
|
371294
|
+
yield transition;
|
|
371295
|
+
}
|
|
371296
|
+
}
|
|
371297
|
+
else {
|
|
371298
|
+
operator_src_logger.info(`SYNC OPERATION: planning item ${item.metadata.name} with sync-policy=${syncPolicy || 'default (observe)'}`);
|
|
371299
|
+
for await (const transition of doPlan(item, op, handler)) {
|
|
371300
|
+
yield transition;
|
|
371301
|
+
}
|
|
371126
371302
|
}
|
|
371127
371303
|
yield {
|
|
371128
371304
|
item,
|
|
@@ -371161,15 +371337,14 @@ async function* markedToDeletion(item, op, handler) {
|
|
|
371161
371337
|
message: 'Destroying process started',
|
|
371162
371338
|
};
|
|
371163
371339
|
const deps = await handler.resolveReferences();
|
|
371164
|
-
const
|
|
371165
|
-
const statePr = item?.metadata?.annotations?.[annotation];
|
|
371340
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371166
371341
|
const hasStatePr = typeof statePr === 'string' && statePr.trim().length > 0;
|
|
371167
371342
|
if (!hasStatePr) {
|
|
371168
371343
|
operator_src_logger.warn(`CR ${item?.kind ?? 'UnknownKind'}/${item?.metadata?.name ?? 'unknown'} ` +
|
|
371169
|
-
`has no "${
|
|
371344
|
+
`has no "${cdktf_LAST_STATE_PR_ANNOTATION}" annotation; skipping GitHub Check Runs (synth, terraform apply).`);
|
|
371170
371345
|
}
|
|
371171
371346
|
else {
|
|
371172
|
-
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${
|
|
371347
|
+
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${cdktf_LAST_STATE_PR_ANNOTATION}" = ${statePr}`);
|
|
371173
371348
|
}
|
|
371174
371349
|
const destroyOutput = await provisioner.runProvisioner({
|
|
371175
371350
|
mainCr: item,
|
|
@@ -371204,7 +371379,7 @@ async function* markedToDeletion(item, op, handler) {
|
|
|
371204
371379
|
};
|
|
371205
371380
|
await handler.finalize(handler.pluralKind, item.metadata.namespace, item, 'firestartr.dev/finalizer');
|
|
371206
371381
|
await handler.writeTerraformOutputInTfResult(item, output);
|
|
371207
|
-
if (item.metadata.annotations[
|
|
371382
|
+
if (item.metadata.annotations[cdktf_LAST_STATE_PR_ANNOTATION] || false) {
|
|
371208
371383
|
await addDestroyCommitStatus(item, 'success', 'Destroy operation completed', `Terraform Destroy ${item.metadata.name}`);
|
|
371209
371384
|
}
|
|
371210
371385
|
void handler.success();
|
|
@@ -371285,15 +371460,14 @@ async function* doApply(item, op, handler) {
|
|
|
371285
371460
|
}
|
|
371286
371461
|
const deps = await handler.resolveReferences();
|
|
371287
371462
|
operator_src_logger.info(`Item ${item.metadata.name} has the following dependencies: ${deps}`);
|
|
371288
|
-
const
|
|
371289
|
-
const statePr = item?.metadata?.annotations?.[annotation];
|
|
371463
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371290
371464
|
const hasStatePr = typeof statePr === 'string' && statePr.trim().length > 0;
|
|
371291
371465
|
if (!hasStatePr) {
|
|
371292
371466
|
operator_src_logger.warn(`CR ${item?.kind ?? 'UnknownKind'}/${item?.metadata?.name ?? 'unknown'} ` +
|
|
371293
|
-
`has no "${
|
|
371467
|
+
`has no "${cdktf_LAST_STATE_PR_ANNOTATION}" annotation; skipping GitHub Check Runs (synth, terraform apply).`);
|
|
371294
371468
|
}
|
|
371295
371469
|
else {
|
|
371296
|
-
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${
|
|
371470
|
+
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${cdktf_LAST_STATE_PR_ANNOTATION}" = ${statePr}`);
|
|
371297
371471
|
}
|
|
371298
371472
|
const applyOutput = await provisioner.runProvisioner({
|
|
371299
371473
|
mainCr: item,
|
|
@@ -371389,6 +371563,219 @@ async function* doApply(item, op, handler) {
|
|
|
371389
371563
|
}
|
|
371390
371564
|
}
|
|
371391
371565
|
}
|
|
371566
|
+
async function* doPlan(item, op, handler) {
|
|
371567
|
+
let checkRunCtl;
|
|
371568
|
+
try {
|
|
371569
|
+
cleanTerraformState();
|
|
371570
|
+
yield {
|
|
371571
|
+
item,
|
|
371572
|
+
reason: op,
|
|
371573
|
+
type: 'PLANNING',
|
|
371574
|
+
status: 'True',
|
|
371575
|
+
message: 'Planning process started',
|
|
371576
|
+
};
|
|
371577
|
+
const deps = await handler.resolveReferences();
|
|
371578
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371579
|
+
const hasStatePr = typeof statePr === 'string' && statePr.trim().length > 0;
|
|
371580
|
+
if (!hasStatePr) {
|
|
371581
|
+
operator_src_logger.warn(`CR ${item?.kind ?? 'UnknownKind'}/${item?.metadata?.name ?? 'unknown'} ` +
|
|
371582
|
+
`has no "${cdktf_LAST_STATE_PR_ANNOTATION}" annotation; skipping GitHub Check Runs for plan.`);
|
|
371583
|
+
}
|
|
371584
|
+
else {
|
|
371585
|
+
operator_src_logger.debug(`CR ${item.kind}/${item.metadata.name} uses "${cdktf_LAST_STATE_PR_ANNOTATION}" = ${statePr}`);
|
|
371586
|
+
await addPlanStatusCheck(statePr, 'CDKTF plan in progress...');
|
|
371587
|
+
}
|
|
371588
|
+
// Run provisioner in plan-only mode
|
|
371589
|
+
const planResult = await provisioner.runProvisioner({ mainCr: item, deps }, {
|
|
371590
|
+
planOnly: true,
|
|
371591
|
+
delete: 'deletionTimestamp' in item.metadata,
|
|
371592
|
+
...(hasStatePr
|
|
371593
|
+
? {
|
|
371594
|
+
logStreamCallbacksCDKTF: {
|
|
371595
|
+
prepare: async () => {
|
|
371596
|
+
checkRunCtl = await GHCheckRun('synth', item);
|
|
371597
|
+
return checkRunCtl;
|
|
371598
|
+
},
|
|
371599
|
+
},
|
|
371600
|
+
logStreamCallbacksTF: {
|
|
371601
|
+
prepare: async () => {
|
|
371602
|
+
checkRunCtl = await GHCheckRun('plan', item);
|
|
371603
|
+
return checkRunCtl;
|
|
371604
|
+
},
|
|
371605
|
+
},
|
|
371606
|
+
}
|
|
371607
|
+
: {}),
|
|
371608
|
+
});
|
|
371609
|
+
const planOutput = planResult?.output || '';
|
|
371610
|
+
// Parse terraform plan output to detect changes
|
|
371611
|
+
// Handles multiple Terraform output formats and versions
|
|
371612
|
+
const hasChanges = detectPlanChanges(planOutput);
|
|
371613
|
+
if (hasChanges) {
|
|
371614
|
+
yield {
|
|
371615
|
+
item,
|
|
371616
|
+
reason: op,
|
|
371617
|
+
type: 'OUT_OF_SYNC',
|
|
371618
|
+
status: 'True',
|
|
371619
|
+
message: 'Plan has changes',
|
|
371620
|
+
};
|
|
371621
|
+
yield {
|
|
371622
|
+
item,
|
|
371623
|
+
reason: op,
|
|
371624
|
+
type: 'PROVISIONED',
|
|
371625
|
+
status: 'False',
|
|
371626
|
+
message: 'Plan has changes',
|
|
371627
|
+
};
|
|
371628
|
+
}
|
|
371629
|
+
else {
|
|
371630
|
+
yield {
|
|
371631
|
+
item,
|
|
371632
|
+
reason: op,
|
|
371633
|
+
type: 'OUT_OF_SYNC',
|
|
371634
|
+
status: 'False',
|
|
371635
|
+
message: 'Plan has no changes',
|
|
371636
|
+
};
|
|
371637
|
+
yield {
|
|
371638
|
+
item,
|
|
371639
|
+
reason: op,
|
|
371640
|
+
type: 'PROVISIONED',
|
|
371641
|
+
status: 'True',
|
|
371642
|
+
message: 'Plan has no changes',
|
|
371643
|
+
};
|
|
371644
|
+
}
|
|
371645
|
+
// Store plan details for later reference
|
|
371646
|
+
yield {
|
|
371647
|
+
item,
|
|
371648
|
+
reason: op,
|
|
371649
|
+
type: 'LAST_PLAN_DETAILS',
|
|
371650
|
+
status: 'Unknown',
|
|
371651
|
+
message: planOutput,
|
|
371652
|
+
};
|
|
371653
|
+
yield {
|
|
371654
|
+
item,
|
|
371655
|
+
reason: op,
|
|
371656
|
+
type: 'PLANNING',
|
|
371657
|
+
status: 'False',
|
|
371658
|
+
message: 'Planning process finished',
|
|
371659
|
+
};
|
|
371660
|
+
if (hasStatePr) {
|
|
371661
|
+
await addPlanStatusCheck(statePr, hasChanges ? 'Plan has changes' : 'Plan has no changes', 'completed');
|
|
371662
|
+
}
|
|
371663
|
+
}
|
|
371664
|
+
catch (e) {
|
|
371665
|
+
operator_src_logger.error(`CDKTF plan failed: ${e}`);
|
|
371666
|
+
if (checkRunCtl) {
|
|
371667
|
+
checkRunCtl.fnOnError(e);
|
|
371668
|
+
}
|
|
371669
|
+
yield {
|
|
371670
|
+
item,
|
|
371671
|
+
reason: op,
|
|
371672
|
+
type: 'ERROR',
|
|
371673
|
+
status: 'True',
|
|
371674
|
+
message: e.toString(),
|
|
371675
|
+
};
|
|
371676
|
+
yield {
|
|
371677
|
+
item,
|
|
371678
|
+
reason: op,
|
|
371679
|
+
type: 'PLANNING',
|
|
371680
|
+
status: 'False',
|
|
371681
|
+
message: e.toString(),
|
|
371682
|
+
};
|
|
371683
|
+
yield {
|
|
371684
|
+
item,
|
|
371685
|
+
reason: op,
|
|
371686
|
+
type: 'PROVISIONED',
|
|
371687
|
+
status: 'False',
|
|
371688
|
+
message: e.toString(),
|
|
371689
|
+
};
|
|
371690
|
+
const statePr = item?.metadata?.annotations?.[cdktf_LAST_STATE_PR_ANNOTATION];
|
|
371691
|
+
if (statePr) {
|
|
371692
|
+
const summaryText = tryCreateErrorSummary('CDKTF Plan failed', e);
|
|
371693
|
+
await addPlanStatusCheck(statePr, summaryText, 'completed', true);
|
|
371694
|
+
}
|
|
371695
|
+
await handler.writeTerraformOutputInTfResult(item, e);
|
|
371696
|
+
void handler.error();
|
|
371697
|
+
}
|
|
371698
|
+
}
|
|
371699
|
+
/**
|
|
371700
|
+
* Detects if a Terraform plan output contains changes
|
|
371701
|
+
* Handles multiple Terraform versions and output formats
|
|
371702
|
+
* @param planOutput - The text output from terraform plan
|
|
371703
|
+
* @returns true if changes are detected, false otherwise
|
|
371704
|
+
*/
|
|
371705
|
+
function detectPlanChanges(planOutput) {
|
|
371706
|
+
if (!planOutput || planOutput.trim().length === 0) {
|
|
371707
|
+
return false;
|
|
371708
|
+
}
|
|
371709
|
+
// Normalize the output for consistent matching
|
|
371710
|
+
const normalized = planOutput.toLowerCase();
|
|
371711
|
+
// Pattern 1: "Plan: X to add, Y to change, Z to destroy"
|
|
371712
|
+
// Matches: "Plan: 1 to add, 0 to change, 0 to destroy"
|
|
371713
|
+
const planPattern = /plan:\s*(\d+)\s+to\s+add,\s*(\d+)\s+to\s+change,\s*(\d+)\s+to\s+destroy/i;
|
|
371714
|
+
const planMatch = planOutput.match(planPattern);
|
|
371715
|
+
if (planMatch) {
|
|
371716
|
+
const add = Number(planMatch[1]);
|
|
371717
|
+
const change = Number(planMatch[2]);
|
|
371718
|
+
const destroy = Number(planMatch[3]);
|
|
371719
|
+
if (add > 0 || change > 0 || destroy > 0) {
|
|
371720
|
+
return true;
|
|
371721
|
+
}
|
|
371722
|
+
// Explicitly found "Plan:" with 0/0/0 - no changes
|
|
371723
|
+
return false;
|
|
371724
|
+
}
|
|
371725
|
+
// Pattern 2: Individual change indicators
|
|
371726
|
+
// Handles variations like "1 to add", "2 to change", "3 to destroy"
|
|
371727
|
+
const hasAdditions = /\d+\s+to\s+add/i.test(planOutput);
|
|
371728
|
+
const hasChanges = /\d+\s+to\s+change/i.test(planOutput);
|
|
371729
|
+
const hasDestructions = /\d+\s+to\s+destroy/i.test(planOutput);
|
|
371730
|
+
const hasImports = /\d+\s+to\s+import/i.test(planOutput);
|
|
371731
|
+
if (hasAdditions || hasChanges || hasDestructions || hasImports) {
|
|
371732
|
+
return true;
|
|
371733
|
+
}
|
|
371734
|
+
// Pattern 3: Resource-level change indicators
|
|
371735
|
+
// Matches: "# resource will be created", "# resource will be updated", etc.
|
|
371736
|
+
const resourceChangePatterns = [
|
|
371737
|
+
/will\s+be\s+(created|destroyed|updated|replaced)/i,
|
|
371738
|
+
/must\s+be\s+(created|destroyed|updated|replaced)/i,
|
|
371739
|
+
/#.*\s+(create|destroy|update|replace)/i,
|
|
371740
|
+
];
|
|
371741
|
+
for (const pattern of resourceChangePatterns) {
|
|
371742
|
+
if (pattern.test(planOutput)) {
|
|
371743
|
+
return true;
|
|
371744
|
+
}
|
|
371745
|
+
}
|
|
371746
|
+
// Pattern 4: Action symbols in plan output
|
|
371747
|
+
// Terraform uses symbols like +, -, ~, -/+ to indicate changes
|
|
371748
|
+
const actionSymbols = [
|
|
371749
|
+
/^\s*[+]\s+/m,
|
|
371750
|
+
/^\s*[-]\s+/m,
|
|
371751
|
+
/^\s*[~]\s+/m,
|
|
371752
|
+
/^\s*[-][/][+]\s+/m, // Replace
|
|
371753
|
+
];
|
|
371754
|
+
for (const pattern of actionSymbols) {
|
|
371755
|
+
if (pattern.test(planOutput)) {
|
|
371756
|
+
return true;
|
|
371757
|
+
}
|
|
371758
|
+
}
|
|
371759
|
+
// Pattern 5: No changes messages (inverse check)
|
|
371760
|
+
const noChangesPatterns = [
|
|
371761
|
+
/no\s+changes/i,
|
|
371762
|
+
/infrastructure\s+is\s+up[-\s]to[-\s]date/i,
|
|
371763
|
+
/your\s+infrastructure\s+matches\s+the\s+configuration/i,
|
|
371764
|
+
/0\s+to\s+add,\s*0\s+to\s+change,\s*0\s+to\s+destroy/i,
|
|
371765
|
+
];
|
|
371766
|
+
for (const pattern of noChangesPatterns) {
|
|
371767
|
+
if (pattern.test(planOutput)) {
|
|
371768
|
+
return false;
|
|
371769
|
+
}
|
|
371770
|
+
}
|
|
371771
|
+
// If we find "Plan:" keyword but couldn't parse it, log a warning and assume no changes
|
|
371772
|
+
if (normalized.includes('plan:')) {
|
|
371773
|
+
operator_src_logger.warn('Found "Plan:" in output but could not parse change counts. Assuming no changes.');
|
|
371774
|
+
return false;
|
|
371775
|
+
}
|
|
371776
|
+
// Default: assume no changes if we can't detect any
|
|
371777
|
+
return false;
|
|
371778
|
+
}
|
|
371392
371779
|
function cleanTerraformState() {
|
|
371393
371780
|
external_fs_.rmSync('/library/packages/provisioner/cdktf.out', {
|
|
371394
371781
|
recursive: true,
|
|
@@ -372388,40 +372775,6 @@ function tf_checkrun_helperCreateCheckRunName(cmd) {
|
|
|
372388
372775
|
return `TFWorkspace - ${cmd}`;
|
|
372389
372776
|
}
|
|
372390
372777
|
|
|
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
372778
|
;// CONCATENATED MODULE: ../operator/src/tfworkspaces/process-operation.ts
|
|
372426
372779
|
|
|
372427
372780
|
|
|
@@ -372612,11 +372965,6 @@ async function* process_operation_renamed(item, op, handler) {
|
|
|
372612
372965
|
yield transition;
|
|
372613
372966
|
}
|
|
372614
372967
|
}
|
|
372615
|
-
function getPolicy(item, annotation) {
|
|
372616
|
-
const policy = item.metadata.annotations && item.metadata.annotations[annotation];
|
|
372617
|
-
if (policy)
|
|
372618
|
-
return policy;
|
|
372619
|
-
}
|
|
372620
372968
|
async function* process_operation_updated(item, op, handler) {
|
|
372621
372969
|
for await (const transition of process_operation_doApply(item, op, handler)) {
|
|
372622
372970
|
yield transition;
|
|
@@ -373260,7 +373608,7 @@ const processOperationPlan_TF_PROJECTS_PATH = '/tmp/tfworkspaces';
|
|
|
373260
373608
|
function processOperationPlan(item, op, handler) {
|
|
373261
373609
|
try {
|
|
373262
373610
|
processOperationPlan_clearLocalTfProjects();
|
|
373263
|
-
const policy =
|
|
373611
|
+
const policy = getPolicy(item, 'firestartr.dev/policy');
|
|
373264
373612
|
if (policy === 'observe' || policy === 'apply') {
|
|
373265
373613
|
return processOperationPlan_plan(item, op, handler);
|
|
373266
373614
|
}
|
|
@@ -373707,12 +374055,6 @@ function processOperationPlan_getErrorOutputMessage(cr, key, ref) {
|
|
|
373707
374055
|
throw new Error(`❌ Source ${cr.spec.source} not supported`);
|
|
373708
374056
|
}
|
|
373709
374057
|
}
|
|
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
374058
|
|
|
373717
374059
|
;// CONCATENATED MODULE: ../operator/src/ctx.ts
|
|
373718
374060
|
class Ctx {
|