bulltrackers-module 1.0.317 → 1.0.318
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/functions/computation-system/tools/BuildReporter.js +190 -166
- package/index.js +9 -4
- package/package.json +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* FILENAME: computation-system/tools/BuildReporter.js
|
|
3
|
-
*
|
|
2
|
+
* FILENAME: bulltrackers-module/functions/computation-system/tools/BuildReporter.js
|
|
3
|
+
* UPGRADED: Offloads heavy logic to a dedicated Cloud Function via Pub/Sub.
|
|
4
|
+
* FEATURES: Patch versioning, data-drift detection (window changes), and checkpointed writes.
|
|
4
5
|
*/
|
|
6
|
+
|
|
5
7
|
const { analyzeDateExecution } = require('../WorkflowOrchestrator');
|
|
6
8
|
const { fetchComputationStatus, updateComputationStatus } = require('../persistence/StatusRepository');
|
|
7
9
|
const { normalizeName, getExpectedDateStrings, DEFINITIVE_EARLIEST_DATES } = require('../utils/utils');
|
|
@@ -11,12 +13,48 @@ const SYSTEM_EPOCH = require('../system_epoch');
|
|
|
11
13
|
const pLimit = require('p-limit');
|
|
12
14
|
const path = require('path');
|
|
13
15
|
const crypto = require('crypto');
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
// Load package info for versioning
|
|
15
18
|
const packageJson = require(path.join(__dirname, '..', '..', '..', 'package.json'));
|
|
16
19
|
const packageVersion = packageJson.version;
|
|
17
20
|
|
|
21
|
+
const BUILD_RECORDS_COLLECTION = 'computation_build_records';
|
|
22
|
+
const BUILD_METADATA_DOC = 'system_build_metadata';
|
|
18
23
|
const SIMHASH_REGISTRY_COLLECTION = 'system_simhash_registry';
|
|
19
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Publishes a message to trigger the dedicated Build Reporter Cloud Function.
|
|
27
|
+
* Replaces the old ensureBuildReport that ran locally on module load.
|
|
28
|
+
*/
|
|
29
|
+
async function requestBuildReport(config, dependencies) {
|
|
30
|
+
const { pubsubUtils, logger } = dependencies;
|
|
31
|
+
try {
|
|
32
|
+
await pubsubUtils.publish(config.buildReporterTopic, {
|
|
33
|
+
requestedAt: new Date().toISOString(),
|
|
34
|
+
packageVersion: packageVersion
|
|
35
|
+
});
|
|
36
|
+
logger.log('INFO', `[BuildReporter] 🛰️ Trigger message sent to ${config.buildReporterTopic}`);
|
|
37
|
+
return { success: true };
|
|
38
|
+
} catch (e) {
|
|
39
|
+
logger.log('ERROR', `[BuildReporter] Failed to publish trigger: ${e.message}`);
|
|
40
|
+
throw e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Cloud Function Entry Point for the Build Reporter.
|
|
46
|
+
*/
|
|
47
|
+
async function handleBuildReportTrigger(message, context, config, dependencies, manifest) {
|
|
48
|
+
const { logger } = dependencies;
|
|
49
|
+
logger.log('INFO', `[BuildReporter] 📥 Trigger received. Starting build analysis...`);
|
|
50
|
+
try {
|
|
51
|
+
return await generateBuildReport(config, dependencies, manifest);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
logger.log('ERROR', `[BuildReporter] Fatal error in execution: ${e.message}`);
|
|
54
|
+
throw e;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
20
58
|
/**
|
|
21
59
|
* Replaces expensive file walking with System Epoch + Manifest Hash.
|
|
22
60
|
*/
|
|
@@ -27,6 +65,20 @@ function getSystemFingerprint(manifest) {
|
|
|
27
65
|
.digest('hex');
|
|
28
66
|
}
|
|
29
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Increments the patch number for the current package version in Firestore.
|
|
70
|
+
*/
|
|
71
|
+
async function getNextBuildId(db, version) {
|
|
72
|
+
const metaRef = db.collection(BUILD_RECORDS_COLLECTION).doc(BUILD_METADATA_DOC);
|
|
73
|
+
return await db.runTransaction(async (t) => {
|
|
74
|
+
const doc = await t.get(metaRef);
|
|
75
|
+
const data = doc.exists ? doc.data() : {};
|
|
76
|
+
const currentPatch = (data[version] || 0) + 1;
|
|
77
|
+
t.set(metaRef, { [version]: currentPatch }, { merge: true });
|
|
78
|
+
return `v${version}_p${currentPatch}`;
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
30
82
|
function isDateBeforeAvailability(dateStr, calcManifest) {
|
|
31
83
|
const targetDate = new Date(dateStr + 'T00:00:00Z');
|
|
32
84
|
const deps = calcManifest.rootDataDependencies || [];
|
|
@@ -115,72 +167,44 @@ async function verifyBehavioralStability(candidates, manifestMap, dailyStatus, l
|
|
|
115
167
|
}
|
|
116
168
|
|
|
117
169
|
/**
|
|
118
|
-
*
|
|
170
|
+
* The main reporter logic. Handles drift detection, minor versioning,
|
|
171
|
+
* and checkpointed batch writes to Firestore.
|
|
119
172
|
*/
|
|
120
|
-
async function
|
|
173
|
+
async function generateBuildReport(config, dependencies, manifest) {
|
|
121
174
|
const { db, logger } = dependencies;
|
|
122
|
-
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const latestBuildDoc = await db.collection('computation_build_records').doc('latest').get();
|
|
138
|
-
|
|
139
|
-
if (latestBuildDoc.exists) {
|
|
140
|
-
const latestData = latestBuildDoc.data();
|
|
141
|
-
if (latestData.systemFingerprint === currentSystemHash) {
|
|
142
|
-
logger.log('INFO', `[BuildReporter] ⚡ System Fingerprint (${currentSystemHash.substring(0,8)}) matches latest build. Skipping Report.`);
|
|
143
|
-
await db.collection('computation_build_records').doc(buildId).set({
|
|
144
|
-
buildId,
|
|
145
|
-
packageVersion,
|
|
146
|
-
systemFingerprint: currentSystemHash,
|
|
147
|
-
status: 'SKIPPED_IDENTICAL',
|
|
148
|
-
referenceBuild: latestData.buildId,
|
|
149
|
-
generatedAt: new Date().toISOString()
|
|
150
|
-
});
|
|
151
|
-
lockRef.update({ status: 'SKIPPED', completedAt: new Date() }).catch(() => {});
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// [DYNAMIC WINDOW CALCULATION]
|
|
157
|
-
const { absoluteEarliest } = DEFINITIVE_EARLIEST_DATES;
|
|
158
|
-
let dynamicDaysBack = 90; // Fallback default
|
|
159
|
-
if (absoluteEarliest) {
|
|
160
|
-
const today = new Date();
|
|
161
|
-
const diffTime = Math.abs(today - absoluteEarliest);
|
|
162
|
-
dynamicDaysBack = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 2; // Days difference + 2 day buffer
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
logger.log('INFO', `[BuildReporter] 🚀 Change Detected. Running Pre-flight Report for v${packageVersion} (Scope: ${dynamicDaysBack} days)...`);
|
|
166
|
-
await generateBuildReport(config, dependencies, manifest, dynamicDaysBack, buildId, currentSystemHash);
|
|
167
|
-
lockRef.update({ status: 'COMPLETED', completedAt: new Date() }).catch(() => {});
|
|
168
|
-
|
|
169
|
-
} catch (e) {
|
|
170
|
-
logger.log('ERROR', `[BuildReporter] Auto-run check failed: ${e.message}`);
|
|
175
|
+
|
|
176
|
+
const currentFingerprint = getSystemFingerprint(manifest);
|
|
177
|
+
const latestBuildDoc = await db.collection(BUILD_RECORDS_COLLECTION).doc('latest').get();
|
|
178
|
+
const latest = latestBuildDoc.exists ? latestBuildDoc.data() : null;
|
|
179
|
+
|
|
180
|
+
// [DATA DRIFT DETECTION]
|
|
181
|
+
// Force a run if the definitive earliest data date has changed (e.g. new history backfilled)
|
|
182
|
+
const currentEarliestStr = DEFINITIVE_EARLIEST_DATES.absoluteEarliest?.toISOString() || 'NONE';
|
|
183
|
+
const lastEarliestStr = latest?.windowEarliest || 'NONE';
|
|
184
|
+
const windowChanged = currentEarliestStr !== lastEarliestStr;
|
|
185
|
+
|
|
186
|
+
// If fingerprints match AND the window is the same, we can truly skip.
|
|
187
|
+
if (latest && latest.systemFingerprint === currentFingerprint && !windowChanged) {
|
|
188
|
+
logger.log('INFO', `[BuildReporter] ⚡ System fingerprint and window stable. Skipping report.`);
|
|
189
|
+
return { success: true, status: 'SKIPPED_IDENTICAL' };
|
|
171
190
|
}
|
|
172
|
-
}
|
|
173
191
|
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const finalFingerprint = systemFingerprint || getSystemFingerprint(manifest);
|
|
192
|
+
// Increment patch version (e.g., v1.0.0_p1, v1.0.0_p2)
|
|
193
|
+
const buildId = await getNextBuildId(db, packageVersion);
|
|
194
|
+
logger.log('INFO', `[BuildReporter] 🚀 Change Detected. Generating Build ${buildId}. Reason: ${windowChanged ? 'Data Window Drift' : 'Code Change'}`);
|
|
178
195
|
|
|
179
|
-
|
|
196
|
+
const today = new Date();
|
|
197
|
+
const { absoluteEarliest } = DEFINITIVE_EARLIEST_DATES;
|
|
198
|
+
|
|
199
|
+
// Dynamic Window calculation
|
|
200
|
+
let dynamicDaysBack = 90;
|
|
201
|
+
if (absoluteEarliest) {
|
|
202
|
+
const diffTime = Math.abs(today - absoluteEarliest);
|
|
203
|
+
dynamicDaysBack = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 2;
|
|
204
|
+
}
|
|
180
205
|
|
|
181
|
-
const today = new Date();
|
|
182
206
|
const startDate = new Date();
|
|
183
|
-
startDate.setDate(today.getDate() -
|
|
207
|
+
startDate.setDate(today.getDate() - dynamicDaysBack);
|
|
184
208
|
|
|
185
209
|
const datesToCheck = getExpectedDateStrings(startDate, today);
|
|
186
210
|
const manifestMap = new Map(manifest.map(c => [normalizeName(c.name), c]));
|
|
@@ -201,131 +225,131 @@ async function generateBuildReport(config, dependencies, manifest, daysBack = 90
|
|
|
201
225
|
const reportHeader = {
|
|
202
226
|
buildId,
|
|
203
227
|
packageVersion,
|
|
204
|
-
systemFingerprint:
|
|
228
|
+
systemFingerprint: currentFingerprint,
|
|
229
|
+
windowEarliest: currentEarliestStr,
|
|
205
230
|
generatedAt: new Date().toISOString(),
|
|
231
|
+
status: 'IN_PROGRESS',
|
|
206
232
|
summary: {},
|
|
207
233
|
_sharded: true
|
|
208
234
|
};
|
|
209
235
|
|
|
236
|
+
// Initialize the build record
|
|
237
|
+
await db.collection(BUILD_RECORDS_COLLECTION).doc(buildId).set(reportHeader);
|
|
238
|
+
|
|
210
239
|
let totalRun = 0, totalReRun = 0, totalStable = 0;
|
|
211
|
-
const limit = pLimit(
|
|
240
|
+
const limit = pLimit(10); // Concurrency for fetching statuses
|
|
212
241
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
prevDateStr =
|
|
225
|
-
if (
|
|
226
|
-
|
|
242
|
+
// Process dates in chunks of 5 for checkpointed writing
|
|
243
|
+
for (let i = 0; i < datesToCheck.length; i += 5) {
|
|
244
|
+
const dateBatch = datesToCheck.slice(i, i + 5);
|
|
245
|
+
|
|
246
|
+
const results = await Promise.all(dateBatch.map(dateStr => limit(async () => {
|
|
247
|
+
try {
|
|
248
|
+
const fetchPromises = [
|
|
249
|
+
fetchComputationStatus(dateStr, config, dependencies),
|
|
250
|
+
checkRootDataAvailability(dateStr, config, dependencies, DEFINITIVE_EARLIEST_DATES)
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
let prevDateStr = null;
|
|
254
|
+
if (manifest.some(c => c.isHistorical)) {
|
|
255
|
+
const prevDate = new Date(dateStr + 'T00:00:00Z');
|
|
256
|
+
prevDate.setUTCDate(prevDate.getUTCDate() - 1);
|
|
257
|
+
prevDateStr = prevDate.toISOString().slice(0, 10);
|
|
258
|
+
if (prevDate >= DEFINITIVE_EARLIEST_DATES.absoluteEarliest) {
|
|
259
|
+
fetchPromises.push(fetchComputationStatus(prevDateStr, config, dependencies));
|
|
260
|
+
}
|
|
227
261
|
}
|
|
228
|
-
}
|
|
229
262
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
run: [], rerun: [], stable: [], blocked: [], impossible: [], uptodate: [],
|
|
240
|
-
meta: { totalIncluded: 0, totalExpected: 0, match: false }
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const expectedCount = manifest.filter(c => !isDateBeforeAvailability(dateStr, c)).length;
|
|
244
|
-
dateSummary.meta.totalExpected = expectedCount;
|
|
245
|
-
|
|
246
|
-
const pushIfValid = (targetArray, item, extraReason = null) => {
|
|
247
|
-
const calcManifest = manifestMap.get(item.name);
|
|
248
|
-
if (calcManifest && isDateBeforeAvailability(dateStr, calcManifest)) return;
|
|
249
|
-
|
|
250
|
-
const entry = {
|
|
251
|
-
name: item.name,
|
|
252
|
-
reason: item.reason || extraReason,
|
|
253
|
-
pass: calcManifest ? calcManifest.pass : '?'
|
|
263
|
+
const [dailyStatus, availability, prevRes] = await Promise.all(fetchPromises);
|
|
264
|
+
const prevDailyStatus = (prevDateStr && prevRes) ? prevRes : (prevDateStr ? {} : null);
|
|
265
|
+
const rootDataStatus = availability ? availability.status : { hasPortfolio: false, hasHistory: false };
|
|
266
|
+
|
|
267
|
+
const analysis = analyzeDateExecution(dateStr, manifest, rootDataStatus, dailyStatus, manifestMap, prevDailyStatus);
|
|
268
|
+
|
|
269
|
+
const dateSummary = {
|
|
270
|
+
run: [], rerun: [], stable: [], blocked: [], impossible: [], uptodate: [],
|
|
271
|
+
meta: { totalIncluded: 0, totalExpected: 0, match: false }
|
|
254
272
|
};
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
if (
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
273
|
+
|
|
274
|
+
const expectedCount = manifest.filter(c => !isDateBeforeAvailability(dateStr, c)).length;
|
|
275
|
+
dateSummary.meta.totalExpected = expectedCount;
|
|
276
|
+
|
|
277
|
+
const pushIfValid = (targetArray, item, extraReason = null) => {
|
|
278
|
+
const calcManifest = manifestMap.get(item.name);
|
|
279
|
+
if (calcManifest && isDateBeforeAvailability(dateStr, calcManifest)) return;
|
|
280
|
+
const entry = { name: item.name, reason: item.reason || extraReason, pass: calcManifest?.pass || '?' };
|
|
281
|
+
if (targetArray === dateSummary.rerun) entry.impact = calculateBlastRadius(item.name, reverseGraph);
|
|
282
|
+
targetArray.push(entry);
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
analysis.runnable.forEach(item => pushIfValid(dateSummary.run, item, "New Calculation"));
|
|
286
|
+
|
|
287
|
+
if (analysis.reRuns.length > 0) {
|
|
288
|
+
const { trueReRuns, stableUpdates } = await verifyBehavioralStability(analysis.reRuns, manifestMap, dailyStatus, logger, simHashCache, db);
|
|
289
|
+
trueReRuns.forEach(item => pushIfValid(dateSummary.rerun, item, "Logic Changed"));
|
|
290
|
+
stableUpdates.forEach(item => pushIfValid(dateSummary.stable, item, "Logic Stable"));
|
|
291
|
+
|
|
292
|
+
if (stableUpdates.length > 0) {
|
|
293
|
+
const updatesPayload = {};
|
|
294
|
+
for (const stable of stableUpdates) {
|
|
295
|
+
const m = manifestMap.get(stable.name);
|
|
296
|
+
const stored = dailyStatus[stable.name];
|
|
297
|
+
if (m && stored) {
|
|
298
|
+
updatesPayload[stable.name] = {
|
|
299
|
+
hash: m.hash, simHash: stable.simHash, resultHash: stored.resultHash,
|
|
300
|
+
dependencyResultHashes: stored.dependencyResultHashes || {},
|
|
301
|
+
category: m.category, composition: m.composition, lastUpdated: new Date()
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (Object.keys(updatesPayload).length > 0) {
|
|
306
|
+
await updateComputationStatus(dateStr, updatesPayload, config, dependencies);
|
|
284
307
|
}
|
|
285
|
-
}
|
|
286
|
-
if (Object.keys(updatesPayload).length > 0) {
|
|
287
|
-
await updateComputationStatus(dateStr, updatesPayload, config, dependencies);
|
|
288
|
-
logger.log('INFO', `[BuildReporter] 🩹 Fixed ${Object.keys(updatesPayload).length} stable items for ${dateStr}. They will NOT re-run.`);
|
|
289
308
|
}
|
|
290
309
|
}
|
|
291
|
-
}
|
|
292
310
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
311
|
+
analysis.blocked.forEach(item => pushIfValid(dateSummary.blocked, item));
|
|
312
|
+
analysis.failedDependency.forEach(item => pushIfValid(dateSummary.blocked, item, "Dependency Missing"));
|
|
313
|
+
analysis.impossible.forEach(item => pushIfValid(dateSummary.impossible, item));
|
|
314
|
+
analysis.skipped.forEach(item => pushIfValid(dateSummary.uptodate, item, "Up To Date"));
|
|
297
315
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
316
|
+
const includedCount = dateSummary.run.length + dateSummary.rerun.length + dateSummary.stable.length +
|
|
317
|
+
dateSummary.blocked.length + dateSummary.impossible.length + dateSummary.uptodate.length;
|
|
318
|
+
dateSummary.meta.totalIncluded = includedCount;
|
|
319
|
+
dateSummary.meta.match = (includedCount === expectedCount);
|
|
302
320
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
.collection('details')
|
|
306
|
-
.doc(dateStr)
|
|
307
|
-
.set(dateSummary);
|
|
321
|
+
// Write detailed date record
|
|
322
|
+
await db.collection(BUILD_RECORDS_COLLECTION).doc(buildId).collection('details').doc(dateStr).set(dateSummary);
|
|
308
323
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
}));
|
|
316
|
-
|
|
317
|
-
const results = await Promise.all(processingPromises);
|
|
324
|
+
return { run: dateSummary.run.length, rerun: dateSummary.rerun.length, stable: dateSummary.stable.length };
|
|
325
|
+
} catch (err) {
|
|
326
|
+
logger.log('ERROR', `[BuildReporter] Analysis failed for ${dateStr}: ${err.message}`);
|
|
327
|
+
return { run: 0, rerun: 0, stable: 0 };
|
|
328
|
+
}
|
|
329
|
+
})));
|
|
318
330
|
|
|
319
|
-
|
|
331
|
+
// Accumulate stats and write a progress checkpoint
|
|
332
|
+
results.forEach(res => { totalRun += res.run; totalReRun += res.rerun; totalStable += res.stable; });
|
|
333
|
+
await db.collection(BUILD_RECORDS_COLLECTION).doc(buildId).update({
|
|
334
|
+
checkpoint: `Processed ${i + dateBatch.length}/${datesToCheck.length} dates`
|
|
335
|
+
});
|
|
336
|
+
}
|
|
320
337
|
|
|
321
|
-
reportHeader.
|
|
338
|
+
reportHeader.status = 'COMPLETED';
|
|
339
|
+
reportHeader.summary = {
|
|
340
|
+
totalReRuns: totalReRun,
|
|
341
|
+
totalNew: totalRun,
|
|
342
|
+
totalStable: totalStable,
|
|
343
|
+
scanRange: `${datesToCheck[0]} to ${datesToCheck[datesToCheck.length-1]}`
|
|
344
|
+
};
|
|
322
345
|
|
|
323
|
-
|
|
324
|
-
await db.collection(
|
|
346
|
+
// Finalize build record and update the 'latest' pointer
|
|
347
|
+
await db.collection(BUILD_RECORDS_COLLECTION).doc(buildId).set(reportHeader);
|
|
348
|
+
await db.collection(BUILD_RECORDS_COLLECTION).doc('latest').set({ ...reportHeader, note: "Latest completed build report." });
|
|
325
349
|
|
|
326
|
-
logger.log('SUCCESS', `[BuildReporter]
|
|
350
|
+
logger.log('SUCCESS', `[BuildReporter] Build ${buildId} completed. Re-runs: ${totalReRun}, Stable: ${totalStable}, New: ${totalRun}.`);
|
|
327
351
|
|
|
328
|
-
return { success: true,
|
|
352
|
+
return { success: true, buildId, summary: reportHeader.summary };
|
|
329
353
|
}
|
|
330
354
|
|
|
331
|
-
module.exports = {
|
|
355
|
+
module.exports = { requestBuildReport, handleBuildReportTrigger, generateBuildReport };
|
package/index.js
CHANGED
|
@@ -29,8 +29,12 @@ const { handleUpdate } = require('./functions
|
|
|
29
29
|
const { build: buildManifest } = require('./functions/computation-system/context/ManifestBuilder');
|
|
30
30
|
const { dispatchComputationPass } = require('./functions/computation-system/helpers/computation_dispatcher');
|
|
31
31
|
const { handleComputationTask } = require('./functions/computation-system/helpers/computation_worker');
|
|
32
|
-
const {
|
|
33
|
-
|
|
32
|
+
const {
|
|
33
|
+
requestBuildReport,
|
|
34
|
+
handleBuildReportTrigger,
|
|
35
|
+
generateBuildReport
|
|
36
|
+
} = require('./functions/computation-system/tools/BuildReporter');// [NEW] Import Monitor
|
|
37
|
+
|
|
34
38
|
const { checkPassStatus } = require('./functions/computation-system/helpers/monitor');
|
|
35
39
|
|
|
36
40
|
const dataLoader = require('./functions/computation-system/utils/data_loader');
|
|
@@ -92,9 +96,10 @@ const computationSystem = {
|
|
|
92
96
|
dataLoader,
|
|
93
97
|
computationUtils,
|
|
94
98
|
buildManifest,
|
|
95
|
-
|
|
99
|
+
// [UPDATED] Refactored Reporter Pipes
|
|
100
|
+
requestBuildReport,
|
|
101
|
+
handleBuildReportTrigger,
|
|
96
102
|
generateBuildReport,
|
|
97
|
-
// [NEW] Export Monitor Pipe
|
|
98
103
|
checkPassStatus
|
|
99
104
|
};
|
|
100
105
|
|