@redpanda-data/docs-extensions-and-macros 4.13.1 → 4.13.3
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/bin/doc-tools-mcp.js +16 -4
- package/bin/doc-tools.js +768 -2089
- package/bin/mcp-tools/generated-docs-review.js +2 -2
- package/bin/mcp-tools/mcp-validation.js +1 -1
- package/bin/mcp-tools/openapi.js +2 -2
- package/bin/mcp-tools/property-docs.js +18 -0
- package/bin/mcp-tools/rpcn-docs.js +28 -3
- package/cli-utils/antora-utils.js +53 -2
- package/cli-utils/dependencies.js +313 -0
- package/cli-utils/diff-utils.js +273 -0
- package/cli-utils/doc-tools-utils.js +54 -0
- package/extensions/algolia-indexer/generate-index.js +134 -102
- package/extensions/algolia-indexer/index.js +70 -38
- package/extensions/collect-bloblang-samples.js +2 -1
- package/extensions/generate-rp-connect-categories.js +125 -67
- package/extensions/generate-rp-connect-info.js +291 -137
- package/macros/rp-connect-components.js +34 -5
- package/package.json +4 -3
- package/tools/add-commercial-names.js +207 -0
- package/tools/bundle-openapi.js +1 -1
- package/tools/generate-cli-docs.js +6 -2
- package/tools/get-console-version.js +5 -0
- package/tools/get-redpanda-version.js +5 -0
- package/tools/property-extractor/compare-properties.js +3 -3
- package/tools/property-extractor/generate-handlebars-docs.js +14 -14
- package/tools/property-extractor/generate-pr-summary.js +46 -0
- package/tools/property-extractor/pr-summary-formatter.js +375 -0
- package/tools/redpanda-connect/README.adoc +403 -38
- package/tools/redpanda-connect/connector-binary-analyzer.js +588 -0
- package/tools/redpanda-connect/generate-rpcn-connector-docs.js +97 -34
- package/tools/redpanda-connect/parse-csv-connectors.js +1 -1
- package/tools/redpanda-connect/pr-summary-formatter.js +663 -0
- package/tools/redpanda-connect/report-delta.js +70 -2
- package/tools/redpanda-connect/rpcn-connector-docs-handler.js +1279 -0
- package/tools/redpanda-connect/templates/connector.hbs +38 -0
- package/tools/redpanda-connect/templates/intro.hbs +0 -20
- package/tools/redpanda-connect/update-nav.js +216 -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
|
+
}
|