@redpanda-data/docs-extensions-and-macros 5.57.0 → 5.58.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.
@@ -1223,7 +1223,7 @@ npm test -- --coverage
1223
1223
  ==== The live overrides corpus
1224
1224
 
1225
1225
  `__tests__/tools/property-extractor/property-corpus-rendering.test.js` runs the real
1226
- overrides file, not a fixture, because a fixture passes while the live 438-entry corpus
1226
+ overrides file, not a fixture, because a fixture passes while the live overrides corpus
1227
1227
  breaks. Two files feed it, both mirrors of the `docs` repo:
1228
1228
 
1229
1229
  `__tests__/docs-data/property-overrides.json`:: A byte copy of `docs-data/property-overrides.json`.
@@ -1245,7 +1245,9 @@ test, so it sat three months and 114 entries behind. That test now has its own
1245
1245
  `property-overrides-admin-fixture.json`; put new fixture data there or in the test
1246
1246
  itself, never in the mirror.
1247
1247
 
1248
- Refresh both from a `docs` checkout:
1248
+ Every Monday, `.github/workflows/property-corpus-drift.yml` compares both files against `docs` main. When they have drifted, it runs the recipe below and opens or updates one pull request from `bot/refresh-property-corpus`. If that PR's tests fail, the refresh has exposed a real bug: push the fix to the same branch, and while the PR is open the job stops updating the branch once its latest commit isn't the bot's.
1249
+
1250
+ To refresh by hand, for example between weekly runs, run the same recipe from a `docs` checkout:
1249
1251
 
1250
1252
  [,bash]
1251
1253
  ----
@@ -169,7 +169,8 @@ For each version pair `(oldVersion → newVersion)`:
169
169
  "removedFields": 2, // Breaking changes!
170
170
  "deprecatedComponents": 0,
171
171
  "deprecatedFields": 1,
172
- "changedDefaults": 0
172
+ "changedDefaults": 0, // A default changed or was removed (breaking)
173
+ "documentedDefaults": 0 // A field with no default now states one (informational)
173
174
  },
174
175
  "details": {
175
176
  "newComponents": [
@@ -385,7 +386,8 @@ Changes between two consecutive versions:
385
386
  "newFields": [...],
386
387
  "removedFields": [...],
387
388
  "deprecatedFields": [...],
388
- "changedDefaults": [...]
389
+ "changedDefaults": [...],
390
+ "documentedDefaults": [...]
389
391
  },
390
392
  "binaryAnalysis": {
391
393
  "versions": {
@@ -63,7 +63,8 @@ function createMasterDiff(intermediateResults, finalDiffPath, outputPath) {
63
63
  removedFields: releases.reduce((sum, r) => sum + (r.summary.removedFields || 0), 0),
64
64
  deprecatedComponents: releases.reduce((sum, r) => sum + (r.summary.deprecatedComponents || 0), 0),
65
65
  deprecatedFields: releases.reduce((sum, r) => sum + (r.summary.deprecatedFields || 0), 0),
66
- changedDefaults: releases.reduce((sum, r) => sum + (r.summary.changedDefaults || 0), 0)
66
+ changedDefaults: releases.reduce((sum, r) => sum + (r.summary.changedDefaults || 0), 0),
67
+ documentedDefaults: releases.reduce((sum, r) => sum + (r.summary.documentedDefaults || 0), 0)
67
68
  };
68
69
 
69
70
  const masterDiff = {
@@ -3,6 +3,16 @@
3
3
  * Outputs a console-parseable format for GitHub Actions
4
4
  */
5
5
 
6
+ /**
7
+ * Format a field default for the Markdown PR summary. A field with no default
8
+ * is `undefined`; a declared null default (Default(nil)) is a value.
9
+ * @param {*} value - The default, or undefined when the field has none
10
+ * @returns {string} Inline code, or `_no default_`
11
+ */
12
+ function formatDefault(value) {
13
+ return value === undefined ? '_no default_' : `\`${JSON.stringify(value)}\``;
14
+ }
15
+
6
16
  /**
7
17
  * Render Bloblang changes section for PR summary
8
18
  * @param {object} data - Bloblang change data
@@ -238,6 +248,9 @@ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, drafte
238
248
  if (total.changedDefaults > 0) {
239
249
  lines.push(`- **${total.changedDefaults}** changed default values`);
240
250
  }
251
+ if (total.documentedDefaults > 0) {
252
+ lines.push(`- **${total.documentedDefaults}** newly stated default values`);
253
+ }
241
254
  if (total.newBloblangMethods > 0) {
242
255
  lines.push(`- **${total.newBloblangMethods}** new Bloblang methods`);
243
256
  }
@@ -375,12 +388,25 @@ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, drafte
375
388
  lines.push('| Component | Field | Old Default | New Default |');
376
389
  lines.push('|-----------|-------|-------------|-------------|');
377
390
  changedDefaults.forEach(change => {
378
- const oldVal = change.oldDefault !== undefined ? `\`${JSON.stringify(change.oldDefault)}\`` : '_none_';
379
- const newVal = change.newDefault !== undefined ? `\`${JSON.stringify(change.newDefault)}\`` : '_none_';
391
+ const oldVal = formatDefault(change.oldDefault);
392
+ const newVal = formatDefault(change.newDefault);
380
393
  lines.push(`| \`${change.component}\` | \`${change.field}\` | ${oldVal} | ${newVal} |`);
381
394
  });
382
395
  lines.push('');
383
396
  }
397
+
398
+ // Fields that gained a stated default
399
+ const documentedDefaults = details.documentedDefaults || [];
400
+ if (documentedDefaults.length > 0) {
401
+ lines.push(`**Newly Stated Defaults (${documentedDefaults.length}):**`);
402
+ lines.push('');
403
+ lines.push("_These fields now state a default. They usually behaved this way already, so they are not listed as changes in What's new. Check that none of them changed behavior._");
404
+ lines.push('');
405
+ documentedDefaults.forEach(change => {
406
+ lines.push(`- \`${change.component}.${change.field}\`: ${formatDefault(change.newDefault)}`);
407
+ });
408
+ lines.push('');
409
+ }
384
410
  }
385
411
 
386
412
  // Writer action items (aggregate)
@@ -558,9 +584,9 @@ function generateMultiVersionPRSummary(masterDiff, binaryAnalysis = null, drafte
558
584
  lines.push('**Review Changed Defaults for Breaking Changes:**');
559
585
  lines.push('');
560
586
  allChangedDefaults.forEach(change => {
561
- const oldVal = change.oldDefault !== undefined ? JSON.stringify(change.oldDefault) : 'none';
562
- const newVal = change.newDefault !== undefined ? JSON.stringify(change.newDefault) : 'none';
563
- lines.push(`- [ ] \`${change.component}.${change.field}\`: \`${oldVal}\` → \`${newVal}\` — changed in **${change.version}**`);
587
+ const oldVal = formatDefault(change.oldDefault);
588
+ const newVal = formatDefault(change.newDefault);
589
+ lines.push(`- [ ] \`${change.component}.${change.field}\`: ${oldVal} → ${newVal} — changed in **${change.version}**`);
564
590
  });
565
591
  lines.push('');
566
592
  }
@@ -717,6 +743,10 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
717
743
  lines.push(`- **${stats.changedDefaults}** default value change${stats.changedDefaults !== 1 ? 's' : ''}`);
718
744
  }
719
745
 
746
+ if (stats.documentedDefaults > 0) {
747
+ lines.push(`- **${stats.documentedDefaults}** newly stated default value${stats.documentedDefaults !== 1 ? 's' : ''} (no behavior change expected)`);
748
+ }
749
+
720
750
  lines.push('');
721
751
 
722
752
  // Writer Reminder for Commercial Names
@@ -1233,14 +1263,25 @@ function generatePRSummary(diffData, binaryAnalysis = null, draftedConnectors =
1233
1263
  const [type, name] = component.split(':');
1234
1264
  lines.push(`**${type}/${name}:**`);
1235
1265
  changes.forEach(c => {
1236
- const oldStr = JSON.stringify(c.oldDefault);
1237
- const newStr = JSON.stringify(c.newDefault);
1238
- lines.push(`- \`${c.field}\`: ${oldStr} → ${newStr}`);
1266
+ lines.push(`- \`${c.field}\`: ${formatDefault(c.oldDefault)} → ${formatDefault(c.newDefault)}`);
1239
1267
  });
1240
1268
  lines.push('');
1241
1269
  });
1242
1270
  }
1243
1271
 
1272
+ // Newly stated defaults
1273
+ const documentedDefaults = diffData.details.documentedDefaults || [];
1274
+ if (documentedDefaults.length > 0) {
1275
+ lines.push('#### Newly Stated Defaults');
1276
+ lines.push('');
1277
+ lines.push("_These fields now state a default. They usually behaved this way already, so they are not listed as changes in What's new. Check that none of them changed behavior._");
1278
+ lines.push('');
1279
+ documentedDefaults.forEach(c => {
1280
+ lines.push(`- \`${c.component}.${c.field}\`: ${formatDefault(c.newDefault)}`);
1281
+ });
1282
+ lines.push('');
1283
+ }
1284
+
1244
1285
  // New Bloblang Methods
1245
1286
  if (stats.newBloblangMethods > 0 && diffData.details.newBloblangMethods) {
1246
1287
  lines.push('#### New Bloblang Methods');
@@ -175,6 +175,10 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
175
175
  const deprecatedFields = [];
176
176
  // Changed default values
177
177
  const changedDefaults = [];
178
+ // Fields that had no default and now state one. The field behaved the same
179
+ // way before, the spec just didn't say so, so these are not default changes
180
+ // and stay out of What's new and the breaking-change warning.
181
+ const documentedDefaults = [];
178
182
 
179
183
  Object.keys(newMap).forEach(cKey => {
180
184
  if (!(cKey in oldMap)) return;
@@ -209,14 +213,16 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
209
213
  const newDefaultStr = JSON.stringify(newDefault);
210
214
 
211
215
  if (oldDefaultStr !== newDefaultStr) {
212
- changedDefaults.push({
216
+ const entry = {
213
217
  component: cKey,
214
218
  field: fName,
215
219
  oldDefault: oldDefault,
216
220
  newDefault: newDefault,
217
221
  description: newFieldObj && newFieldObj.description,
218
222
  shortDescription: newFieldObj && newFieldObj.short_description
219
- });
223
+ };
224
+ if (oldDefault === undefined) documentedDefaults.push(entry);
225
+ else changedDefaults.push(entry);
220
226
  }
221
227
  }
222
228
  });
@@ -280,6 +286,7 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
280
286
  deprecatedComponents: deprecatedComponents.length,
281
287
  deprecatedFields: deprecatedFields.length,
282
288
  changedDefaults: changedDefaults.length,
289
+ documentedDefaults: documentedDefaults.length,
283
290
  platformTransitions: platformTransitions.length,
284
291
  newBloblangMethods: newBloblangMethods.length,
285
292
  removedBloblangMethods: removedBloblangMethods.length,
@@ -296,6 +303,7 @@ function generateConnectorDiffJson(oldIndex, newIndex, opts = {}) {
296
303
  deprecatedComponents,
297
304
  deprecatedFields,
298
305
  changedDefaults,
306
+ documentedDefaults,
299
307
  platformTransitions,
300
308
  newBloblangMethods,
301
309
  removedBloblangMethods,
@@ -646,7 +654,8 @@ function printDeltaReport(oldIndex, newIndex, opts = {}) {
646
654
  const oldDefaultStr = JSON.stringify(oldDefault);
647
655
  const newDefaultStr = JSON.stringify(newDefault);
648
656
 
649
- if (oldDefaultStr !== newDefaultStr) {
657
+ // A field that had no default and now states one is not a change.
658
+ if (oldDefaultStr !== newDefaultStr && oldDefault !== undefined) {
650
659
  changedDefaultsList.push({
651
660
  component: cKey,
652
661
  field: fName,
@@ -719,8 +728,8 @@ function printDeltaReport(oldIndex, newIndex, opts = {}) {
719
728
  console.log('➤ Changed default values:');
720
729
  changedDefaultsList.forEach(entry => {
721
730
  const { component, field, oldDefault, newDefault } = entry;
722
- const oldStr = JSON.stringify(oldDefault);
723
- const newStr = JSON.stringify(newDefault);
731
+ const oldStr = oldDefault === undefined ? 'no default' : JSON.stringify(oldDefault);
732
+ const newStr = newDefault === undefined ? 'no default' : JSON.stringify(newDefault);
724
733
  console.log(` • ${component} → ${field}`);
725
734
  console.log(` Old: ${oldStr}`);
726
735
  console.log(` New: ${newStr}`);
@@ -657,7 +657,8 @@ function buildChangedDefaultsTable (changedDefaults, capFn) {
657
657
  const byFieldAndDefaults = {}
658
658
  for (const change of changedDefaults) {
659
659
  const [type, compName] = change.component.split(':')
660
- const compositeKey = `${change.field}|${String(change.oldDefault)}|${String(change.newDefault)}`
660
+ // JSON keeps null apart from "null" and one object default apart from another.
661
+ const compositeKey = JSON.stringify([change.field, change.oldDefault, change.newDefault])
661
662
  if (!byFieldAndDefaults[compositeKey]) {
662
663
  byFieldAndDefaults[compositeKey] = {
663
664
  field: change.field,
@@ -675,23 +676,31 @@ function buildChangedDefaultsTable (changedDefaults, capFn) {
675
676
  section += '|Field |Old default |New default |Description |Affected components\n\n'
676
677
 
677
678
  for (const [, info] of Object.entries(byFieldAndDefaults)) {
678
- // Values render as literal inline code, so interpolations like
679
- // ${!uuid_v4()} and characters like * or _ show as typed.
680
679
  // Values render as literal inline code through pass:c, which, unlike
681
680
  // `+...+`, also keeps values with ++ or with spaces at either end. Strings
682
681
  // that are empty, start or end with whitespace, or contain a newline show
683
682
  // as JSON, so " " and "\n" read as the values they are.
684
- const formatDefault = (val) => {
685
- if (val === undefined || val === null) return 'none'
683
+ const formatDefault = (val, asJson = false) => {
684
+ // 'none' would read as a value, and is one for some fields (compression).
685
+ if (val === undefined) return '_no default_'
686
686
  let text
687
- if (typeof val === 'string') text = (val === '' || /^\s|\s$|\n/.test(val)) ? JSON.stringify(val) : val
687
+ if (asJson) text = JSON.stringify(val)
688
+ // A null default is declared (Default(nil)), so it renders as a value.
689
+ else if (val === null) text = 'null'
690
+ else if (typeof val === 'string') text = (val === '' || /^\s|\s$|\n/.test(val)) ? JSON.stringify(val) : val
688
691
  else if (typeof val === 'number' || typeof val === 'boolean') text = String(val)
689
692
  else text = JSON.stringify(val)
690
693
  return `\`pass:c[${text.replace(/\]/g, '\\]').replace(/\|/g, '\\|')}]\``
691
694
  }
692
695
 
693
- const oldVal = formatDefault(info.oldDefault)
694
- const newVal = formatDefault(info.newDefault)
696
+ let oldVal = formatDefault(info.oldDefault)
697
+ let newVal = formatDefault(info.newDefault)
698
+ // A type change such as "5" to 5 or "null" to null would read as no
699
+ // change, so show both sides as JSON.
700
+ if (oldVal === newVal) {
701
+ oldVal = formatDefault(info.oldDefault, true)
702
+ newVal = formatDefault(info.newDefault, true)
703
+ }
695
704
  // A | in the description would end the cell and shift the row.
696
705
  const desc = info.description ? capFn(info.description).replace(/\|/g, '\\|') : '// TODO: Add description'
697
706