@redpanda-data/docs-extensions-and-macros 4.13.1 → 4.13.2

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.
Files changed (33) hide show
  1. package/bin/doc-tools-mcp.js +15 -3
  2. package/bin/doc-tools.js +767 -2088
  3. package/bin/mcp-tools/property-docs.js +18 -0
  4. package/bin/mcp-tools/rpcn-docs.js +28 -3
  5. package/cli-utils/antora-utils.js +53 -2
  6. package/cli-utils/dependencies.js +313 -0
  7. package/cli-utils/diff-utils.js +273 -0
  8. package/cli-utils/doc-tools-utils.js +54 -0
  9. package/extensions/algolia-indexer/generate-index.js +134 -102
  10. package/extensions/algolia-indexer/index.js +70 -38
  11. package/extensions/collect-bloblang-samples.js +2 -1
  12. package/extensions/generate-rp-connect-categories.js +126 -67
  13. package/extensions/generate-rp-connect-info.js +291 -137
  14. package/macros/rp-connect-components.js +34 -5
  15. package/package.json +4 -3
  16. package/tools/add-commercial-names.js +207 -0
  17. package/tools/generate-cli-docs.js +6 -2
  18. package/tools/get-console-version.js +5 -0
  19. package/tools/get-redpanda-version.js +5 -0
  20. package/tools/property-extractor/compare-properties.js +3 -3
  21. package/tools/property-extractor/generate-handlebars-docs.js +14 -14
  22. package/tools/property-extractor/generate-pr-summary.js +46 -0
  23. package/tools/property-extractor/pr-summary-formatter.js +375 -0
  24. package/tools/redpanda-connect/README.adoc +403 -38
  25. package/tools/redpanda-connect/connector-binary-analyzer.js +588 -0
  26. package/tools/redpanda-connect/generate-rpcn-connector-docs.js +97 -34
  27. package/tools/redpanda-connect/parse-csv-connectors.js +1 -1
  28. package/tools/redpanda-connect/pr-summary-formatter.js +601 -0
  29. package/tools/redpanda-connect/report-delta.js +69 -2
  30. package/tools/redpanda-connect/rpcn-connector-docs-handler.js +1180 -0
  31. package/tools/redpanda-connect/templates/connector.hbs +38 -0
  32. package/tools/redpanda-connect/templates/intro.hbs +0 -20
  33. package/tools/redpanda-connect/update-nav.js +205 -0
@@ -0,0 +1,273 @@
1
+ 'use strict'
2
+
3
+ const { spawnSync } = require('child_process')
4
+ const path = require('path')
5
+ const fs = require('fs')
6
+ const { findRepoRoot } = require('./doc-tools-utils')
7
+
8
+ /**
9
+ * Run the cluster documentation generator script for a specific release/tag.
10
+ *
11
+ * Invokes the external `generate-cluster-docs.sh` script with the provided mode, tag,
12
+ * and Docker-related options.
13
+ *
14
+ * @param {string} mode - Operation mode passed to the script (for example, "generate" or "clean").
15
+ * @param {string} tag - Release tag or version to generate docs for.
16
+ * @param {Object} options - Runtime options.
17
+ * @param {string} options.dockerRepo - Docker repository used by the script.
18
+ * @param {string} options.consoleTag - Console image tag passed to the script.
19
+ * @param {string} options.consoleDockerRepo - Console Docker repository used by the script.
20
+ */
21
+ function runClusterDocs (mode, tag, options) {
22
+ const script = path.join(__dirname, 'generate-cluster-docs.sh')
23
+ const args = [mode, tag, options.dockerRepo, options.consoleTag, options.consoleDockerRepo]
24
+ console.log(`Running ${script} with arguments: ${args.join(' ')}`)
25
+ const r = spawnSync('bash', [script, ...args], { stdio: 'inherit' })
26
+ if (r.status !== 0) process.exit(r.status)
27
+ }
28
+
29
+ /**
30
+ * Cleanup old diff files, keeping only the 2 most recent.
31
+ *
32
+ * @param {string} diffDir - Directory containing diff files
33
+ */
34
+ function cleanupOldDiffs (diffDir) {
35
+ try {
36
+ console.log('Cleaning up old diff JSON files (keeping only 2 most recent)…')
37
+
38
+ const absoluteDiffDir = path.resolve(diffDir)
39
+ if (!fs.existsSync(absoluteDiffDir)) {
40
+ return
41
+ }
42
+
43
+ // Get all diff files sorted by modification time (newest first)
44
+ const files = fs.readdirSync(absoluteDiffDir)
45
+ .filter(file => file.startsWith('redpanda-property-changes-') && file.endsWith('.json'))
46
+ .map(file => ({
47
+ name: file,
48
+ path: path.join(absoluteDiffDir, file),
49
+ time: fs.statSync(path.join(absoluteDiffDir, file)).mtime.getTime()
50
+ }))
51
+ .sort((a, b) => b.time - a.time)
52
+
53
+ // Delete all but the 2 most recent
54
+ if (files.length > 2) {
55
+ files.slice(2).forEach(file => {
56
+ console.log(` Removing old file: ${file.name}`)
57
+ fs.unlinkSync(file.path)
58
+ })
59
+ }
60
+ } catch (error) {
61
+ console.error(` Failed to cleanup old diff files: ${error.message}`)
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Generate a detailed JSON report describing property changes between two releases.
67
+ *
68
+ * @param {string} oldTag - Release tag or identifier for the "old" properties set.
69
+ * @param {string} newTag - Release tag or identifier for the "new" properties set.
70
+ * @param {string} outputDir - Directory where the comparison report will be written.
71
+ */
72
+ function generatePropertyComparisonReport (oldTag, newTag, outputDir) {
73
+ try {
74
+ console.log('\nGenerating detailed property comparison report...')
75
+
76
+ // Look for the property JSON files in the standard location
77
+ const repoRoot = findRepoRoot()
78
+ const attachmentsDir = path.join(repoRoot, 'modules/reference/attachments')
79
+ const oldJsonPath = path.join(attachmentsDir, `redpanda-properties-${oldTag}.json`)
80
+ const newJsonPath = path.join(attachmentsDir, `redpanda-properties-${newTag}.json`)
81
+
82
+ if (!fs.existsSync(oldJsonPath)) {
83
+ console.log(`Warning: Old properties JSON not found at: ${oldJsonPath}`)
84
+ console.log(' Skipping detailed property comparison.')
85
+ return
86
+ }
87
+
88
+ if (!fs.existsSync(newJsonPath)) {
89
+ console.log(`Warning: New properties JSON not found at: ${newJsonPath}`)
90
+ console.log(' Skipping detailed property comparison.')
91
+ return
92
+ }
93
+
94
+ // Ensure output directory exists
95
+ const absoluteOutputDir = path.resolve(outputDir)
96
+ fs.mkdirSync(absoluteOutputDir, { recursive: true })
97
+
98
+ // Run the property comparison tool
99
+ const propertyExtractorDir = path.resolve(__dirname, '../tools/property-extractor')
100
+ const compareScript = path.join(propertyExtractorDir, 'compare-properties.js')
101
+ const reportFilename = `redpanda-property-changes-${oldTag}-to-${newTag}.json`
102
+ const reportPath = path.join(absoluteOutputDir, reportFilename)
103
+ const args = [compareScript, oldJsonPath, newJsonPath, oldTag, newTag, absoluteOutputDir, reportFilename]
104
+
105
+ const result = spawnSync('node', args, {
106
+ stdio: 'inherit',
107
+ cwd: propertyExtractorDir
108
+ })
109
+
110
+ if (result.error) {
111
+ console.error(`Error: Property comparison failed: ${result.error.message}`)
112
+ } else if (result.status !== 0) {
113
+ console.error(`Error: Property comparison exited with code: ${result.status}`)
114
+ } else {
115
+ console.log(`Done: Property comparison report saved to: ${reportPath}`)
116
+ }
117
+ } catch (error) {
118
+ console.error(`Error: Error generating property comparison: ${error.message}`)
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Update property overrides file with version information for new properties
124
+ *
125
+ * @param {string} overridesPath - Path to property-overrides.json file
126
+ * @param {object} diffData - Diff data from property comparison
127
+ * @param {string} newTag - Version tag for new properties (e.g., "v25.3.3")
128
+ */
129
+ function updatePropertyOverridesWithVersion (overridesPath, diffData, newTag) {
130
+ try {
131
+ console.log('\nUpdating property overrides with version information...')
132
+
133
+ // Load existing overrides
134
+ let overridesRoot = { properties: {} }
135
+ if (fs.existsSync(overridesPath)) {
136
+ const overridesContent = fs.readFileSync(overridesPath, 'utf8')
137
+ overridesRoot = JSON.parse(overridesContent)
138
+
139
+ if (!overridesRoot.properties) {
140
+ overridesRoot.properties = {}
141
+ }
142
+ }
143
+
144
+ const overrides = overridesRoot.properties
145
+ const newProperties = diffData.details?.newProperties || []
146
+
147
+ if (newProperties.length === 0) {
148
+ console.log(' No new properties to update')
149
+ return
150
+ }
151
+
152
+ let updatedCount = 0
153
+ let createdCount = 0
154
+
155
+ newProperties.forEach(prop => {
156
+ const propertyName = prop.name
157
+
158
+ if (overrides[propertyName]) {
159
+ if (overrides[propertyName].version !== newTag) {
160
+ overrides[propertyName].version = newTag
161
+ updatedCount++
162
+ }
163
+ } else {
164
+ overrides[propertyName] = { version: newTag }
165
+ createdCount++
166
+ }
167
+ })
168
+
169
+ // Save updated overrides (sorted)
170
+ const sortedOverrides = {}
171
+ Object.keys(overrides).sort().forEach(key => {
172
+ sortedOverrides[key] = overrides[key]
173
+ })
174
+
175
+ overridesRoot.properties = sortedOverrides
176
+ fs.writeFileSync(overridesPath, JSON.stringify(overridesRoot, null, 2) + '\n', 'utf8')
177
+
178
+ if (updatedCount > 0 || createdCount > 0) {
179
+ console.log('Done: Updated property overrides:')
180
+ if (createdCount > 0) {
181
+ console.log(` • Created ${createdCount} new override ${createdCount === 1 ? 'entry' : 'entries'}`)
182
+ }
183
+ if (updatedCount > 0) {
184
+ console.log(` • Updated ${updatedCount} existing override ${updatedCount === 1 ? 'entry' : 'entries'}`)
185
+ }
186
+
187
+ newProperties.forEach(prop => {
188
+ console.log(` • ${prop.name} → ${newTag}`)
189
+ })
190
+ }
191
+ } catch (error) {
192
+ console.error(`Warning: Failed to update property overrides: ${error.message}`)
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Create a unified diff patch between two directories and clean them up.
198
+ *
199
+ * @param {string} kind - Logical category for the diff (for example, "metrics" or "rpk")
200
+ * @param {string} oldTag - Identifier for the "old" version
201
+ * @param {string} newTag - Identifier for the "new" version
202
+ * @param {string} oldTempDir - Path to the directory containing the old output
203
+ * @param {string} newTempDir - Path to the directory containing the new output
204
+ */
205
+ function diffDirs (kind, oldTag, newTag, oldTempDir, newTempDir) {
206
+ // Backwards compatibility: if temp directories not provided, use autogenerated paths
207
+ if (!oldTempDir) {
208
+ oldTempDir = path.join('autogenerated', oldTag, kind)
209
+ }
210
+ if (!newTempDir) {
211
+ newTempDir = path.join('autogenerated', newTag, kind)
212
+ }
213
+
214
+ const diffDir = path.join('tmp', 'diffs', kind, `${oldTag}_to_${newTag}`)
215
+
216
+ if (!fs.existsSync(oldTempDir)) {
217
+ console.error(`Error: Cannot diff: missing ${oldTempDir}`)
218
+ process.exit(1)
219
+ }
220
+ if (!fs.existsSync(newTempDir)) {
221
+ console.error(`Error: Cannot diff: missing ${newTempDir}`)
222
+ process.exit(1)
223
+ }
224
+
225
+ fs.mkdirSync(diffDir, { recursive: true })
226
+
227
+ // Generate traditional patch
228
+ const patch = path.join(diffDir, 'changes.patch')
229
+ const cmd = `diff -ru "${oldTempDir}" "${newTempDir}" > "${patch}" || true`
230
+ const res = spawnSync(cmd, { stdio: 'inherit', shell: true })
231
+
232
+ if (res.error) {
233
+ console.error(`Error: diff failed: ${res.error.message}`)
234
+ process.exit(1)
235
+ }
236
+ console.log(`Done: Wrote patch: ${patch}`)
237
+
238
+ // Safety guard: only clean up directories that are explicitly passed as temp directories
239
+ const tmpRoot = path.resolve('tmp') + path.sep
240
+ const workspaceRoot = path.resolve('.') + path.sep
241
+
242
+ // Only clean up if directories were explicitly provided as temp directories
243
+ const explicitTempDirs = arguments.length >= 5
244
+
245
+ if (explicitTempDirs) {
246
+ [oldTempDir, newTempDir].forEach(dirPath => {
247
+ const resolvedPath = path.resolve(dirPath) + path.sep
248
+ const isInTmp = resolvedPath.startsWith(tmpRoot)
249
+ const isInWorkspace = resolvedPath.startsWith(workspaceRoot)
250
+
251
+ if (isInWorkspace && isInTmp) {
252
+ try {
253
+ fs.rmSync(dirPath, { recursive: true, force: true })
254
+ console.log(`🧹 Cleaned up temporary directory: ${dirPath}`)
255
+ } catch (err) {
256
+ console.warn(`Warning: Could not clean up directory ${dirPath}: ${err.message}`)
257
+ }
258
+ } else {
259
+ console.log(`ℹ️ Skipping cleanup of directory outside tmp/: ${dirPath}`)
260
+ }
261
+ })
262
+ } else {
263
+ console.log('ℹ️ Using autogenerated directories - skipping cleanup for safety')
264
+ }
265
+ }
266
+
267
+ module.exports = {
268
+ runClusterDocs,
269
+ cleanupOldDiffs,
270
+ generatePropertyComparisonReport,
271
+ updatePropertyOverridesWithVersion,
272
+ diffDirs
273
+ }
@@ -0,0 +1,54 @@
1
+ 'use strict'
2
+
3
+ const path = require('path')
4
+ const fs = require('fs')
5
+
6
+ /**
7
+ * Searches upward from a starting directory to locate the repository root.
8
+ *
9
+ * Traverses parent directories from the specified start path, returning the first
10
+ * directory containing either a `.git` folder or a `package.json` file.
11
+ * Exits the process with an error if no such directory is found.
12
+ *
13
+ * @param {string} [start] - The directory to begin the search from. Defaults to cwd.
14
+ * @returns {string} The absolute path to the repository root directory.
15
+ */
16
+ function findRepoRoot (start = process.cwd()) {
17
+ let dir = start
18
+ while (dir !== path.parse(dir).root) {
19
+ if (
20
+ fs.existsSync(path.join(dir, '.git')) ||
21
+ fs.existsSync(path.join(dir, 'package.json'))
22
+ ) {
23
+ return dir
24
+ }
25
+ dir = path.dirname(dir)
26
+ }
27
+ console.error('Error: Could not find repo root (no .git or package.json in any parent)')
28
+ process.exit(1)
29
+ }
30
+
31
+ /**
32
+ * Prints an error message to stderr and exits the process with a non-zero status.
33
+ *
34
+ * @param {string} msg - The error message to display before exiting.
35
+ */
36
+ function fail (msg) {
37
+ console.error(`Error: ${msg}`)
38
+ process.exit(1)
39
+ }
40
+
41
+ /**
42
+ * Common options for automation tasks
43
+ */
44
+ const commonOptions = {
45
+ dockerRepo: 'redpanda',
46
+ consoleTag: 'latest',
47
+ consoleDockerRepo: 'console'
48
+ }
49
+
50
+ module.exports = {
51
+ findRepoRoot,
52
+ fail,
53
+ commonOptions
54
+ }