@redpanda-data/docs-extensions-and-macros 4.15.6 → 4.15.8

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.
@@ -3,22 +3,555 @@
3
3
  * Outputs a console-parseable format for GitHub Actions
4
4
  */
5
5
 
6
+ /**
7
+ * Render Bloblang changes section for PR summary
8
+ * @param {object} data - Bloblang change data
9
+ * @param {array} data.newMethods - Array of new methods (with .name and optional .version)
10
+ * @param {array} data.newFunctions - Array of new functions (with .name and optional .version)
11
+ * @param {array} data.removedMethods - Array of removed methods
12
+ * @param {array} data.removedFunctions - Array of removed functions
13
+ * @param {array} data.deprecatedMethods - Array of deprecated methods
14
+ * @param {array} data.deprecatedFunctions - Array of deprecated functions
15
+ * @param {boolean} includeVersion - Whether to include version info in output
16
+ * @returns {array} Array of lines to add to the summary
17
+ */
18
+ function renderBloblangChanges(data, includeVersion = false) {
19
+ const lines = [];
20
+ const {
21
+ newMethods = [],
22
+ newFunctions = [],
23
+ removedMethods = [],
24
+ removedFunctions = [],
25
+ deprecatedMethods = [],
26
+ deprecatedFunctions = []
27
+ } = data;
28
+
29
+ const hasChanges = newMethods.length > 0 || newFunctions.length > 0 ||
30
+ removedMethods.length > 0 || removedFunctions.length > 0 ||
31
+ deprecatedMethods.length > 0 || deprecatedFunctions.length > 0;
32
+
33
+ if (!hasChanges) {
34
+ return lines;
35
+ }
36
+
37
+ lines.push('**Update Bloblang Guide Pages:**');
38
+ lines.push('');
39
+
40
+ if (newMethods.length > 0) {
41
+ lines.push(`New methods to add to \`modules/guides/pages/bloblang/methods.adoc\` (${newMethods.length}):`);
42
+ newMethods.forEach(method => {
43
+ const versionInfo = includeVersion && method.version ? ` — introduced in **${method.version}**` : '';
44
+ const name = typeof method === 'string' ? method : method.name;
45
+ lines.push(`- [ ] \`${name}\`${versionInfo}`);
46
+ });
47
+ lines.push('');
48
+ }
49
+
50
+ if (newFunctions.length > 0) {
51
+ lines.push(`New functions to add to \`modules/guides/pages/bloblang/functions.adoc\` (${newFunctions.length}):`);
52
+ newFunctions.forEach(func => {
53
+ const versionInfo = includeVersion && func.version ? ` — introduced in **${func.version}**` : '';
54
+ const name = typeof func === 'string' ? func : func.name;
55
+ lines.push(`- [ ] \`${name}\`${versionInfo}`);
56
+ });
57
+ lines.push('');
58
+ }
59
+
60
+ if (removedMethods.length > 0) {
61
+ lines.push(`Removed methods to delete from \`modules/guides/pages/bloblang/methods.adoc\` (${removedMethods.length}):`);
62
+ removedMethods.forEach(method => {
63
+ const versionInfo = includeVersion && method.version ? ` — removed in **${method.version}**` : '';
64
+ const name = typeof method === 'string' ? method : method.name;
65
+ lines.push(`- [ ] \`${name}\`${versionInfo}`);
66
+ });
67
+ lines.push('');
68
+ }
69
+
70
+ if (removedFunctions.length > 0) {
71
+ lines.push(`Removed functions to delete from \`modules/guides/pages/bloblang/functions.adoc\` (${removedFunctions.length}):`);
72
+ removedFunctions.forEach(func => {
73
+ const versionInfo = includeVersion && func.version ? ` — removed in **${func.version}**` : '';
74
+ const name = typeof func === 'string' ? func : func.name;
75
+ lines.push(`- [ ] \`${name}\`${versionInfo}`);
76
+ });
77
+ lines.push('');
78
+ }
79
+
80
+ if (deprecatedMethods.length > 0) {
81
+ lines.push(`Deprecated methods - add deprecation notice to \`modules/guides/pages/bloblang/methods.adoc\` (${deprecatedMethods.length}):`);
82
+ deprecatedMethods.forEach(method => {
83
+ const versionInfo = includeVersion && method.version ? ` — deprecated in **${method.version}**` : '';
84
+ const name = typeof method === 'string' ? method : method.name;
85
+ lines.push(`- [ ] \`${name}\`${versionInfo}`);
86
+ });
87
+ lines.push('');
88
+ }
89
+
90
+ if (deprecatedFunctions.length > 0) {
91
+ lines.push(`Deprecated functions - add deprecation notice to \`modules/guides/pages/bloblang/functions.adoc\` (${deprecatedFunctions.length}):`);
92
+ deprecatedFunctions.forEach(func => {
93
+ const versionInfo = includeVersion && func.version ? ` — deprecated in **${func.version}**` : '';
94
+ const name = typeof func === 'string' ? func : func.name;
95
+ lines.push(`- [ ] \`${name}\`${versionInfo}`);
96
+ });
97
+ lines.push('');
98
+ }
99
+
100
+ lines.push('**How to add includes:**');
101
+ lines.push('');
102
+ lines.push('For methods, find the appropriate category section in `methods.adoc` and add:');
103
+ lines.push('```asciidoc');
104
+ lines.push('include::redpanda-connect:partial$bloblang-methods/method_name.adoc[leveloffset=+2]');
105
+ lines.push('```');
106
+ lines.push('');
107
+ lines.push('For functions, add to the Functions section in `functions.adoc`:');
108
+ lines.push('```asciidoc');
109
+ lines.push('include::redpanda-connect:partial$bloblang-functions/function_name.adoc[leveloffset=+2]');
110
+ lines.push('```');
111
+ lines.push('');
112
+ lines.push('**Note:** Partials are auto-generated. Includes must be added manually in alphabetical order within their section.');
113
+ lines.push('');
114
+
115
+ return lines;
116
+ }
117
+
118
+ /**
119
+ * Generate PR summary for multiple releases
120
+ * @param {object} masterDiff - Master diff with releases array
121
+ * @param {object} binaryAnalysis - Cloud support data (from latest release)
122
+ * @param {array} draftedConnectors - Array of newly drafted connectors
123
+ * @returns {string} Formatted summary
124
+ */
125
+ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, draftedConnectors = null) {
126
+ const lines = [];
127
+
128
+ // Defensive: ensure metadata exists
129
+ const metadata = masterDiff?.metadata || {};
130
+ const startVersion = metadata.startVersion || 'unknown';
131
+ const endVersion = metadata.endVersion || 'unknown';
132
+ const processedReleases = metadata.processedReleases || 0;
133
+
134
+ lines.push('<!-- PR_SUMMARY_START -->');
135
+ lines.push('');
136
+ lines.push('## Redpanda Connect Documentation Update');
137
+ lines.push('');
138
+ lines.push(`**Multi-Release Update:** ${startVersion} → ${endVersion}`);
139
+ lines.push(`**Releases Processed:** ${processedReleases}`);
140
+
141
+ if (binaryAnalysis) {
142
+ lines.push(`**Cloud Version:** ${binaryAnalysis.cloudVersion}`);
143
+ }
144
+
145
+ lines.push('');
146
+
147
+ // Total summary across all releases
148
+ lines.push('### Total Changes Across All Releases');
149
+ lines.push('');
150
+ const total = masterDiff?.totalSummary || {};
151
+
152
+ if (total.newComponents > 0) {
153
+ lines.push(`- **${total.newComponents}** new connectors`);
154
+ }
155
+ if (total.newFields > 0) {
156
+ lines.push(`- **${total.newFields}** new fields across ${total.releaseCount || 0} release(s)`);
157
+ }
158
+ if (total.removedComponents > 0) {
159
+ lines.push(`- **${total.removedComponents}** removed connectors`);
160
+ }
161
+ if (total.removedFields > 0) {
162
+ lines.push(`- **${total.removedFields}** removed fields`);
163
+ }
164
+ if (total.deprecatedComponents > 0) {
165
+ lines.push(`- **${total.deprecatedComponents}** deprecated connectors`);
166
+ }
167
+ if (total.deprecatedFields > 0) {
168
+ lines.push(`- **${total.deprecatedFields}** deprecated fields`);
169
+ }
170
+ if (total.changedDefaults > 0) {
171
+ lines.push(`- **${total.changedDefaults}** changed default values`);
172
+ }
173
+ if (total.newBloblangMethods > 0) {
174
+ lines.push(`- **${total.newBloblangMethods}** new Bloblang methods`);
175
+ }
176
+ if (total.removedBloblangMethods > 0) {
177
+ lines.push(`- **${total.removedBloblangMethods}** removed Bloblang methods`);
178
+ }
179
+ if (total.newBloblangFunctions > 0) {
180
+ lines.push(`- **${total.newBloblangFunctions}** new Bloblang functions`);
181
+ }
182
+ if (total.removedBloblangFunctions > 0) {
183
+ lines.push(`- **${total.removedBloblangFunctions}** removed Bloblang functions`);
184
+ }
185
+
186
+ lines.push('');
187
+
188
+ // Guard: ensure releases array exists
189
+ const releases = masterDiff?.releases || [];
190
+ if (releases.length === 0) {
191
+ lines.push('_No releases to process_');
192
+ lines.push('');
193
+ lines.push('<!-- PR_SUMMARY_END -->');
194
+ return lines.join('\n');
195
+ }
196
+
197
+ // Per-release detailed breakdown
198
+ lines.push('### Changes Per Release');
199
+ lines.push('');
200
+
201
+ for (const release of releases) {
202
+ const releaseNotesUrl = `https://github.com/redpanda-data/connect/releases/tag/v${release.toVersion}`;
203
+ lines.push(`#### Version ${release.toVersion}`);
204
+ lines.push(`> [Release notes](${releaseNotesUrl})`);
205
+ lines.push('');
206
+
207
+ const summary = release.summary || {};
208
+ const details = release.details || {};
209
+ const hasChanges = Object.values(summary).some(v => v > 0);
210
+
211
+ if (!hasChanges) {
212
+ lines.push('_No documentation changes in this release_');
213
+ lines.push('');
214
+ continue;
215
+ }
216
+
217
+ // New connectors with descriptions
218
+ const newComponents = details.newComponents || [];
219
+ if (summary.newComponents > 0 && newComponents.length > 0) {
220
+ lines.push(`**New Connectors (${summary.newComponents}):**`);
221
+ lines.push('');
222
+ const inCloud = release.binaryAnalysis?.comparison?.inCloud || [];
223
+ const cloudOnly = release.binaryAnalysis?.comparison?.cloudOnly || [];
224
+ const notInCloud = release.binaryAnalysis?.comparison?.notInCloud || [];
225
+ const cgoOnly = release.binaryAnalysis?.cgoOnly || [];
226
+
227
+ newComponents.forEach(comp => {
228
+ const isInCloud = inCloud.some(c => c.type === comp.type && c.name === comp.name) ||
229
+ cloudOnly.some(c => c.type === comp.type && c.name === comp.name);
230
+ const isSelfHostedOnly = notInCloud.some(c => c.type === comp.type && c.name === comp.name);
231
+ const isCgoOnly = cgoOnly.some(c => c.type === comp.type && c.name === comp.name);
232
+
233
+ let platformIndicator = '';
234
+ if (isInCloud) platformIndicator = ' ☁️';
235
+ else if (isSelfHostedOnly) platformIndicator = ' 🖥️';
236
+ if (isCgoOnly) platformIndicator += ' 🔧';
237
+
238
+ lines.push(`##### \`${comp.name}\` (${comp.type}, ${comp.status})${platformIndicator}`);
239
+
240
+ // Add description (truncated to 2 sentences)
241
+ if (comp.description) {
242
+ const shortDesc = truncateToSentence(comp.description, 2);
243
+ lines.push(`> ${shortDesc}`);
244
+ }
245
+ lines.push('');
246
+ });
247
+ }
248
+
249
+ // New fields with details
250
+ const newFields = details.newFields || [];
251
+ if (summary.newFields > 0 && newFields.length > 0) {
252
+ lines.push(`**New Fields (${summary.newFields}):**`);
253
+ lines.push('');
254
+ lines.push('| Component | Field | Description |');
255
+ lines.push('|-----------|-------|-------------|');
256
+
257
+ newFields.forEach(field => {
258
+ const desc = field.description ? truncateToSentence(field.description, 1).replace(/\|/g, '\\|') : '_No description_';
259
+ lines.push(`| \`${field.component}\` | \`${field.field}\` | ${desc} |`);
260
+ });
261
+ lines.push('');
262
+ }
263
+
264
+ // Removed components
265
+ const removedComponents = details.removedComponents || [];
266
+ if (summary.removedComponents > 0 && removedComponents.length > 0) {
267
+ lines.push(`**Removed Connectors (${summary.removedComponents}):**`);
268
+ lines.push('');
269
+ removedComponents.forEach(comp => {
270
+ lines.push(`- \`${comp.name}\` (${comp.type})`);
271
+ });
272
+ lines.push('');
273
+ }
274
+
275
+ // Removed fields
276
+ const removedFields = details.removedFields || [];
277
+ if (summary.removedFields > 0 && removedFields.length > 0) {
278
+ lines.push(`**Removed Fields (${summary.removedFields}):**`);
279
+ lines.push('');
280
+ lines.push('| Component | Field |');
281
+ lines.push('|-----------|-------|');
282
+ removedFields.forEach(field => {
283
+ lines.push(`| \`${field.component}\` | \`${field.field}\` |`);
284
+ });
285
+ lines.push('');
286
+ }
287
+
288
+ // Deprecated fields with migration guidance
289
+ const deprecatedFields = details.deprecatedFields || [];
290
+ if (summary.deprecatedFields > 0 && deprecatedFields.length > 0) {
291
+ lines.push(`**Deprecated Fields (${summary.deprecatedFields}):**`);
292
+ lines.push('');
293
+ deprecatedFields.forEach(field => {
294
+ const guidance = field.description ? ` — ${truncateToSentence(field.description, 1)}` : '';
295
+ lines.push(`- \`${field.component}.${field.field}\`${guidance}`);
296
+ });
297
+ lines.push('');
298
+ }
299
+
300
+ // Changed defaults
301
+ const changedDefaults = details.changedDefaults || [];
302
+ if (summary.changedDefaults > 0 && changedDefaults.length > 0) {
303
+ lines.push(`**Changed Defaults (${summary.changedDefaults}):**`);
304
+ lines.push('');
305
+ lines.push('| Component | Field | Old Default | New Default |');
306
+ lines.push('|-----------|-------|-------------|-------------|');
307
+ changedDefaults.forEach(change => {
308
+ const oldVal = change.oldDefault !== undefined ? `\`${JSON.stringify(change.oldDefault)}\`` : '_none_';
309
+ const newVal = change.newDefault !== undefined ? `\`${JSON.stringify(change.newDefault)}\`` : '_none_';
310
+ lines.push(`| \`${change.component}\` | \`${change.field}\` | ${oldVal} | ${newVal} |`);
311
+ });
312
+ lines.push('');
313
+ }
314
+ }
315
+
316
+ // Writer action items (aggregate)
317
+ lines.push('---');
318
+ lines.push('');
319
+ lines.push('### Writer Action Items');
320
+ lines.push('');
321
+
322
+ // Collect all new connectors across all releases with full details
323
+ const allNewConnectors = [];
324
+ const allRemovedConnectors = [];
325
+ const allDeprecatedFields = [];
326
+ const allChangedDefaults = [];
327
+ const allNewBloblangMethods = [];
328
+ const allRemovedBloblangMethods = [];
329
+ const allNewBloblangFunctions = [];
330
+ const allRemovedBloblangFunctions = [];
331
+ const allDeprecatedBloblangMethods = [];
332
+ const allDeprecatedBloblangFunctions = [];
333
+
334
+ releases.forEach(release => {
335
+ const details = release.details || {};
336
+ const releaseInCloud = release.binaryAnalysis?.comparison?.inCloud || [];
337
+ const releaseCloudOnly = release.binaryAnalysis?.comparison?.cloudOnly || [];
338
+ const releaseNotInCloud = release.binaryAnalysis?.comparison?.notInCloud || [];
339
+
340
+ // New connectors
341
+ (details.newComponents || []).forEach(comp => {
342
+ const isCloud = releaseInCloud.some(c => c.type === comp.type && c.name === comp.name) ||
343
+ releaseCloudOnly.some(c => c.type === comp.type && c.name === comp.name);
344
+ const isSelfHostedOnly = releaseNotInCloud.some(c => c.type === comp.type && c.name === comp.name);
345
+
346
+ allNewConnectors.push({
347
+ name: comp.name,
348
+ type: comp.type,
349
+ status: comp.status,
350
+ description: comp.description,
351
+ version: release.toVersion,
352
+ isCloud,
353
+ isSelfHostedOnly
354
+ });
355
+ });
356
+
357
+ // Removed connectors
358
+ (details.removedComponents || []).forEach(comp => {
359
+ allRemovedConnectors.push({
360
+ name: comp.name,
361
+ type: comp.type,
362
+ version: release.toVersion
363
+ });
364
+ });
365
+
366
+ // Deprecated fields
367
+ (details.deprecatedFields || []).forEach(field => {
368
+ allDeprecatedFields.push({
369
+ component: field.component,
370
+ field: field.field,
371
+ description: field.description,
372
+ version: release.toVersion
373
+ });
374
+ });
375
+
376
+ // Changed defaults
377
+ (details.changedDefaults || []).forEach(change => {
378
+ allChangedDefaults.push({
379
+ component: change.component,
380
+ field: change.field,
381
+ oldDefault: change.oldDefault,
382
+ newDefault: change.newDefault,
383
+ version: release.toVersion
384
+ });
385
+ });
386
+
387
+ // New/removed Bloblang methods
388
+ (details.newBloblangMethods || []).forEach(methodName => {
389
+ allNewBloblangMethods.push({
390
+ name: methodName,
391
+ version: release.toVersion
392
+ });
393
+ });
394
+ (details.removedBloblangMethods || []).forEach(methodName => {
395
+ allRemovedBloblangMethods.push({
396
+ name: methodName,
397
+ version: release.toVersion
398
+ });
399
+ });
400
+
401
+ // New/removed Bloblang functions
402
+ (details.newBloblangFunctions || []).forEach(funcName => {
403
+ allNewBloblangFunctions.push({
404
+ name: funcName,
405
+ version: release.toVersion
406
+ });
407
+ });
408
+ (details.removedBloblangFunctions || []).forEach(funcName => {
409
+ allRemovedBloblangFunctions.push({
410
+ name: funcName,
411
+ version: release.toVersion
412
+ });
413
+ });
414
+
415
+ // Deprecated Bloblang methods/functions
416
+ (details.deprecatedBloblangMethods || []).forEach(methodName => {
417
+ allDeprecatedBloblangMethods.push({
418
+ name: methodName,
419
+ version: release.toVersion
420
+ });
421
+ });
422
+ (details.deprecatedBloblangFunctions || []).forEach(funcName => {
423
+ allDeprecatedBloblangFunctions.push({
424
+ name: funcName,
425
+ version: release.toVersion
426
+ });
427
+ });
428
+ });
429
+
430
+ // Priority 1: New connectors needing documentation
431
+ if (allNewConnectors.length > 0) {
432
+ lines.push('**📝 Document New Connectors:**');
433
+ lines.push('');
434
+
435
+ // Group by cloud vs self-hosted
436
+ const cloudConnectors = allNewConnectors.filter(c => c.isCloud);
437
+ const selfHostedConnectors = allNewConnectors.filter(c => c.isSelfHostedOnly);
438
+ const otherConnectors = allNewConnectors.filter(c => !c.isCloud && !c.isSelfHostedOnly);
439
+
440
+ if (cloudConnectors.length > 0) {
441
+ lines.push('_Cloud-supported (higher priority):_');
442
+ cloudConnectors.forEach(conn => {
443
+ lines.push(`- [ ] \`${conn.name}\` ${conn.type} ☁️ — introduced in **${conn.version}**`);
444
+ });
445
+ lines.push('');
446
+ }
447
+
448
+ if (selfHostedConnectors.length > 0) {
449
+ lines.push('_Self-hosted only:_');
450
+ selfHostedConnectors.forEach(conn => {
451
+ lines.push(`- [ ] \`${conn.name}\` ${conn.type} 🖥️ — introduced in **${conn.version}**`);
452
+ });
453
+ lines.push('');
454
+ }
455
+
456
+ if (otherConnectors.length > 0) {
457
+ lines.push('_Other connectors:_');
458
+ otherConnectors.forEach(conn => {
459
+ lines.push(`- [ ] \`${conn.name}\` ${conn.type} — introduced in **${conn.version}**`);
460
+ });
461
+ lines.push('');
462
+ }
463
+ }
464
+
465
+ // Priority 2: Removed connectors needing migration docs
466
+ if (allRemovedConnectors.length > 0) {
467
+ lines.push('**Update Migration Guide for Removed Connectors:**');
468
+ lines.push('');
469
+ allRemovedConnectors.forEach(conn => {
470
+ lines.push(`- [ ] \`${conn.name}\` ${conn.type} — removed in **${conn.version}**`);
471
+ });
472
+ lines.push('');
473
+ }
474
+
475
+ // Priority 3: Deprecated fields needing docs update
476
+ if (allDeprecatedFields.length > 0) {
477
+ lines.push('**Update Docs for Deprecated Fields:**');
478
+ lines.push('');
479
+ allDeprecatedFields.forEach(field => {
480
+ const guidance = field.description ? ` (${truncateToSentence(field.description, 1)})` : '';
481
+ lines.push(`- [ ] \`${field.component}.${field.field}\`${guidance} — deprecated in **${field.version}**`);
482
+ });
483
+ lines.push('');
484
+ }
485
+
486
+ // Priority 4: Changed defaults that may affect users
487
+ if (allChangedDefaults.length > 0) {
488
+ lines.push('**Review Changed Defaults for Breaking Changes:**');
489
+ lines.push('');
490
+ allChangedDefaults.forEach(change => {
491
+ const oldVal = change.oldDefault !== undefined ? JSON.stringify(change.oldDefault) : 'none';
492
+ const newVal = change.newDefault !== undefined ? JSON.stringify(change.newDefault) : 'none';
493
+ lines.push(`- [ ] \`${change.component}.${change.field}\`: \`${oldVal}\` → \`${newVal}\` — changed in **${change.version}**`);
494
+ });
495
+ lines.push('');
496
+ }
497
+
498
+ // Bloblang methods and functions
499
+ const bloblangLines = renderBloblangChanges({
500
+ newMethods: allNewBloblangMethods,
501
+ newFunctions: allNewBloblangFunctions,
502
+ removedMethods: allRemovedBloblangMethods,
503
+ removedFunctions: allRemovedBloblangFunctions,
504
+ deprecatedMethods: allDeprecatedBloblangMethods,
505
+ deprecatedFunctions: allDeprecatedBloblangFunctions
506
+ }, true); // includeVersion = true for multi-version summaries
507
+ lines.push(...bloblangLines);
508
+
509
+ // Add commercial name reminder if there are new connectors
510
+ if (allNewConnectors.length > 0) {
511
+ lines.push('---');
512
+ lines.push('');
513
+ lines.push('**💡 Reminder:** For each new connector, add the `:page-commercial-names:` attribute:');
514
+ lines.push('');
515
+ lines.push('```asciidoc');
516
+ lines.push('= Connector Name');
517
+ lines.push(':type: input');
518
+ lines.push(':page-commercial-names: Commercial Name, Alternative Name');
519
+ lines.push('```');
520
+ lines.push('');
521
+ }
522
+
523
+ lines.push('<!-- PR_SUMMARY_END -->');
524
+ return lines.join('\n');
525
+ }
526
+
6
527
  /**
7
528
  * Generate a PR-friendly summary for connector changes
8
- * @param {object} diffData - Diff data from generateConnectorDiffJson
529
+ * @param {object} diffData - Diff data from generateConnectorDiffJson OR master diff with multiple releases
9
530
  * @param {object} binaryAnalysis - Cloud support data from getCloudSupport
10
531
  * @param {array} draftedConnectors - Array of newly drafted connectors
532
+ * @param {boolean} isMultiVersion - Whether diffData is a master diff with multiple releases
11
533
  * @returns {string} Formatted summary
12
534
  */
13
- function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors = null) {
535
+ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors = null, isMultiVersion = false) {
14
536
  const lines = [];
15
537
 
16
538
  // Header with delimiters for GitHub Action parsing
17
539
  lines.push('<!-- PR_SUMMARY_START -->');
18
540
  lines.push('');
19
541
 
542
+ // Detect if this is a master diff
543
+ if (!isMultiVersion && diffData.releases && diffData.totalSummary) {
544
+ isMultiVersion = true;
545
+ }
546
+
547
+ if (isMultiVersion) {
548
+ // Multi-version format
549
+ return generateMultiVersionPRSummary(diffData, binaryAnalysis, draftedConnectors);
550
+ }
551
+
552
+ // Single version format (original logic)
20
553
  // Quick Summary Section
21
- lines.push('## 📊 Redpanda Connect Documentation Update');
554
+ lines.push('## Redpanda Connect Documentation Update');
22
555
  lines.push('');
23
556
  lines.push(`**OSS Version:** ${diffData.comparison.oldVersion} → ${diffData.comparison.newVersion}`);
24
557
 
@@ -33,7 +566,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
33
566
  const hasChanges = Object.values(stats).some(v => v > 0) || (draftedConnectors && draftedConnectors.length > 0);
34
567
 
35
568
  if (!hasChanges) {
36
- lines.push('**No changes detected** - Documentation is up to date');
569
+ lines.push('**No changes detected** - Documentation is up to date');
37
570
  lines.push('');
38
571
  lines.push('<!-- PR_SUMMARY_END -->');
39
572
  return lines.join('\n');
@@ -45,11 +578,13 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
45
578
  if (stats.newComponents > 0) {
46
579
  lines.push(`- **${stats.newComponents}** new connector${stats.newComponents !== 1 ? 's' : ''}`);
47
580
 
48
- if (binaryAnalysis) {
581
+ if (binaryAnalysis && binaryAnalysis.comparison) {
49
582
  const newConnectorKeys = diffData.details.newComponents.map(c => `${c.type}:${c.name}`);
50
583
  const cloudSupported = newConnectorKeys.filter(key => {
51
584
  const inCloud = binaryAnalysis.comparison.inCloud.some(c => `${c.type}:${c.name}` === key);
52
- return inCloud;
585
+ const cloudOnly = binaryAnalysis.comparison.cloudOnly &&
586
+ binaryAnalysis.comparison.cloudOnly.some(c => `${c.type}:${c.name}` === key);
587
+ return inCloud || cloudOnly;
53
588
  }).length;
54
589
 
55
590
  const needsCloudDocs = cloudSupported;
@@ -66,11 +601,11 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
66
601
  }
67
602
 
68
603
  if (stats.removedComponents > 0) {
69
- lines.push(`- **${stats.removedComponents}** removed connector${stats.removedComponents !== 1 ? 's' : ''} ⚠️`);
604
+ lines.push(`- **${stats.removedComponents}** removed connector${stats.removedComponents !== 1 ? 's' : ''}`);
70
605
  }
71
606
 
72
607
  if (stats.removedFields > 0) {
73
- lines.push(`- **${stats.removedFields}** removed field${stats.removedFields !== 1 ? 's' : ''} ⚠️`);
608
+ lines.push(`- **${stats.removedFields}** removed field${stats.removedFields !== 1 ? 's' : ''}`);
74
609
  }
75
610
 
76
611
  if (stats.deprecatedComponents > 0) {
@@ -81,15 +616,39 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
81
616
  lines.push(`- **${stats.deprecatedFields}** deprecated field${stats.deprecatedFields !== 1 ? 's' : ''}`);
82
617
  }
83
618
 
619
+ if (stats.newBloblangMethods > 0) {
620
+ lines.push(`- **${stats.newBloblangMethods}** new Bloblang method${stats.newBloblangMethods !== 1 ? 's' : ''}`);
621
+ }
622
+
623
+ if (stats.newBloblangFunctions > 0) {
624
+ lines.push(`- **${stats.newBloblangFunctions}** new Bloblang function${stats.newBloblangFunctions !== 1 ? 's' : ''}`);
625
+ }
626
+
627
+ if (stats.removedBloblangMethods > 0) {
628
+ lines.push(`- **${stats.removedBloblangMethods}** removed Bloblang method${stats.removedBloblangMethods !== 1 ? 's' : ''}`);
629
+ }
630
+
631
+ if (stats.removedBloblangFunctions > 0) {
632
+ lines.push(`- **${stats.removedBloblangFunctions}** removed Bloblang function${stats.removedBloblangFunctions !== 1 ? 's' : ''}`);
633
+ }
634
+
635
+ if (stats.deprecatedBloblangMethods > 0) {
636
+ lines.push(`- **${stats.deprecatedBloblangMethods}** deprecated Bloblang method${stats.deprecatedBloblangMethods !== 1 ? 's' : ''}`);
637
+ }
638
+
639
+ if (stats.deprecatedBloblangFunctions > 0) {
640
+ lines.push(`- **${stats.deprecatedBloblangFunctions}** deprecated Bloblang function${stats.deprecatedBloblangFunctions !== 1 ? 's' : ''}`);
641
+ }
642
+
84
643
  if (stats.changedDefaults > 0) {
85
- lines.push(`- **${stats.changedDefaults}** default value change${stats.changedDefaults !== 1 ? 's' : ''} ⚠️`);
644
+ lines.push(`- **${stats.changedDefaults}** default value change${stats.changedDefaults !== 1 ? 's' : ''}`);
86
645
  }
87
646
 
88
647
  lines.push('');
89
648
 
90
649
  // Writer Reminder for Commercial Names
91
650
  if (stats.newComponents > 0) {
92
- lines.push('### ✍️ Writer Action Required');
651
+ lines.push('### Writer Action Required');
93
652
  lines.push('');
94
653
  lines.push('For each new connector, add the `:page-commercial-names:` attribute to the frontmatter:');
95
654
  lines.push('');
@@ -172,7 +731,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
172
731
  if (stats.changedDefaults > 0) breakingChanges.push('changed defaults');
173
732
 
174
733
  if (breakingChanges.length > 0) {
175
- lines.push('### ⚠️ Breaking Changes Detected');
734
+ lines.push('### Breaking Changes Detected');
176
735
  lines.push('');
177
736
  lines.push(`This update includes **${breakingChanges.join(', ')}** that may affect existing configurations.`);
178
737
  lines.push('');
@@ -199,9 +758,15 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
199
758
  Object.entries(draftsByType).forEach(([type, drafts]) => {
200
759
  lines.push(`**${type}:**`);
201
760
  drafts.forEach(draft => {
202
- const cloudIndicator = binaryAnalysis?.comparison.inCloud.some(c =>
761
+ // Check both inCloud (OSS+Cloud) and cloudOnly (Cloud-only)
762
+ const isInCloud = binaryAnalysis?.comparison.inCloud.some(c =>
203
763
  c.type === type && c.name === draft.name
204
- ) ? ' ☁️' : '';
764
+ );
765
+ const isCloudOnly = binaryAnalysis?.comparison.cloudOnly &&
766
+ binaryAnalysis.comparison.cloudOnly.some(c =>
767
+ c.type === type && c.name === draft.name
768
+ );
769
+ const cloudIndicator = (isInCloud || isCloudOnly) ? ' ☁️' : '';
205
770
  const cgoIndicator = draft.requiresCgo ? ' 🔧' : '';
206
771
  const statusBadge = draft.status && draft.status !== 'stable' ? ` (${draft.status})` : '';
207
772
  lines.push(`- \`${draft.name}\`${statusBadge}${cloudIndicator}${cgoIndicator} → \`${draft.path}\``);
@@ -240,7 +805,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
240
805
  }
241
806
 
242
807
  if (missingDescriptions.length > 0) {
243
- lines.push('### ⚠️ Missing Descriptions');
808
+ lines.push('### Missing Descriptions');
244
809
  lines.push('');
245
810
  lines.push(`**${missingDescriptions.length}** item${missingDescriptions.length !== 1 ? 's' : ''} missing descriptions - these need writer attention:`);
246
811
  lines.push('');
@@ -285,7 +850,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
285
850
  if (missingDescriptions.length > 0) {
286
851
  actionItems.push({
287
852
  priority: 0,
288
- text: `⚠️ Add descriptions for ${missingDescriptions.length} component${missingDescriptions.length !== 1 ? 's' : ''}/field${missingDescriptions.length !== 1 ? 's' : ''} (see Missing Descriptions section)`
853
+ text: `Add descriptions for ${missingDescriptions.length} component${missingDescriptions.length !== 1 ? 's' : ''}/field${missingDescriptions.length !== 1 ? 's' : ''} (see Missing Descriptions section)`
289
854
  });
290
855
  }
291
856
 
@@ -304,13 +869,16 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
304
869
  });
305
870
  }
306
871
 
307
- // New connectors without cloud support
308
- if (stats.newComponents > 0) {
872
+ // New connectors without cloud support (self-hosted only)
873
+ if (binaryAnalysis && stats.newComponents > 0) {
309
874
  diffData.details.newComponents.forEach(connector => {
310
875
  const key = `${connector.type}:${connector.name}`;
311
- const inCloud = binaryAnalysis?.comparison.inCloud.some(c => `${c.type}:${c.name}` === key);
312
876
 
313
- if (!inCloud) {
877
+ // Check if it's explicitly in the self-hosted only list
878
+ const isSelfHostedOnly = binaryAnalysis.comparison.notInCloud &&
879
+ binaryAnalysis.comparison.notInCloud.some(c => `${c.type}:${c.name}` === key);
880
+
881
+ if (isSelfHostedOnly) {
314
882
  actionItems.push({
315
883
  priority: 2,
316
884
  text: `Document new \`${connector.name}\` ${connector.type} (self-hosted only)`
@@ -360,9 +928,20 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
360
928
 
361
929
  lines.push('');
362
930
 
931
+ // Bloblang methods and functions
932
+ const bloblangLines = renderBloblangChanges({
933
+ newMethods: diffData.details.newBloblangMethods || [],
934
+ newFunctions: diffData.details.newBloblangFunctions || [],
935
+ removedMethods: diffData.details.removedBloblangMethods || [],
936
+ removedFunctions: diffData.details.removedBloblangFunctions || [],
937
+ deprecatedMethods: diffData.details.deprecatedBloblangMethods || [],
938
+ deprecatedFunctions: diffData.details.deprecatedBloblangFunctions || []
939
+ }, false); // includeVersion = false for single-version summaries
940
+ lines.push(...bloblangLines);
941
+
363
942
  // Detailed breakdown (expandable)
364
943
  lines.push('<details>');
365
- lines.push('<summary><strong>📋 Detailed Changes</strong> (click to expand)</summary>');
944
+ lines.push('<summary><strong>Detailed Changes</strong> (click to expand)</summary>');
366
945
  lines.push('');
367
946
 
368
947
  // New Connectors
@@ -376,7 +955,13 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
376
955
 
377
956
  diffData.details.newComponents.forEach(connector => {
378
957
  const key = `${connector.type}:${connector.name}`;
958
+
959
+ // Check explicit categories
379
960
  const inCloud = binaryAnalysis.comparison.inCloud.some(c => `${c.type}:${c.name}` === key);
961
+ const isSelfHostedOnly = binaryAnalysis.comparison.notInCloud &&
962
+ binaryAnalysis.comparison.notInCloud.some(c => `${c.type}:${c.name}` === key);
963
+ const isCloudOnly = binaryAnalysis.comparison.cloudOnly &&
964
+ binaryAnalysis.comparison.cloudOnly.some(c => `${c.type}:${c.name}` === key);
380
965
 
381
966
  const entry = {
382
967
  name: connector.name,
@@ -385,9 +970,10 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
385
970
  description: connector.description
386
971
  };
387
972
 
388
- if (inCloud) {
973
+ // Use explicit positive checks instead of !inCloud
974
+ if (inCloud || isCloudOnly) {
389
975
  cloudSupportedNew.push(entry);
390
- } else {
976
+ } else if (isSelfHostedOnly) {
391
977
  selfHostedOnlyNew.push(entry);
392
978
  }
393
979
  });
@@ -493,7 +1079,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
493
1079
 
494
1080
  // Removed Connectors
495
1081
  if (stats.removedComponents > 0) {
496
- lines.push('#### ⚠️ Removed Connectors');
1082
+ lines.push('#### Removed Connectors');
497
1083
  lines.push('');
498
1084
  diffData.details.removedComponents.forEach(c => {
499
1085
  lines.push(`- **${c.name}** (${c.type})`);
@@ -503,7 +1089,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
503
1089
 
504
1090
  // Removed Fields
505
1091
  if (stats.removedFields > 0) {
506
- lines.push('#### ⚠️ Removed Fields');
1092
+ lines.push('#### Removed Fields');
507
1093
  lines.push('');
508
1094
 
509
1095
  const fieldsByComponent = {};
@@ -559,7 +1145,7 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
559
1145
 
560
1146
  // Changed Defaults
561
1147
  if (stats.changedDefaults > 0) {
562
- lines.push('#### ⚠️ Changed Default Values');
1148
+ lines.push('#### Changed Default Values');
563
1149
  lines.push('');
564
1150
 
565
1151
  const changesByComponent = {};
@@ -582,6 +1168,66 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
582
1168
  });
583
1169
  }
584
1170
 
1171
+ // New Bloblang Methods
1172
+ if (stats.newBloblangMethods > 0 && diffData.details.newBloblangMethods) {
1173
+ lines.push('#### New Bloblang Methods');
1174
+ lines.push('');
1175
+ diffData.details.newBloblangMethods.forEach(methodName => {
1176
+ lines.push(`- \`${methodName}\``);
1177
+ });
1178
+ lines.push('');
1179
+ }
1180
+
1181
+ // New Bloblang Functions
1182
+ if (stats.newBloblangFunctions > 0 && diffData.details.newBloblangFunctions) {
1183
+ lines.push('#### New Bloblang Functions');
1184
+ lines.push('');
1185
+ diffData.details.newBloblangFunctions.forEach(funcName => {
1186
+ lines.push(`- \`${funcName}\``);
1187
+ });
1188
+ lines.push('');
1189
+ }
1190
+
1191
+ // Removed Bloblang Methods
1192
+ if (stats.removedBloblangMethods > 0 && diffData.details.removedBloblangMethods) {
1193
+ lines.push('#### Removed Bloblang Methods');
1194
+ lines.push('');
1195
+ diffData.details.removedBloblangMethods.forEach(methodName => {
1196
+ lines.push(`- \`${methodName}\``);
1197
+ });
1198
+ lines.push('');
1199
+ }
1200
+
1201
+ // Removed Bloblang Functions
1202
+ if (stats.removedBloblangFunctions > 0 && diffData.details.removedBloblangFunctions) {
1203
+ lines.push('#### Removed Bloblang Functions');
1204
+ lines.push('');
1205
+ diffData.details.removedBloblangFunctions.forEach(funcName => {
1206
+ lines.push(`- \`${funcName}\``);
1207
+ });
1208
+ lines.push('');
1209
+ }
1210
+
1211
+ // Deprecated Bloblang Methods
1212
+ if (stats.deprecatedBloblangMethods > 0 && diffData.details.deprecatedBloblangMethods) {
1213
+ lines.push('#### Deprecated Bloblang Methods');
1214
+ lines.push('');
1215
+ diffData.details.deprecatedBloblangMethods.forEach(methodName => {
1216
+ lines.push(`- \`${methodName}\``);
1217
+ });
1218
+ lines.push('');
1219
+ }
1220
+
1221
+ // Deprecated Bloblang Functions
1222
+ if (stats.deprecatedBloblangFunctions > 0 && diffData.details.deprecatedBloblangFunctions) {
1223
+ lines.push('#### Deprecated Bloblang Functions');
1224
+ lines.push('');
1225
+ diffData.details.deprecatedBloblangFunctions.forEach(funcName => {
1226
+ lines.push(`- \`${funcName}\``);
1227
+ });
1228
+ lines.push('');
1229
+ }
1230
+
585
1231
  // Cloud Support Gap Analysis
586
1232
  if (binaryAnalysis && binaryAnalysis.comparison.notInCloud.length > 0) {
587
1233
  lines.push('#### 🔍 Cloud Support Gap Analysis');
@@ -661,6 +1307,7 @@ function printPRSummary(diffData, binaryAnalysis = null, draftedConnectors = nul
661
1307
 
662
1308
  module.exports = {
663
1309
  generatePRSummary,
1310
+ generateMultiVersionPRSummary,
664
1311
  printPRSummary,
665
1312
  truncateToSentence
666
1313
  };