@redpanda-data/docs-extensions-and-macros 5.29.0 → 5.31.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.
- package/bin/doc-tools.js +54 -19
- package/bin/mcp-tools/versions.js +1 -1
- package/cli-utils/enterprise-sources.js +6 -6
- package/cli-utils/install-test-dependencies.sh +58 -6
- package/extensions/version-fetcher/set-latest-version.js +11 -2
- package/mcp/CLI_INTERFACE.adoc +1 -1
- package/mcp/USER_GUIDE.adoc +4 -4
- package/package.json +1 -1
- package/tools/bundle-openapi.js +28 -10
- package/tools/get-redpanda-version.js +14 -1
- package/tools/property-extractor/Makefile +99 -42
- package/tools/property-extractor/README.adoc +1 -1
- package/tools/property-extractor/cloud_config.py +11 -7
- package/tools/property-extractor/merge-rp-util.js +208 -0
- package/tools/property-extractor/rp-util-fetch.js +447 -0
- package/tools/property-extractor/rp_util_merge.py +599 -0
- package/tools/property-extractor/templates/property.hbs +12 -5
- package/tools/property-extractor/templates/topic-property.hbs +7 -4
- package/tools/rpk-docs/rpk-docs-handler.js +98 -16
|
@@ -1296,7 +1296,7 @@ node generate-handlebars-docs.js test-input.json test-output
|
|
|
1296
1296
|
|
|
1297
1297
|
== Additional resources
|
|
1298
1298
|
|
|
1299
|
-
* https://github.com/redpanda-data/
|
|
1299
|
+
* https://github.com/redpanda-data/streaming-enterprise[streaming-enterprise Repository] (private; this is where the extractor clones Redpanda's source from)
|
|
1300
1300
|
* https://github.com/redpanda-data/docs-extensions-and-macros[docs-extensions-and-macros Repository]
|
|
1301
1301
|
* https://tree-sitter.github.io/tree-sitter/[Tree-sitter Documentation]
|
|
1302
1302
|
* https://handlebarsjs.com/[Handlebars.js Guide]
|
|
@@ -6,7 +6,7 @@ This module fetches cloud configuration from the cloudv2 repository to determine
|
|
|
6
6
|
which Redpanda properties are supported, editable, or readonly in cloud deployments.
|
|
7
7
|
|
|
8
8
|
Prerequisites:
|
|
9
|
-
- GITHUB_TOKEN environment variable set with appropriate permissions
|
|
9
|
+
- GH_TOKEN, GITHUB_TOKEN, or REDPANDA_GITHUB_TOKEN environment variable set with appropriate permissions
|
|
10
10
|
- Internet connection to access GitHub API
|
|
11
11
|
|
|
12
12
|
Usage:
|
|
@@ -105,14 +105,14 @@ def fetch_cloud_config(github_token: Optional[str] = None) -> CloudConfig:
|
|
|
105
105
|
"""
|
|
106
106
|
Fetch the latest cloud configuration from the redpanda-data/cloudv2 repository and return it as a CloudConfig.
|
|
107
107
|
|
|
108
|
-
This function uses a GitHub personal access token for authentication. If `github_token` is not provided, it will read GITHUB_TOKEN or REDPANDA_GITHUB_TOKEN from the environment. It downloads the most recent versioned YAML from the repository's install-pack directory, validates expected sections (`customer_managed_configs` and `readonly_cluster_config`), and constructs a CloudConfig instance.
|
|
109
|
-
|
|
108
|
+
This function uses a GitHub personal access token for authentication. If `github_token` is not provided, it will read GH_TOKEN, GITHUB_TOKEN, or REDPANDA_GITHUB_TOKEN from the environment. It downloads the most recent versioned YAML from the repository's install-pack directory, validates expected sections (`customer_managed_configs` and `readonly_cluster_config`), and constructs a CloudConfig instance.
|
|
109
|
+
|
|
110
110
|
Parameters:
|
|
111
|
-
github_token (Optional[str]): Personal access token for GitHub API. If omitted, the function will try environment variables GITHUB_TOKEN or REDPANDA_GITHUB_TOKEN.
|
|
112
|
-
|
|
111
|
+
github_token (Optional[str]): Personal access token for GitHub API. If omitted, the function will try environment variables GH_TOKEN, GITHUB_TOKEN, or REDPANDA_GITHUB_TOKEN.
|
|
112
|
+
|
|
113
113
|
Returns:
|
|
114
114
|
CloudConfig: Parsed cloud configuration for the latest available version.
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
Raises:
|
|
117
117
|
GitHubAuthError: Authentication or access problems with the GitHub API (including 401/403 responses).
|
|
118
118
|
NetworkError: Network connectivity or timeout failures when contacting the GitHub API.
|
|
@@ -120,7 +120,11 @@ def fetch_cloud_config(github_token: Optional[str] = None) -> CloudConfig:
|
|
|
120
120
|
CloudConfigError: Generic configuration error (for example, missing token) or unexpected internal failures.
|
|
121
121
|
"""
|
|
122
122
|
if not github_token:
|
|
123
|
-
|
|
123
|
+
# GH_TOKEN takes priority: `doc-tools generate property-docs` pre-resolves
|
|
124
|
+
# a token via cli-utils/github-token.js's full priority chain (GIT_CREDENTIALS,
|
|
125
|
+
# ACTIONS_BOT_TOKEN, etc.) and passes it down as GH_TOKEN, so this must see
|
|
126
|
+
# that name too -- not just the two env vars a directly-invoked `make` sets.
|
|
127
|
+
github_token = os.environ.get('GH_TOKEN') or os.environ.get('GITHUB_TOKEN') or os.environ.get('REDPANDA_GITHUB_TOKEN')
|
|
124
128
|
|
|
125
129
|
if not github_token:
|
|
126
130
|
error_msg = (
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Overwrite cluster/broker scope in an already-extracted --enhanced-output
|
|
6
|
+
* file with rp_util's runtime-introspected data, in place.
|
|
7
|
+
*
|
|
8
|
+
* Called from the Makefile's `build` target, after property_extractor.py's
|
|
9
|
+
* Tree-sitter extraction and before generate-docs renders the result. Topic
|
|
10
|
+
* properties (rp_util has no equivalent) and anything rp_util doesn't cover
|
|
11
|
+
* pass through untouched -- see rp_util_merge.py.
|
|
12
|
+
*
|
|
13
|
+
* Failure behavior depends on what kind of ref is being built:
|
|
14
|
+
*
|
|
15
|
+
* Branch refs (dev, feature branches): never fails the build. If rp_util's
|
|
16
|
+
* schema can't be obtained (no published release for this ref, no GitHub
|
|
17
|
+
* token, no Docker/Bazel available to build from source) or the merge
|
|
18
|
+
* itself errors, this logs a warning and leaves the Tree-sitter-only
|
|
19
|
+
* extraction as the enhanced file, exactly as it already was before this
|
|
20
|
+
* step ran. In-progress content tolerates the degraded data; it gets
|
|
21
|
+
* regenerated constantly.
|
|
22
|
+
*
|
|
23
|
+
* Release tags (v26.3.0, v26.3.1-rc1, ...): fails the build. A release run
|
|
24
|
+
* is the one that publishes the property reference, and shipping the
|
|
25
|
+
* Tree-sitter-only extraction there is not a degradation readers can see
|
|
26
|
+
* past: post streaming-enterprise#63, it silently drops enum_set
|
|
27
|
+
* properties (http_authentication) and misparses others behind a green
|
|
28
|
+
* job. The fix is to publish the schema first (the publish-rp-util-schema
|
|
29
|
+
* workflow, which also runs on a schedule) and re-run; --skip-rp-util /
|
|
30
|
+
* SKIP_RP_UTIL=1 remains the explicit opt-out.
|
|
31
|
+
*
|
|
32
|
+
* Usage:
|
|
33
|
+
* node merge-rp-util.js --tag <ref> --enhanced <path> [--overrides <path>] [--output <path>]
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const fs = require('fs')
|
|
37
|
+
const os = require('os')
|
|
38
|
+
const path = require('path')
|
|
39
|
+
const { spawnSync } = require('child_process')
|
|
40
|
+
const { getRpUtilSchema, SCHEMA_FLAGS } = require('./rp-util-fetch')
|
|
41
|
+
const bigIntJson = require('../../cli-utils/big-int-json')
|
|
42
|
+
|
|
43
|
+
function getArg(args, flag) {
|
|
44
|
+
const i = args.indexOf(flag)
|
|
45
|
+
return i === -1 ? undefined : args[i + 1]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// A ref this pipeline treats as a release build: vX.Y.Z, with or without an
|
|
49
|
+
// -rcN suffix (RC tags feed the docs beta branch, which publishes too). Same
|
|
50
|
+
// release/RC shape streaming-enterprise's own dispatch-docs-updates.yml keys
|
|
51
|
+
// on. Everything else (dev, feature branches, bare SHAs) is in-progress
|
|
52
|
+
// content where a degraded merge is tolerable.
|
|
53
|
+
const RELEASE_TAG_RX = /^v?\d+\.\d+\.\d+(-rc\d+)?$/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Handle a step of the rp_util merge being unavailable: fatal for a release
|
|
57
|
+
* tag (see the header comment), a warning plus the Tree-sitter fallback for
|
|
58
|
+
* everything else.
|
|
59
|
+
*/
|
|
60
|
+
function handleMergeUnavailable(tag, enhanced, reason) {
|
|
61
|
+
if (RELEASE_TAG_RX.test(tag)) {
|
|
62
|
+
// Print the canonical v-prefixed tag in the remediation command:
|
|
63
|
+
// streaming-enterprise tags (and therefore schema release names) are
|
|
64
|
+
// always v-prefixed, so telling the operator to publish a v-less name
|
|
65
|
+
// would send them to a workflow run that can never help.
|
|
66
|
+
const releaseTag = tag.startsWith('v') ? tag : `v${tag}`
|
|
67
|
+
console.error(`Error: ${reason}`)
|
|
68
|
+
console.error(
|
|
69
|
+
`Refusing to publish Tree-sitter-only property data for release ${tag}: ` +
|
|
70
|
+
'it drops or misparses enum_set properties. Publish the rp_util schema ' +
|
|
71
|
+
`first (gh workflow run publish-rp-util-schema.yaml -f tag=${releaseTag}, or wait ` +
|
|
72
|
+
'for its scheduled run) and retry, or pass --skip-rp-util to override.'
|
|
73
|
+
)
|
|
74
|
+
process.exitCode = 1
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
console.warn(`Warning: ${reason}`)
|
|
78
|
+
console.warn('Skipping rp_util merge -- keeping the Tree-sitter-only extraction for cluster/broker scope.')
|
|
79
|
+
markRpUtilMergeUnavailable(enhanced)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// rp_util covers every cluster/broker-scope property (see this file's own
|
|
83
|
+
// header comment), so when its merge is skipped or fails, any cluster/
|
|
84
|
+
// broker property still missing gets_restored isn't "no annotation exists"
|
|
85
|
+
// (the pre-existing, legitimate case property.hbs already renders as an
|
|
86
|
+
// absent row) -- it's "we don't know, because the merge that would have
|
|
87
|
+
// told us didn't run". Mark those explicitly so the template can render
|
|
88
|
+
// that as a visible "Unknown" state instead of silently rendering nothing,
|
|
89
|
+
// which previously made a flaky rp_util fetch indistinguishable from a
|
|
90
|
+
// real upstream change in the generated docs.
|
|
91
|
+
const RP_UTIL_COVERED_SCOPES = new Set(['cluster', 'broker'])
|
|
92
|
+
|
|
93
|
+
function markRpUtilMergeUnavailable(enhancedPath) {
|
|
94
|
+
let data
|
|
95
|
+
try {
|
|
96
|
+
data = bigIntJson.parse(fs.readFileSync(enhancedPath, 'utf8'))
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.warn(`Warning: could not mark rp_util merge as unavailable in ${enhancedPath}: ${err.message}`)
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
const properties = data.properties || {}
|
|
102
|
+
let marked = 0
|
|
103
|
+
for (const prop of Object.values(properties)) {
|
|
104
|
+
if (!prop || !RP_UTIL_COVERED_SCOPES.has(prop.config_scope)) continue
|
|
105
|
+
if (prop.gets_restored !== undefined) continue
|
|
106
|
+
prop.rp_util_merge_status = 'unavailable'
|
|
107
|
+
marked++
|
|
108
|
+
}
|
|
109
|
+
if (marked === 0) return
|
|
110
|
+
try {
|
|
111
|
+
fs.writeFileSync(enhancedPath, bigIntJson.stringify(data))
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.warn(`Warning: could not write rp_util-unavailable marker to ${enhancedPath}: ${err.message}`)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function main() {
|
|
118
|
+
const args = process.argv.slice(2)
|
|
119
|
+
const tag = getArg(args, '--tag')
|
|
120
|
+
const enhanced = getArg(args, '--enhanced')
|
|
121
|
+
const overrides = getArg(args, '--overrides')
|
|
122
|
+
const output = getArg(args, '--output') || enhanced
|
|
123
|
+
const sourcePath = getArg(args, '--source-path')
|
|
124
|
+
// Cluster properties rp_util reports but the Tree-sitter pass never saw
|
|
125
|
+
// have no existing entry to carry cloud metadata forward from, so the
|
|
126
|
+
// merge needs its own CloudConfig to annotate them -- see rp_util_merge.py.
|
|
127
|
+
// Honours CLOUD_SUPPORT=1 as well because that is how doc-tools passes the
|
|
128
|
+
// request down to `make` in the first place.
|
|
129
|
+
const cloudSupport = args.includes('--cloud-support') || process.env.CLOUD_SUPPORT === '1'
|
|
130
|
+
|
|
131
|
+
if (!tag || !enhanced) {
|
|
132
|
+
console.error(
|
|
133
|
+
'Usage: node merge-rp-util.js --tag <ref> --enhanced <path> ' +
|
|
134
|
+
'[--overrides <path>] [--output <path>] [--source-path <dir>] [--cloud-support]'
|
|
135
|
+
)
|
|
136
|
+
process.exit(1)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log(`Fetching rp_util schema for ${tag}...`)
|
|
140
|
+
let schemas
|
|
141
|
+
try {
|
|
142
|
+
// --source-path builds from an existing local streaming-enterprise
|
|
143
|
+
// checkout instead of fetching a published release or cloning+building
|
|
144
|
+
// fresh -- same option rp-util-fetch.js itself exposes, useful for
|
|
145
|
+
// local iteration against a branch that has no published schema yet.
|
|
146
|
+
schemas = await getRpUtilSchema(tag, sourcePath ? { sourcePath } : undefined)
|
|
147
|
+
} catch (err) {
|
|
148
|
+
handleMergeUnavailable(tag, enhanced, `could not get rp_util schema for ${tag}: ${err.message}`)
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const schemaDir = fs.mkdtempSync(path.join(os.tmpdir(), 'rp-util-schemas-'))
|
|
153
|
+
try {
|
|
154
|
+
let anySchema = false
|
|
155
|
+
for (const { key } of SCHEMA_FLAGS) {
|
|
156
|
+
if (schemas[key]) {
|
|
157
|
+
fs.writeFileSync(path.join(schemaDir, `${key}.json`), bigIntJson.stringify(schemas[key]))
|
|
158
|
+
anySchema = true
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (!anySchema) {
|
|
162
|
+
handleMergeUnavailable(tag, enhanced, `rp_util schema for ${tag} came back empty.`)
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const venvPython = path.join(__dirname, 'tmp', 'redpanda-property-extractor-venv', 'bin', 'python')
|
|
167
|
+
const pythonBin = fs.existsSync(venvPython) ? venvPython : 'python3'
|
|
168
|
+
|
|
169
|
+
// Write to a temp path and only rename over the real output on success.
|
|
170
|
+
// output frequently equals enhanced (an in-place update), so a partial
|
|
171
|
+
// write from a mid-json.dump failure must never be able to leave that
|
|
172
|
+
// file truncated -- generate-docs reads it right after this returns.
|
|
173
|
+
const tempOutput = `${output}.rp-util-merge-tmp`
|
|
174
|
+
const mergeArgs = [
|
|
175
|
+
'rp_util_merge.py',
|
|
176
|
+
'--enhanced', enhanced,
|
|
177
|
+
'--rp-util-dir', schemaDir,
|
|
178
|
+
'--output', tempOutput
|
|
179
|
+
]
|
|
180
|
+
if (overrides && fs.existsSync(overrides)) {
|
|
181
|
+
mergeArgs.push('--overrides', overrides)
|
|
182
|
+
}
|
|
183
|
+
if (cloudSupport) {
|
|
184
|
+
mergeArgs.push('--cloud-support')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
console.log('Merging rp_util schema into extracted properties...')
|
|
188
|
+
const result = spawnSync(pythonBin, mergeArgs, { cwd: __dirname, stdio: 'inherit' })
|
|
189
|
+
if (result.error || result.status !== 0) {
|
|
190
|
+
fs.rmSync(tempOutput, { force: true })
|
|
191
|
+
handleMergeUnavailable(
|
|
192
|
+
tag,
|
|
193
|
+
enhanced,
|
|
194
|
+
`rp_util merge failed (${result.error ? result.error.message : `exit ${result.status}`}).`
|
|
195
|
+
)
|
|
196
|
+
} else {
|
|
197
|
+
fs.renameSync(tempOutput, output)
|
|
198
|
+
}
|
|
199
|
+
} finally {
|
|
200
|
+
fs.rmSync(schemaDir, { recursive: true, force: true })
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = { main, markRpUtilMergeUnavailable }
|
|
205
|
+
|
|
206
|
+
if (require.main === module) {
|
|
207
|
+
main()
|
|
208
|
+
}
|