@firestartr/cli 2.5.0-snapshot-2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +263 -19
- package/build/packages/gh_provisioner/src/entities/ghrepo/helpers/branch_protections.d.ts +7 -0
- package/build/packages/gh_provisioner/src/entities/ghrepo/helpers/index.d.ts +1 -0
- package/build/packages/gh_provisioner/src/entities/ghrepo/index.d.ts +1 -0
- package/build/packages/operator/src/definitions.d.ts +15 -1
- package/build/packages/operator/src/processItem.blocks.d.ts +40 -0
- package/build/packages/operator/src/processItem.d.ts +2 -1
- package/build/packages/operator/src/processItem.slot.d.ts +5 -2
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -291270,6 +291270,27 @@ function definitions_getPluralFromKind(kind) {
|
|
|
291270
291270
|
const plural = Object.keys(kindPluralMap).find((key) => kindPluralMap[key] === kind);
|
|
291271
291271
|
return plural;
|
|
291272
291272
|
}
|
|
291273
|
+
// ----------------------------------------------------
|
|
291274
|
+
// Operations, workitems and handlers definitions
|
|
291275
|
+
// ----------------------------------------------------
|
|
291276
|
+
/**
|
|
291277
|
+
* Helper to extract the canonical identity (metadata.uid) from a WorkItem or its item.
|
|
291278
|
+
*
|
|
291279
|
+
* Use this helper when you need a stable identity key for WorkItems, e.g. for
|
|
291280
|
+
* in-memory deferred-scheduling bookkeeping.
|
|
291281
|
+
*
|
|
291282
|
+
* Note: other subsystems may still use kind/namespace/name keys; this helper is
|
|
291283
|
+
* specifically intended for UID-based WorkItem identity.
|
|
291284
|
+
* Any future change to identity logic MUST be made here and nowhere else.
|
|
291285
|
+
*
|
|
291286
|
+
* Returns undefined if .metadata.uid is missing so scheduler/bookkeeping paths
|
|
291287
|
+
* can safely short-circuit instead of throwing and aborting an entire pass.
|
|
291288
|
+
*/
|
|
291289
|
+
function getWorkItemIdentity(wi) {
|
|
291290
|
+
// Support either .item.metadata.uid or direct .metadata.uid for future extensibility
|
|
291291
|
+
const meta = wi.item && wi.item.metadata ? wi.item.metadata : wi.metadata;
|
|
291292
|
+
return meta && meta.uid ? meta.uid : undefined;
|
|
291293
|
+
}
|
|
291273
291294
|
var OperationType;
|
|
291274
291295
|
(function (OperationType) {
|
|
291275
291296
|
OperationType["RENAMED"] = "RENAMED";
|
|
@@ -293513,6 +293534,134 @@ function fdummies_fWait(ms) {
|
|
|
293513
293534
|
});
|
|
293514
293535
|
}
|
|
293515
293536
|
|
|
293537
|
+
;// CONCATENATED MODULE: ../operator/src/processItem.blocks.ts
|
|
293538
|
+
// processItem.blocks.ts
|
|
293539
|
+
// Responsible for all in-memory deferred-scheduling bookkeeping for blocked parent deletions.
|
|
293540
|
+
//
|
|
293541
|
+
// Always extract WorkItem identity for all in-memory maps and keys by calling
|
|
293542
|
+
// getWorkItemIdentity() from definitions.ts, and NOT by constructing your own key.
|
|
293543
|
+
// This ensures spec compliance and future maintainability.
|
|
293544
|
+
//
|
|
293545
|
+
// Does NOT detect "blocked" state (caller must supply outcome). Purely key/value scheduler-local state logic per spec.
|
|
293546
|
+
|
|
293547
|
+
// Only use getWorkItemIdentity(item) for identity bookkeeping and maps.
|
|
293548
|
+
// --- Config: Deferral Policy ---
|
|
293549
|
+
/**
|
|
293550
|
+
* Maximum number of blocked attempts allowed before an item is moved to the deferred segment.
|
|
293551
|
+
* An item becomes deferred once its blocked-attempt count exceeds this value.
|
|
293552
|
+
*/
|
|
293553
|
+
const MAX_BLOCKED_ATTEMPTS_BEFORE_DEFER = 5;
|
|
293554
|
+
// Initial supported parent kind(s): extensible for future cases
|
|
293555
|
+
const SUPPORTED_PARENT_KINDS = new Set(['FirestartrGithubRepository']);
|
|
293556
|
+
// --- Bookkeeper Class ---
|
|
293557
|
+
/**
|
|
293558
|
+
* Encapsulates all deferred-scheduling bookkeeping state for one scheduler queue.
|
|
293559
|
+
* Instantiate once per queue (alongside processItemSlotsManager) inside loop().
|
|
293560
|
+
*/
|
|
293561
|
+
class DeferredSchedulingBookkeeper {
|
|
293562
|
+
constructor() {
|
|
293563
|
+
this._blockedAttempts = new Map();
|
|
293564
|
+
this._deferredEntryOrder = new Map();
|
|
293565
|
+
this._deferredOrderCounter = 0;
|
|
293566
|
+
}
|
|
293567
|
+
// --- Applicability Logic ---
|
|
293568
|
+
/**
|
|
293569
|
+
* Returns true only for supported parent kinds AND only for deletion operations.
|
|
293570
|
+
* Per spec Definition 2: applicable when operation is MARKED_TO_DELETION,
|
|
293571
|
+
* or RETRY with metadata.deletionTimestamp set.
|
|
293572
|
+
*/
|
|
293573
|
+
isDeferredSchedulingApplicable(item) {
|
|
293574
|
+
const kind = item.item && item.item.kind ? item.item.kind : item.kind;
|
|
293575
|
+
if (!SUPPORTED_PARENT_KINDS.has(kind))
|
|
293576
|
+
return false;
|
|
293577
|
+
const op = item.operation;
|
|
293578
|
+
if (op === OperationType.MARKED_TO_DELETION)
|
|
293579
|
+
return true;
|
|
293580
|
+
if (op === OperationType.RETRY && item.item?.metadata?.deletionTimestamp)
|
|
293581
|
+
return true;
|
|
293582
|
+
return false;
|
|
293583
|
+
}
|
|
293584
|
+
// --- Bookkeeping API ---
|
|
293585
|
+
/**
|
|
293586
|
+
* Increments block counter for item (only call when item has been detected as blocked).
|
|
293587
|
+
* Returns new value. Promotes item to deferred segment if threshold crossed.
|
|
293588
|
+
*/
|
|
293589
|
+
incrementBlockedAttempt(item) {
|
|
293590
|
+
if (!this.isDeferredSchedulingApplicable(item))
|
|
293591
|
+
return 0;
|
|
293592
|
+
const id = getWorkItemIdentity(item);
|
|
293593
|
+
if (id === undefined)
|
|
293594
|
+
return 0;
|
|
293595
|
+
const prev = this._blockedAttempts.get(id) || 0;
|
|
293596
|
+
const next = prev + 1;
|
|
293597
|
+
this._blockedAttempts.set(id, next);
|
|
293598
|
+
if (next > MAX_BLOCKED_ATTEMPTS_BEFORE_DEFER &&
|
|
293599
|
+
!this._deferredEntryOrder.has(id)) {
|
|
293600
|
+
this._deferredEntryOrder.set(id, ++this._deferredOrderCounter);
|
|
293601
|
+
}
|
|
293602
|
+
return next;
|
|
293603
|
+
}
|
|
293604
|
+
getBlockedAttempts(item) {
|
|
293605
|
+
if (!this.isDeferredSchedulingApplicable(item))
|
|
293606
|
+
return 0;
|
|
293607
|
+
const id = getWorkItemIdentity(item);
|
|
293608
|
+
if (id === undefined)
|
|
293609
|
+
return 0;
|
|
293610
|
+
return this._blockedAttempts.get(id) || 0;
|
|
293611
|
+
}
|
|
293612
|
+
isDeferred(item) {
|
|
293613
|
+
if (!this.isDeferredSchedulingApplicable(item))
|
|
293614
|
+
return false;
|
|
293615
|
+
return this.getBlockedAttempts(item) > MAX_BLOCKED_ATTEMPTS_BEFORE_DEFER;
|
|
293616
|
+
}
|
|
293617
|
+
getDeferredOrder(item) {
|
|
293618
|
+
if (!this.isDeferredSchedulingApplicable(item))
|
|
293619
|
+
return undefined;
|
|
293620
|
+
const id = getWorkItemIdentity(item);
|
|
293621
|
+
if (id === undefined)
|
|
293622
|
+
return undefined;
|
|
293623
|
+
return this._deferredEntryOrder.get(id);
|
|
293624
|
+
}
|
|
293625
|
+
removeBookkeeping(item) {
|
|
293626
|
+
if (!this.isDeferredSchedulingApplicable(item))
|
|
293627
|
+
return;
|
|
293628
|
+
const id = getWorkItemIdentity(item);
|
|
293629
|
+
if (id === undefined)
|
|
293630
|
+
return;
|
|
293631
|
+
this._blockedAttempts.delete(id);
|
|
293632
|
+
this._deferredEntryOrder.delete(id);
|
|
293633
|
+
}
|
|
293634
|
+
// --- Queue Partitioning ---
|
|
293635
|
+
/**
|
|
293636
|
+
* Splits queue into non-deferred and deferred, preserving original order,
|
|
293637
|
+
* but sorts deferred by stable insertion order.
|
|
293638
|
+
*/
|
|
293639
|
+
partitionQueueByDeferred(queue) {
|
|
293640
|
+
const nonDeferred = [];
|
|
293641
|
+
const deferred = [];
|
|
293642
|
+
for (const item of queue) {
|
|
293643
|
+
if (this.isDeferredSchedulingApplicable(item) && this.isDeferred(item)) {
|
|
293644
|
+
deferred.push(item);
|
|
293645
|
+
}
|
|
293646
|
+
else {
|
|
293647
|
+
nonDeferred.push(item);
|
|
293648
|
+
}
|
|
293649
|
+
}
|
|
293650
|
+
deferred.sort((a, b) => {
|
|
293651
|
+
const orderA = this.getDeferredOrder(a) || 0;
|
|
293652
|
+
const orderB = this.getDeferredOrder(b) || 0;
|
|
293653
|
+
return orderA - orderB;
|
|
293654
|
+
});
|
|
293655
|
+
return { nonDeferred, deferred };
|
|
293656
|
+
}
|
|
293657
|
+
// --- TESTING / DEBUG ---
|
|
293658
|
+
clearAllBookkeeping() {
|
|
293659
|
+
this._blockedAttempts.clear();
|
|
293660
|
+
this._deferredEntryOrder.clear();
|
|
293661
|
+
this._deferredOrderCounter = 0;
|
|
293662
|
+
}
|
|
293663
|
+
}
|
|
293664
|
+
|
|
293516
293665
|
;// CONCATENATED MODULE: ../operator/src/processItem.debug.ts
|
|
293517
293666
|
|
|
293518
293667
|
|
|
@@ -294003,12 +294152,12 @@ async function startCRStates(meter, kindList, namespace) {
|
|
|
294003
294152
|
|
|
294004
294153
|
|
|
294005
294154
|
|
|
294006
|
-
function initProcessItemsSlots(nSlots, initMetrics = true) {
|
|
294155
|
+
function initProcessItemsSlots(nSlots, initMetrics = true, onWorkItemBlockedByHandler) {
|
|
294007
294156
|
operator_src_logger.info(`Initializing ${nSlots} processing slots...`);
|
|
294008
|
-
return new ProcessItemSlots(nSlots, initMetrics);
|
|
294157
|
+
return new ProcessItemSlots(nSlots, initMetrics, onWorkItemBlockedByHandler);
|
|
294009
294158
|
}
|
|
294010
294159
|
class ProcessItemSlots {
|
|
294011
|
-
constructor(nSlots, initMetrics) {
|
|
294160
|
+
constructor(nSlots, initMetrics, onWorkItemBlockedByHandler) {
|
|
294012
294161
|
this._guardRails = new GuardRails();
|
|
294013
294162
|
// let's init the slots
|
|
294014
294163
|
this._nSlots = nSlots;
|
|
@@ -294025,6 +294174,7 @@ class ProcessItemSlots {
|
|
|
294025
294174
|
slot.actions = {
|
|
294026
294175
|
blockItem: (item) => this._guardRails.block(item),
|
|
294027
294176
|
unblockItem: (item) => this._guardRails.unblock(item),
|
|
294177
|
+
onWorkItemBlockedByHandler,
|
|
294028
294178
|
};
|
|
294029
294179
|
return slot;
|
|
294030
294180
|
});
|
|
@@ -294135,6 +294285,9 @@ class ProcessItemSlot {
|
|
|
294135
294285
|
if ('needsBlocking' in workItem.handler &&
|
|
294136
294286
|
workItem.handler.needsBlocking(item, workItem.operation)) {
|
|
294137
294287
|
operator_src_logger.debug(`Item ${item.kind}/${item.metadata.namespace} needs blocking`);
|
|
294288
|
+
// Fire-and-forget: the callback is synchronous bookkeeping only;
|
|
294289
|
+
// no async side effects are expected from this callback.
|
|
294290
|
+
this._actions?.onWorkItemBlockedByHandler?.(workItem);
|
|
294138
294291
|
return;
|
|
294139
294292
|
}
|
|
294140
294293
|
workItem.workStatus = WorkStatus.PROCESSING;
|
|
@@ -294156,6 +294309,7 @@ class ProcessItemSlot {
|
|
|
294156
294309
|
|
|
294157
294310
|
|
|
294158
294311
|
|
|
294312
|
+
|
|
294159
294313
|
const queue = [];
|
|
294160
294314
|
const WEIGHTS = {
|
|
294161
294315
|
RENAMED: 15,
|
|
@@ -294276,12 +294430,26 @@ async function processItem(workItem) {
|
|
|
294276
294430
|
async function processItem_loop() {
|
|
294277
294431
|
loopWorkItemDebug(queue);
|
|
294278
294432
|
let podIsTerminating = false;
|
|
294279
|
-
const
|
|
294280
|
-
const
|
|
294281
|
-
|
|
294282
|
-
|
|
294283
|
-
|
|
294284
|
-
|
|
294433
|
+
const deferredBookkeeper = new DeferredSchedulingBookkeeper();
|
|
294434
|
+
const processItemSlotsManager = initProcessItemsSlots(MAX_SLOTS, true, (w) => deferredBookkeeper.incrementBlockedAttempt(w));
|
|
294435
|
+
if (process.env.GARBAGE_QUEUE_COLLECTOR) {
|
|
294436
|
+
void workItemGarbageCollector(queue, deferredBookkeeper);
|
|
294437
|
+
}
|
|
294438
|
+
const nextWorkItem = () => {
|
|
294439
|
+
// First, sort the queue and partition it for deferred scheduling.
|
|
294440
|
+
const sorted = sortQueue(queue);
|
|
294441
|
+
const { nonDeferred, deferred } = deferredBookkeeper.partitionQueueByDeferred(sorted);
|
|
294442
|
+
// Helper for selection logic
|
|
294443
|
+
function pickEligible(arr) {
|
|
294444
|
+
return arr
|
|
294445
|
+
.filter((w) => !w.isBlocked &&
|
|
294446
|
+
!w.isPicked &&
|
|
294447
|
+
!processItemSlotsManager.isWorkItemBlocked(w))
|
|
294448
|
+
.find((w) => w.workStatus === WorkStatus.PENDING);
|
|
294449
|
+
}
|
|
294450
|
+
// Always prefer non-deferred, only defer if absolutely nothing eligible
|
|
294451
|
+
return pickEligible(nonDeferred) || pickEligible(deferred);
|
|
294452
|
+
};
|
|
294285
294453
|
initSignalsHandler(new Map([['SIGTERM', () => (podIsTerminating = true)]]));
|
|
294286
294454
|
operator_src_logger.info(`
|
|
294287
294455
|
------- Processor main loop started with a maximum of '${MAX_SLOTS}' concurrent slots to process items. -------
|
|
@@ -294358,24 +294526,23 @@ function processItem_wait(t = 2000) {
|
|
|
294358
294526
|
* Periodically checks the queue for finished WorkItems and removes them
|
|
294359
294527
|
* @param {WorkItem[]} queue - Queue of WorkItems
|
|
294360
294528
|
*/
|
|
294361
|
-
async function workItemGarbageCollector(queue) {
|
|
294529
|
+
async function workItemGarbageCollector(queue, bookkeeper) {
|
|
294362
294530
|
while (1) {
|
|
294363
294531
|
operator_src_logger.debug(`The garbage collector processed '${queue.length}' work items.`);
|
|
294364
|
-
for (
|
|
294532
|
+
for (let i = queue.length - 1; i >= 0; i--) {
|
|
294533
|
+
const wi = queue[i];
|
|
294365
294534
|
if (wi.workStatus === WorkStatus.FINISHED) {
|
|
294535
|
+
bookkeeper?.removeBookkeeping(wi);
|
|
294366
294536
|
// Because the queue is a constant, we cannot reassign it, instead we
|
|
294367
294537
|
// use splice which modifies the array in place
|
|
294368
294538
|
//wi.onDelete()
|
|
294369
|
-
queue.splice(
|
|
294539
|
+
queue.splice(i, 1);
|
|
294370
294540
|
}
|
|
294371
294541
|
}
|
|
294372
294542
|
operator_src_logger.debug(`The garbage collector finished its run, leaving '${queue.length}' work items in the queue.`);
|
|
294373
294543
|
await processItem_wait(10 * 1000);
|
|
294374
294544
|
}
|
|
294375
294545
|
}
|
|
294376
|
-
if (process.env.GARBAGE_QUEUE_COLLECTOR) {
|
|
294377
|
-
void workItemGarbageCollector(queue);
|
|
294378
|
-
}
|
|
294379
294546
|
|
|
294380
294547
|
;// CONCATENATED MODULE: ../terraform_provisioner/src/tf/analyzer.ts
|
|
294381
294548
|
|
|
@@ -298337,8 +298504,8 @@ const MODULES = {
|
|
|
298337
298504
|
},
|
|
298338
298505
|
FirestartrGithubRepository: {
|
|
298339
298506
|
module: 'git::https://github.com/prefapp/tfm.git//modules/github-repo',
|
|
298340
|
-
// github-repo-v0.
|
|
298341
|
-
ref: '
|
|
298507
|
+
// github-repo-v0.5.1
|
|
298508
|
+
ref: '67c7afaec38c1fdc9f1928090c181ef310fb81ec',
|
|
298342
298509
|
},
|
|
298343
298510
|
FirestartrGithubRepositoryFeature: {
|
|
298344
298511
|
module: 'git::https://github.com/prefapp/tfm.git//modules/github-files-set',
|
|
@@ -299056,6 +299223,48 @@ function checkIfLabelExists(labelName, repoIssuesList) {
|
|
|
299056
299223
|
return repoIssuesList.some((label) => label.name === labelName);
|
|
299057
299224
|
}
|
|
299058
299225
|
|
|
299226
|
+
;// CONCATENATED MODULE: ../gh_provisioner/src/entities/ghrepo/helpers/branch_protections.ts
|
|
299227
|
+
|
|
299228
|
+
|
|
299229
|
+
/**
|
|
299230
|
+
* Adds branch protection config to the synthesized Terraform config,
|
|
299231
|
+
* preserving legacy field semantics exactly (empty lists, explicit booleans, names).
|
|
299232
|
+
* @param entity The EntityGHRepo instance
|
|
299233
|
+
*/
|
|
299234
|
+
function provisionBranchProtections(entity) {
|
|
299235
|
+
const protections = entity.cr.spec.branchProtections;
|
|
299236
|
+
if (!protections || !Array.isArray(protections) || protections.length === 0) {
|
|
299237
|
+
return;
|
|
299238
|
+
}
|
|
299239
|
+
for (const protection of protections) {
|
|
299240
|
+
// This shape should match the compatible Terraform contract
|
|
299241
|
+
const output = {};
|
|
299242
|
+
// Only emit legacy fields in allowed order
|
|
299243
|
+
output.branch = protection.branch;
|
|
299244
|
+
output.statusChecks =
|
|
299245
|
+
'statusChecks' in protection ? (protection.statusChecks ?? []) : [];
|
|
299246
|
+
if ('requiredReviewersCount' in protection)
|
|
299247
|
+
output.requiredReviewersCount = protection.requiredReviewersCount;
|
|
299248
|
+
if ('requiredCodeownersReviewers' in protection)
|
|
299249
|
+
output.requiredCodeownersReviewers =
|
|
299250
|
+
protection.requiredCodeownersReviewers;
|
|
299251
|
+
if ('enforceAdmins' in protection)
|
|
299252
|
+
output.enforceAdmins = protection.enforceAdmins;
|
|
299253
|
+
if ('requireSignedCommits' in protection)
|
|
299254
|
+
output.requireSignedCommits = protection.requireSignedCommits;
|
|
299255
|
+
if ('requireConversationResolution' in protection)
|
|
299256
|
+
output.requireConversationResolution =
|
|
299257
|
+
protection.requireConversationResolution;
|
|
299258
|
+
// Only keep fields that are present, including explicit false/empty
|
|
299259
|
+
gh_provisioner_src_logger.debug(`[gh-provisioner] Adding branch protection config: ${JSON.stringify(output)}`);
|
|
299260
|
+
entity.patchData({
|
|
299261
|
+
op: PatchOperations.add,
|
|
299262
|
+
path: '/config/branch_protections/-',
|
|
299263
|
+
value: output,
|
|
299264
|
+
});
|
|
299265
|
+
}
|
|
299266
|
+
}
|
|
299267
|
+
|
|
299059
299268
|
;// CONCATENATED MODULE: ../gh_provisioner/src/entities/ghrepo/helpers/index.ts
|
|
299060
299269
|
|
|
299061
299270
|
|
|
@@ -299064,6 +299273,7 @@ function checkIfLabelExists(labelName, repoIssuesList) {
|
|
|
299064
299273
|
|
|
299065
299274
|
|
|
299066
299275
|
|
|
299276
|
+
|
|
299067
299277
|
;// CONCATENATED MODULE: ../gh_provisioner/src/entities/ghrepo/post/additional_branches.ts
|
|
299068
299278
|
|
|
299069
299279
|
|
|
@@ -299130,6 +299340,9 @@ async function provisionRegularBranch(repo, branchName, sourceBranch, org) {
|
|
|
299130
299340
|
|
|
299131
299341
|
|
|
299132
299342
|
class EntityGHRepo extends base_Entity {
|
|
299343
|
+
escapeTerraformBranchName(value) {
|
|
299344
|
+
return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
299345
|
+
}
|
|
299133
299346
|
constructor(artifact) {
|
|
299134
299347
|
super(artifact, {
|
|
299135
299348
|
config: {
|
|
@@ -299138,6 +299351,7 @@ class EntityGHRepo extends base_Entity {
|
|
|
299138
299351
|
teams: [],
|
|
299139
299352
|
collaborators: [],
|
|
299140
299353
|
labels: [],
|
|
299354
|
+
branch_protections: [],
|
|
299141
299355
|
},
|
|
299142
299356
|
});
|
|
299143
299357
|
}
|
|
@@ -299192,6 +299406,8 @@ class EntityGHRepo extends base_Entity {
|
|
|
299192
299406
|
await provisionDefaultBranch(this);
|
|
299193
299407
|
await provisionCodeowners(this);
|
|
299194
299408
|
await provisionVariables(this);
|
|
299409
|
+
// Add branch protections to config if defined
|
|
299410
|
+
provisionBranchProtections(this);
|
|
299195
299411
|
await provisionOIDCSubjectClaim(this);
|
|
299196
299412
|
await provisionPermissions(this);
|
|
299197
299413
|
await provisionLabels(this, repoAlreadyExists);
|
|
@@ -299241,6 +299457,21 @@ class EntityGHRepo extends base_Entity {
|
|
|
299241
299457
|
id: this.cr.name,
|
|
299242
299458
|
},
|
|
299243
299459
|
});
|
|
299460
|
+
// Import github_branch_protection ONLY for protections declared in CR, not GitHub state
|
|
299461
|
+
const protections = this.cr.spec.branchProtections;
|
|
299462
|
+
if (protections && Array.isArray(protections) && protections.length > 0) {
|
|
299463
|
+
for (const protection of protections) {
|
|
299464
|
+
const branch = protection.branch;
|
|
299465
|
+
this.patchImportData({
|
|
299466
|
+
op: PatchOperations.add,
|
|
299467
|
+
path: '/imports/-',
|
|
299468
|
+
value: {
|
|
299469
|
+
to: `github_branch_protection.this["${this.escapeTerraformBranchName(branch)}"]`,
|
|
299470
|
+
id: `${this.cr.name}:${this.escapeTerraformBranchName(branch)}`,
|
|
299471
|
+
},
|
|
299472
|
+
});
|
|
299473
|
+
}
|
|
299474
|
+
}
|
|
299244
299475
|
// we cannot ensure the files exist, thus we need to check
|
|
299245
299476
|
// it they exist before importing them
|
|
299246
299477
|
//for (const file of this.document.config.files) {
|
|
@@ -299263,6 +299494,19 @@ class EntityGHRepo extends base_Entity {
|
|
|
299263
299494
|
},
|
|
299264
299495
|
});
|
|
299265
299496
|
}
|
|
299497
|
+
// Import Pages resource if configured.
|
|
299498
|
+
// When a repository is manually created with Pages already enabled,
|
|
299499
|
+
// we must import the existing resource to avoid a 409 conflict on apply.
|
|
299500
|
+
if (this.cr.spec.pages) {
|
|
299501
|
+
this.patchImportData({
|
|
299502
|
+
op: PatchOperations.add,
|
|
299503
|
+
path: '/imports/-',
|
|
299504
|
+
value: {
|
|
299505
|
+
to: 'github_repository_pages.this[0]',
|
|
299506
|
+
id: this.cr.name,
|
|
299507
|
+
},
|
|
299508
|
+
});
|
|
299509
|
+
}
|
|
299266
299510
|
}
|
|
299267
299511
|
async provisionRepository() {
|
|
299268
299512
|
this.patchData({
|
|
@@ -301909,9 +302153,9 @@ const crs_analyzerSubcommand = {
|
|
|
301909
302153
|
};
|
|
301910
302154
|
|
|
301911
302155
|
;// CONCATENATED MODULE: ./package.json
|
|
301912
|
-
const package_namespaceObject =
|
|
302156
|
+
const package_namespaceObject = {"i8":"2.5.0"};
|
|
301913
302157
|
;// CONCATENATED MODULE: ../../package.json
|
|
301914
|
-
const package_namespaceObject_1 = {"i8":"2.
|
|
302158
|
+
const package_namespaceObject_1 = {"i8":"2.5.0"};
|
|
301915
302159
|
;// CONCATENATED MODULE: ./src/subcommands/index.ts
|
|
301916
302160
|
|
|
301917
302161
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { EntityGHRepo } from '../';
|
|
2
|
+
/**
|
|
3
|
+
* Adds branch protection config to the synthesized Terraform config,
|
|
4
|
+
* preserving legacy field semantics exactly (empty lists, explicit booleans, names).
|
|
5
|
+
* @param entity The EntityGHRepo instance
|
|
6
|
+
*/
|
|
7
|
+
export declare function provisionBranchProtections(entity: EntityGHRepo): void;
|
|
@@ -4,3 +4,4 @@ export { provisionVariables } from './variables';
|
|
|
4
4
|
export { provisionOIDCSubjectClaim } from './actions_oidc';
|
|
5
5
|
export { provisionPermissions } from './teams';
|
|
6
6
|
export { provisionLabels } from './labels';
|
|
7
|
+
export { provisionBranchProtections } from './branch_protections';
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
import type { Dependencies } from './resolver';
|
|
1
2
|
export declare function getKindFromPlural(plural: string): any;
|
|
2
3
|
export declare function getPluralFromKind(kind: string): string;
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Helper to extract the canonical identity (metadata.uid) from a WorkItem or its item.
|
|
6
|
+
*
|
|
7
|
+
* Use this helper when you need a stable identity key for WorkItems, e.g. for
|
|
8
|
+
* in-memory deferred-scheduling bookkeeping.
|
|
9
|
+
*
|
|
10
|
+
* Note: other subsystems may still use kind/namespace/name keys; this helper is
|
|
11
|
+
* specifically intended for UID-based WorkItem identity.
|
|
12
|
+
* Any future change to identity logic MUST be made here and nowhere else.
|
|
13
|
+
*
|
|
14
|
+
* Returns undefined if .metadata.uid is missing so scheduler/bookkeeping paths
|
|
15
|
+
* can safely short-circuit instead of throwing and aborting an entire pass.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getWorkItemIdentity(wi: WorkItem): string | undefined;
|
|
4
18
|
export declare enum OperationType {
|
|
5
19
|
RENAMED = "RENAMED",
|
|
6
20
|
UPDATED = "UPDATED",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { WorkItem } from './definitions';
|
|
2
|
+
/**
|
|
3
|
+
* Maximum number of blocked attempts allowed before an item is moved to the deferred segment.
|
|
4
|
+
* An item becomes deferred once its blocked-attempt count exceeds this value.
|
|
5
|
+
*/
|
|
6
|
+
export declare const MAX_BLOCKED_ATTEMPTS_BEFORE_DEFER = 5;
|
|
7
|
+
export declare const SUPPORTED_PARENT_KINDS: Set<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Encapsulates all deferred-scheduling bookkeeping state for one scheduler queue.
|
|
10
|
+
* Instantiate once per queue (alongside processItemSlotsManager) inside loop().
|
|
11
|
+
*/
|
|
12
|
+
export declare class DeferredSchedulingBookkeeper {
|
|
13
|
+
private _blockedAttempts;
|
|
14
|
+
private _deferredEntryOrder;
|
|
15
|
+
private _deferredOrderCounter;
|
|
16
|
+
/**
|
|
17
|
+
* Returns true only for supported parent kinds AND only for deletion operations.
|
|
18
|
+
* Per spec Definition 2: applicable when operation is MARKED_TO_DELETION,
|
|
19
|
+
* or RETRY with metadata.deletionTimestamp set.
|
|
20
|
+
*/
|
|
21
|
+
isDeferredSchedulingApplicable(item: WorkItem): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Increments block counter for item (only call when item has been detected as blocked).
|
|
24
|
+
* Returns new value. Promotes item to deferred segment if threshold crossed.
|
|
25
|
+
*/
|
|
26
|
+
incrementBlockedAttempt(item: WorkItem): number;
|
|
27
|
+
getBlockedAttempts(item: WorkItem): number;
|
|
28
|
+
isDeferred(item: WorkItem): boolean;
|
|
29
|
+
getDeferredOrder(item: WorkItem): number | undefined;
|
|
30
|
+
removeBookkeeping(item: WorkItem): void;
|
|
31
|
+
/**
|
|
32
|
+
* Splits queue into non-deferred and deferred, preserving original order,
|
|
33
|
+
* but sorts deferred by stable insertion order.
|
|
34
|
+
*/
|
|
35
|
+
partitionQueueByDeferred<T extends WorkItem>(queue: T[]): {
|
|
36
|
+
nonDeferred: T[];
|
|
37
|
+
deferred: T[];
|
|
38
|
+
};
|
|
39
|
+
clearAllBookkeeping(): void;
|
|
40
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { WorkItem } from './informer';
|
|
2
|
+
import { DeferredSchedulingBookkeeper } from './processItem.blocks';
|
|
2
3
|
export declare function getQueueMetrics(): {
|
|
3
4
|
nItems: number;
|
|
4
5
|
nItemsFinished: number;
|
|
@@ -25,4 +26,4 @@ export declare function processItem(workItem: WorkItem): Promise<void>;
|
|
|
25
26
|
* Periodically checks the queue for finished WorkItems and removes them
|
|
26
27
|
* @param {WorkItem[]} queue - Queue of WorkItems
|
|
27
28
|
*/
|
|
28
|
-
export declare function workItemGarbageCollector(queue: WorkItem[]): Promise<void>;
|
|
29
|
+
export declare function workItemGarbageCollector(queue: WorkItem[], bookkeeper?: DeferredSchedulingBookkeeper): Promise<void>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { WorkItem } from './definitions';
|
|
2
2
|
import { ProcessItemSlotMetrics } from './metrics/processItem.slot.metrics';
|
|
3
|
-
export declare function initProcessItemsSlots(nSlots: number, initMetrics?: boolean): ProcessItemSlots;
|
|
3
|
+
export declare function initProcessItemsSlots(nSlots: number, initMetrics?: boolean, onWorkItemBlockedByHandler?: (workItem: WorkItem) => void): ProcessItemSlots;
|
|
4
4
|
export declare class ProcessItemSlots {
|
|
5
5
|
_slots: ProcessItemSlot[];
|
|
6
6
|
_nSlots: number;
|
|
7
7
|
_guardRails: GuardRails;
|
|
8
|
-
constructor(nSlots: number, initMetrics: boolean);
|
|
8
|
+
constructor(nSlots: number, initMetrics: boolean, onWorkItemBlockedByHandler?: (workItem: WorkItem) => void);
|
|
9
9
|
getIdleSlots(): Generator<ProcessItemSlot, void, unknown>;
|
|
10
10
|
allSlotsAreIdle(): boolean;
|
|
11
11
|
isWorkItemBlocked(workItem: WorkItem): boolean;
|
|
@@ -24,16 +24,19 @@ export declare class ProcessItemSlot {
|
|
|
24
24
|
_actions: {
|
|
25
25
|
blockItem: (item: any) => void;
|
|
26
26
|
unblockItem: (item: any) => void;
|
|
27
|
+
onWorkItemBlockedByHandler?: (workItem: WorkItem) => void;
|
|
27
28
|
} | undefined;
|
|
28
29
|
_metrics: ProcessItemSlotMetrics;
|
|
29
30
|
constructor(id: number);
|
|
30
31
|
set actions(actions: {
|
|
31
32
|
blockItem: (item: any) => void;
|
|
32
33
|
unblockItem: (item: any) => void;
|
|
34
|
+
onWorkItemBlockedByHandler?: (workItem: WorkItem) => void;
|
|
33
35
|
});
|
|
34
36
|
get actions(): {
|
|
35
37
|
blockItem: (item: any) => void;
|
|
36
38
|
unblockItem: (item: any) => void;
|
|
39
|
+
onWorkItemBlockedByHandler?: (workItem: WorkItem) => void;
|
|
37
40
|
};
|
|
38
41
|
get idle(): boolean;
|
|
39
42
|
get id(): number;
|