@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 CHANGED
@@ -119,7 +119,12 @@ programCli
119
119
  *
120
120
  * @requirements
121
121
  * - Internet connection to access GitHub API
122
- * - GitHub API rate limits apply (60 requests/hour unauthenticated)
122
+ * - A GitHub token with access to redpanda-data/streaming-enterprise, which is
123
+ * private. Redpanda releases are published there now, and the old public repo
124
+ * is frozen, so this command exits rather than report a stale version when it
125
+ * has no token. Resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN,
126
+ * ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in
127
+ * that priority order
123
128
  */
124
129
  programCli
125
130
  .command('get-redpanda-version')
@@ -1057,8 +1062,10 @@ automation
1057
1062
  * @requirements
1058
1063
  * - Python 3.9 or higher
1059
1064
  * - Git
1060
- * - Internet connection to clone Redpanda repository
1061
- * - For --cloud-support: GitHub token with repo permissions (GITHUB_TOKEN env var)
1065
+ * - A GitHub token (resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in that priority order) with
1066
+ * access to redpanda-data/streaming-enterprise, which is private
1067
+ * - Internet connection to clone the streaming-enterprise repository
1068
+ * - For --cloud-support: GitHub token with repo permissions (same resolution chain)
1062
1069
  * - For --cloud-support: Python packages pyyaml and requests
1063
1070
  */
1064
1071
  automation
@@ -1073,7 +1080,9 @@ automation
1073
1080
  .option('--regenerate-old-baseline', 'Re-extract the --diff tag from source instead of using the committed attachments/redpanda-properties-<oldTag>.json baseline')
1074
1081
  .option('--overrides <path>', 'Optional JSON file with property description overrides', 'docs-data/property-overrides.json')
1075
1082
  .option('--output-dir <dir>', 'Where to write all generated files', 'modules/reference')
1076
- .option('--cloud-support', 'Add AsciiDoc tags to generated property docs to indicate which ones are supported in Redpanda Cloud. This data is fetched from the cloudv2 repository so requires a GitHub token with repo permissions. Set the token as an environment variable using GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN', true)
1083
+ .option('--cloud-support', 'Add AsciiDoc tags to generated property docs to indicate which ones are supported in Redpanda Cloud. This data is fetched from the cloudv2 repository so requires a GitHub token with repo permissions. The token is resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in that priority order', true)
1084
+ .option('--no-cloud-support', 'Skip Cloud support tags, and the cloudv2 repository access they need. A GitHub token is still required either way: the extractor clones the private streaming-enterprise repo to read the source')
1085
+ .option('--skip-rp-util', 'Keep cluster/broker scope Tree-sitter-only, skipping the rp_util merge step (default: use rp_util when available, falling back to Tree-sitter-only data if its schema cannot be obtained)')
1077
1086
  .option('--template-property <path>', 'Custom Handlebars template for individual property sections')
1078
1087
  .option('--template-topic-property <path>', 'Custom Handlebars template for topic property sections')
1079
1088
  .option('--template-topic-property-mappings <path>', 'Custom Handlebars template for topic property mappings table')
@@ -1091,17 +1100,35 @@ automation
1091
1100
 
1092
1101
  const newTag = options.tag || options.branch || 'dev'
1093
1102
 
1094
- if (options.cloudSupport) {
1095
- console.log('Validating cloud support dependencies...')
1096
- const { getGitHubToken } = require('../cli-utils/github-token')
1097
- const token = getGitHubToken()
1098
- if (!token) {
1099
- console.error('Error: Cloud support requires a GitHub token')
1100
- console.error(' Set: export GITHUB_TOKEN=your_token_here')
1101
- console.error(' Or disable cloud support with: --no-cloud-support')
1102
- process.exit(1)
1103
+ // Resolved once, via the same priority chain every other GitHub-fetching
1104
+ // command in this CLI already uses (cli-utils/github-token.js) --
1105
+ // notably GIT_CREDENTIALS, which is the token Antora/Netlify builds
1106
+ // actually populate, and which the Makefile's own narrower shell
1107
+ // fallback (REDPANDA_GITHUB_TOKEN/GITHUB_TOKEN/GH_TOKEN only) can't see.
1108
+ // Passed through as GH_TOKEN so the Makefile's clone step picks up
1109
+ // whatever this resolved, private-repo access included, without having
1110
+ // to duplicate the GIT_CREDENTIALS parsing logic in shell.
1111
+ const { getGitHubToken } = require('../cli-utils/github-token')
1112
+ const githubToken = getGitHubToken()
1113
+
1114
+ // A token is required whether or not Cloud metadata is: the extractor
1115
+ // clones the private streaming-enterprise repo to read the source either
1116
+ // way. --no-cloud-support only drops the extra cloudv2 read, so it is not
1117
+ // a remedy for having no token, and pointing at it as one sent people
1118
+ // into a run that got as far as the Makefile's clone step and died there.
1119
+ if (!githubToken) {
1120
+ console.error('Error: Generating property docs requires a GitHub token')
1121
+ console.error(' The extractor reads Redpanda source from the private')
1122
+ console.error(' redpanda-data/streaming-enterprise repository.')
1123
+ console.error(' Set GH_TOKEN, REDPANDA_GITHUB_TOKEN, or GITHUB_TOKEN to a token with access.')
1124
+ if (options.cloudSupport) {
1125
+ console.error(' Cloud support tags (on by default) additionally read the cloudv2 repository;')
1126
+ console.error(' --no-cloud-support skips those, but not the token requirement above.')
1103
1127
  }
1104
- console.log('Done: GitHub token validated')
1128
+ process.exit(1)
1129
+ }
1130
+ if (options.cloudSupport) {
1131
+ console.log('Done: GitHub token validated for source and cloudv2 access')
1105
1132
  }
1106
1133
 
1107
1134
  let oldTag = options.diff
@@ -1127,8 +1154,10 @@ automation
1127
1154
  console.log(`Building property docs for ${tag}…`)
1128
1155
  const args = ['build', `TAG=${tag}`]
1129
1156
  const env = { ...process.env }
1157
+ if (githubToken) env.GH_TOKEN = githubToken
1130
1158
  if (overrides) env.OVERRIDES = path.resolve(overrides)
1131
1159
  if (options.cloudSupport) env.CLOUD_SUPPORT = '1'
1160
+ if (options.skipRpUtil) env.SKIP_RP_UTIL = '1'
1132
1161
  if (templates.property) env.TEMPLATE_PROPERTY = path.resolve(templates.property)
1133
1162
  if (templates.topicProperty) env.TEMPLATE_TOPIC_PROPERTY = path.resolve(templates.topicProperty)
1134
1163
  if (templates.topicPropertyMappings) env.TEMPLATE_TOPIC_PROPERTY_MAPPINGS = path.resolve(templates.topicPropertyMappings)
@@ -1290,8 +1319,9 @@ automation
1290
1319
  *
1291
1320
  * @description
1292
1321
  * Generates comprehensive CLI reference documentation for rpk (Redpanda Keeper).
1293
- * Clones the Redpanda source, builds rpk with Go, and parses `rpk --print-tree` JSON output.
1294
- * Detects Linux-only commands by analyzing Go build tags in the source code.
1322
+ * Clones the Redpanda source from streaming-enterprise (private), builds rpk
1323
+ * with Go, and parses `rpk --print-tree` JSON output. Detects Linux-only
1324
+ * commands by analyzing Go build tags in the source code.
1295
1325
  *
1296
1326
  * Key features:
1297
1327
  * - Clones source from GitHub (sparse checkout for speed)
@@ -1325,6 +1355,9 @@ automation
1325
1355
  * @requirements
1326
1356
  * - Go must be installed (https://go.dev/)
1327
1357
  * - Git must be installed (for cloning source)
1358
+ * - A GitHub token (resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in that priority order) with
1359
+ * access to redpanda-data/streaming-enterprise, which is private (not
1360
+ * needed when --from-source points at an existing local checkout)
1328
1361
  */
1329
1362
  automation
1330
1363
  .command('rpk-docs')
@@ -1875,7 +1908,7 @@ automation
1875
1908
  *
1876
1909
  * @requirements
1877
1910
  * - GitHub token with access to redpanda-data/cloudv2-infra repository
1878
- * - Token must be set via GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN environment variable
1911
+ * - Token is resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in that priority order
1879
1912
  * - Internet connection to access GitHub API
1880
1913
  */
1881
1914
  automation
@@ -2169,7 +2202,9 @@ automation
2169
2202
  * npx doc-tools generate bundle-openapi --tag $VERSION --surface both
2170
2203
  *
2171
2204
  * @requirements
2172
- * - Git to clone Redpanda repository
2205
+ * - Git to clone the streaming-enterprise repository
2206
+ * - A GitHub token (resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in that priority order) with
2207
+ * access to redpanda-data/streaming-enterprise, which is private
2173
2208
  * - Buf tool (automatically installed via npm)
2174
2209
  * - Redocly CLI or vacuum for OpenAPI bundling (automatically detected)
2175
2210
  * - Internet connection to clone repository
@@ -2180,7 +2215,7 @@ automation
2180
2215
  .description('Bundle Redpanda OpenAPI fragments for admin and connect APIs. Requires either --tag or --branch.')
2181
2216
  .option('-t, --tag <tag>', 'Git tag for released content')
2182
2217
  .option('-b, --branch <branch>', 'Branch name for in-progress content')
2183
- .option('--repo <url>', 'Repository URL', 'https://github.com/redpanda-data/redpanda.git')
2218
+ .option('--repo <url>', 'Repository URL. The default is a private repo, so requires a GitHub token (resolved from GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, or GH_TOKEN, in that priority order)', 'https://github.com/redpanda-data/streaming-enterprise.git')
2184
2219
  .addOption(new Option('-s, --surface <surface>', 'Which API surfaces to bundle').choices(['admin', 'connect', 'both']).makeOptionMandatory())
2185
2220
  .option('--out-admin <path>', 'Output path for admin API', 'admin/redpanda-admin-api.yaml')
2186
2221
  .option('--out-connect <path>', 'Output path for connect API', 'connect/redpanda-connect-api.yaml')
@@ -74,7 +74,7 @@ function getRedpandaVersion(args = {}) {
74
74
  version,
75
75
  docker_tag: `docker.redpanda.com/redpandadata/${dockerRepo}:${version}`,
76
76
  is_beta: args.beta || false,
77
- notes_url: `https://github.com/redpanda-data/redpanda/releases/tag/${version}`,
77
+ notes_url: `https://github.com/redpanda-data/streaming-enterprise/releases/tag/${version}`,
78
78
  _modelRecommendation: 'haiku'
79
79
  };
80
80
 
@@ -17,13 +17,13 @@ const { getGitHubToken } = require('./github-token')
17
17
  const RAW = 'https://raw.githubusercontent.com'
18
18
 
19
19
  // Repos known to be private, so a 404 can legitimately mean "needs auth".
20
- // Public sources (redpanda core headers, connect info.csv) 404 only when the
21
- // file is genuinely missing, and suggesting credentials there sends the
22
- // reader after a problem that does not exist (e.g. during a transient
23
- // GitHub blip).
20
+ // Public sources (connect info.csv) 404 only when the file is genuinely
21
+ // missing, and suggesting credentials there sends the reader after a
22
+ // problem that does not exist (e.g. during a transient GitHub blip).
24
23
  const PRIVATE_REPO_PREFIXES = [
25
24
  `${RAW}/redpanda-data/docs/`,
26
25
  `${RAW}/redpanda-data/rp-connect-docs/`,
26
+ `${RAW}/redpanda-data/streaming-enterprise/`,
27
27
  ]
28
28
 
29
29
  const TOKEN_HINT = ' This source is in a private repository: set GIT_CREDENTIALS (or GITHUB_TOKEN / REDPANDA_GITHUB_TOKEN / ACTIONS_BOT_TOKEN) so the fetch can authenticate.'
@@ -220,8 +220,8 @@ async function loadEnterpriseSources (options, deps = {}) {
220
220
  const registryYaml = options.registry
221
221
  ? readLocal(options.registry)
222
222
  : await fetchText(`${RAW}/redpanda-data/docs/${options.docsRef}/shared/modules/ROOT/partials/enterprise-features.yml`)
223
- const coreHeader = await fetchText(`${RAW}/redpanda-data/redpanda/${options.tag}/src/v/features/enterprise_features.h`, 'core enterprise_features.h')
224
- const configurationHeader = await fetchText(`${RAW}/redpanda-data/redpanda/${options.tag}/src/v/config/configuration.h`, 'core configuration.h')
223
+ const coreHeader = await fetchText(`${RAW}/redpanda-data/streaming-enterprise/${options.tag}/src/v/features/enterprise_features.h`, 'core enterprise_features.h')
224
+ const configurationHeader = await fetchText(`${RAW}/redpanda-data/streaming-enterprise/${options.tag}/src/v/config/configuration.h`, 'core configuration.h')
225
225
 
226
226
  let connectRef = options.connectRef
227
227
  let infoCsv
@@ -462,21 +462,73 @@ install_rpk() {
462
462
  ;;
463
463
  esac
464
464
 
465
- # Construct download URL and filename
465
+ # rpk releases now publish to the private redpanda-data/streaming-enterprise,
466
+ # not the public redpanda-data/redpanda, so a token is required (same
467
+ # priority order as cli-utils/github-token.js's getGitHubToken(), minus
468
+ # GIT_CREDENTIALS, which is Antora's own credential store and doesn't
469
+ # apply to this standalone installer script).
470
+ local gh_token="${REDPANDA_GITHUB_TOKEN:-${ACTIONS_BOT_TOKEN:-${GITHUB_TOKEN:-${VBOT_GITHUB_API_TOKEN:-${GH_TOKEN:-}}}}}"
471
+ if [ -z "$gh_token" ]; then
472
+ log_warn "No GitHub token found (checked REDPANDA_GITHUB_TOKEN, ACTIONS_BOT_TOKEN, GITHUB_TOKEN, VBOT_GITHUB_API_TOKEN, GH_TOKEN)."
473
+ log_warn "rpk releases are now published to the private redpanda-data/streaming-enterprise repo and require authentication."
474
+ log_warn "Please install rpk manually:"
475
+ log_warn "https://docs.redpanda.com/current/get-started/rpk-install/"
476
+ return 1
477
+ fi
478
+
466
479
  local rpk_filename="rpk-${rpk_os}-${rpk_arch}.zip"
467
- local rpk_url="https://github.com/redpanda-data/redpanda/releases/latest/download/${rpk_filename}"
468
-
469
- log_info "Detected ${os_name} ${arch_name}, downloading ${rpk_filename}..."
470
-
480
+ local releases_api="https://api.github.com/repos/redpanda-data/streaming-enterprise/releases/latest"
481
+
482
+ log_info "Detected ${os_name} ${arch_name}, looking up the latest rpk release..."
483
+
484
+ # The Authorization header reaches curl through a config file on stdin
485
+ # (--config -), never as an -H argument: an argv header is readable by
486
+ # any process on the host (ps, /proc) for as long as the transfer runs.
487
+ local release_json
488
+ if ! release_json=$(curl -fsSL --retry 5 --retry-all-errors \
489
+ --connect-timeout 30 --max-time 60 --retry-max-time 120 \
490
+ --config - \
491
+ -H "Accept: application/vnd.github+json" \
492
+ "$releases_api" <<EOF
493
+ header = "Authorization: token ${gh_token}"
494
+ EOF
495
+ ); then
496
+ log_warn "Failed to query the latest release from streaming-enterprise"
497
+ log_warn "Please install rpk manually:"
498
+ log_warn "https://docs.redpanda.com/current/get-started/rpk-install/"
499
+ return 1
500
+ fi
501
+
502
+ # Resolve the asset's API url (not browser_download_url): only the API
503
+ # asset endpoint accepts the Authorization header this private repo needs.
504
+ local rpk_url
505
+ rpk_url=$(printf '%s' "$release_json" | jq -r --arg name "$rpk_filename" '.assets[] | select(.name == $name) | .url')
506
+ if [ -z "$rpk_url" ] || [ "$rpk_url" = "null" ]; then
507
+ log_warn "Latest streaming-enterprise release has no asset named ${rpk_filename}"
508
+ log_warn "Please install rpk manually:"
509
+ log_warn "https://docs.redpanda.com/current/get-started/rpk-install/"
510
+ return 1
511
+ fi
512
+
513
+ log_info "Downloading ${rpk_filename}..."
514
+
471
515
  # Try to download and install rpk.
472
516
  # Use -f so HTTP errors (e.g. 403/404/429/503) fail instead of writing an
473
517
  # error page into the zip, and retry with curl's default exponential
474
518
  # backoff (1s, 2s, 4s, ...) to ride out transient GitHub/CDN and network
475
519
  # errors, including rate limits that need time to clear. --retry-max-time
476
520
  # caps the whole retry window so CI fails fast on persistent errors.
521
+ # Accept: application/octet-stream is required on the API asset url to
522
+ # receive the binary itself instead of its JSON metadata.
523
+ # Same as the release lookup above: the token travels on stdin, not argv.
477
524
  if curl -fL --retry 5 --retry-all-errors \
478
525
  --connect-timeout 30 --max-time 300 --retry-max-time 600 \
479
- -o "$rpk_filename" "$rpk_url"; then
526
+ --config - \
527
+ -H "Accept: application/octet-stream" \
528
+ -o "$rpk_filename" "$rpk_url" <<EOF
529
+ header = "Authorization: token ${gh_token}"
530
+ EOF
531
+ then
480
532
  if unzip "$rpk_filename" 2>/dev/null; then
481
533
  mkdir -p ~/.local/bin
482
534
  if mv rpk ~/.local/bin/ 2>/dev/null; then
@@ -16,7 +16,12 @@ module.exports.register = function ({ config }) {
16
16
  const token = getGitHubToken();
17
17
 
18
18
  if (!token) {
19
- logger.warn('GitHub token not set (REDPANDA_GITHUB_TOKEN, GITHUB_TOKEN, or GH_TOKEN). Attempting unauthenticated request.');
19
+ // Unauthenticated requests still work for the public repos this
20
+ // extension queries (connect, redpanda-operator), but the Redpanda
21
+ // version now comes from the private streaming-enterprise repo, whose
22
+ // API 404s without a token -- the latest-redpanda-* attributes are then
23
+ // left unset and pages fall back to their antora.yml values.
24
+ logger.warn('GitHub token not set (GIT_CREDENTIALS, REDPANDA_GITHUB_TOKEN, GITHUB_TOKEN, or GH_TOKEN). The Redpanda version lookup against the private streaming-enterprise repo will fail and leave latest-redpanda-* attributes unset; other lookups proceed unauthenticated.');
20
25
  }
21
26
 
22
27
  this.on('contentClassified', async ({ contentCatalog }) => {
@@ -41,7 +46,11 @@ module.exports.register = function ({ config }) {
41
46
  latestOperatorResult,
42
47
  latestConnectResult,
43
48
  ] = await Promise.allSettled([
44
- GetLatestRedpandaVersion(github, owner, 'redpanda', logger),
49
+ // streaming-enterprise, not the frozen public 'redpanda' repo: the public
50
+ // repo still answers API calls but stopped receiving releases on
51
+ // 2026-08-20, so resolving from it silently pins the docs to the last
52
+ // pre-freeze version forever.
53
+ GetLatestRedpandaVersion(github, owner, 'streaming-enterprise', logger),
45
54
  GetLatestDockerTag(dockerNamespace, 'console', logger),
46
55
  GetLatestDockerTag(dockerNamespace, 'redpanda-operator', logger),
47
56
  GetLatestConnectVersion(github, owner, 'connect', logger),
@@ -43,7 +43,7 @@ npx doc-tools get-redpanda-version [--beta]
43
43
  ----
44
44
  REDPANDA_VERSION=v25.3.1
45
45
  REDPANDA_DOCKER_TAG=docker.redpanda.com/redpandadata/redpanda:v25.3.1
46
- REDPANDA_RELEASE_NOTES=https://github.com/redpanda-data/redpanda/releases/tag/v25.3.1
46
+ REDPANDA_RELEASE_NOTES=https://github.com/redpanda-data/streaming-enterprise/releases/tag/v25.3.1
47
47
  ----
48
48
 
49
49
  *Flags:*
@@ -571,7 +571,7 @@ NOTE: Stack traces are only included when `NODE_ENV=development` for security re
571
571
  "version": "v25.3.1",
572
572
  "docker_tag": "docker.redpanda.com/redpandadata/redpanda:v25.3.1",
573
573
  "is_beta": false,
574
- "notes_url": "https://github.com/redpanda-data/redpanda/releases/tag/v25.3.1"
574
+ "notes_url": "https://github.com/redpanda-data/streaming-enterprise/releases/tag/v25.3.1"
575
575
  }
576
576
  ----
577
577
 
@@ -592,7 +592,7 @@ notes_url:: GitHub release notes URL
592
592
  "version": "v25.4.1-rc1",
593
593
  "docker_tag": "docker.redpanda.com/redpandadata/redpanda-unstable:v25.4.1-rc1",
594
594
  "is_beta": true,
595
- "notes_url": "https://github.com/redpanda-data/redpanda/releases/tag/v25.4.1-rc1"
595
+ "notes_url": "https://github.com/redpanda-data/streaming-enterprise/releases/tag/v25.4.1-rc1"
596
596
  }
597
597
  ----
598
598
 
@@ -857,7 +857,7 @@ Claude: *uses get_redpanda_version MCP tool*
857
857
  The latest Redpanda version is v25.3.1, released on January 15, 2024.
858
858
 
859
859
  Docker tag: docker.redpanda.com/redpandadata/redpanda:v25.3.1
860
- Release notes: https://github.com/redpanda-data/redpanda/releases/tag/v25.3.1
860
+ Release notes: https://github.com/redpanda-data/streaming-enterprise/releases/tag/v25.3.1
861
861
  ----
862
862
 
863
863
  ----
@@ -969,7 +969,7 @@ Claude: *uses generate_property_docs MCP tool*
969
969
  ❌ Generation failed: Tag v99.9.9 not found in Redpanda repository
970
970
 
971
971
  Suggestion: Check that the version exists in the Redpanda repository. You can find available versions at:
972
- https://github.com/redpanda-data/redpanda/releases
972
+ https://github.com/redpanda-data/streaming-enterprise/releases
973
973
  ----
974
974
 
975
975
  === Example 7: Property documentation updates (with prompt)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "5.29.0",
3
+ "version": "5.31.0",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const { execSync, spawnSync } = require('child_process');
5
+ const { execSync, execFileSync, spawnSync } = require('child_process');
6
6
  const yaml = require('yaml');
7
7
  const { getMajorMinor } = require('../cli-utils/version');
8
8
 
@@ -585,7 +585,7 @@ function postProcessBundle(filePath, options, quiet = false) {
585
585
  * @param {string} [options.output] - Standalone output file path; when provided, used for the single output file.
586
586
  * @param {string} [options.outAdmin] - Output path for the admin API when integrating with doc-tools mode.
587
587
  * @param {string} [options.outConnect] - Output path for the connect API when integrating with doc-tools mode.
588
- * @param {string} [options.repo] - Repository URL to clone (defaults to https://github.com/redpanda-data/redpanda.git).
588
+ * @param {string} [options.repo] - Repository URL to clone (defaults to https://github.com/redpanda-data/streaming-enterprise.git, a private repo that requires a GitHub token).
589
589
  * @param {string} [options.adminMajor] - Admin API major version string used for metadata (for example, 'v2.0.0').
590
590
  * @param {boolean} [options.useAdminMajorVersion] - When true and processing the admin surface, use `adminMajor` for the bundle info.version.
591
591
  * @param {boolean} [options.quiet=false] - Suppress logging to stdout/stderr when true.
@@ -649,24 +649,42 @@ async function bundleOpenAPI(options) {
649
649
  try {
650
650
  // Clone repository (only once for all surfaces)
651
651
  if (!quiet) {
652
- console.log('📥 Cloning redpanda repository...');
652
+ console.log('📥 Cloning streaming-enterprise repository...');
653
653
  }
654
654
 
655
- const { getAuthenticatedGitHubUrl, hasGitHubToken } = require('../cli-utils/github-token');
655
+ const { getGitHubToken } = require('../cli-utils/github-token');
656
656
 
657
- let repositoryUrl = repo || 'https://github.com/redpanda-data/redpanda.git';
657
+ const repositoryUrl = repo || 'https://github.com/redpanda-data/streaming-enterprise.git';
658
+ const usingDefaultRepo = !repo;
659
+ const token = getGitHubToken();
658
660
 
659
- // Use token if available for better rate limits and reliability
660
- if (hasGitHubToken() && repositoryUrl.includes('github.com')) {
661
- repositoryUrl = getAuthenticatedGitHubUrl(repositoryUrl);
661
+ if (usingDefaultRepo && !token) {
662
+ throw new Error('redpanda-data/streaming-enterprise is a private repository: set GH_TOKEN, GITHUB_TOKEN, or REDPANDA_GITHUB_TOKEN so the clone can authenticate.');
663
+ }
664
+
665
+ // Auth travels via a credential helper registered through GIT_CONFIG_*
666
+ // environment variables, never as a git -c argument, so the token
667
+ // cannot appear in this process's argv (visible to anything that can
668
+ // list processes) or get embedded in an exec error's command-line
669
+ // message. It's also never embedded in the remote URL or persisted in
670
+ // the clone's .git/config.
671
+ const gitEnv = { ...process.env };
672
+ if (token && repositoryUrl.includes('github.com')) {
662
673
  if (!quiet) {
663
674
  console.log('🔑 Using authenticated clone (token provided)');
664
675
  }
676
+ gitEnv.BUNDLE_OPENAPI_CLONE_TOKEN = token;
677
+ gitEnv.GIT_CONFIG_COUNT = '2';
678
+ gitEnv.GIT_CONFIG_KEY_0 = 'credential.helper';
679
+ gitEnv.GIT_CONFIG_VALUE_0 = '';
680
+ gitEnv.GIT_CONFIG_KEY_1 = 'credential.https://github.com.helper';
681
+ gitEnv.GIT_CONFIG_VALUE_1 = '!f() { echo "username=x-access-token"; echo "password=$BUNDLE_OPENAPI_CLONE_TOKEN"; }; f';
665
682
  }
666
683
 
667
684
  try {
668
- execSync(`git clone --depth 1 --branch ${tag} ${repositoryUrl} redpanda`, {
685
+ execFileSync('git', ['clone', '--depth', '1', '--branch', tag, repositoryUrl, 'redpanda'], {
669
686
  cwd: tempDir,
687
+ env: gitEnv,
670
688
  stdio: quiet ? 'ignore' : 'inherit',
671
689
  timeout: 60000 // 1 minute timeout
672
690
  });
@@ -825,7 +843,7 @@ if (require.main === module) {
825
843
  .option('-o, --output <path>', 'Output file path (defaults: admin/redpanda-admin-api.yaml or connect/redpanda-connect-api.yaml)')
826
844
  .option('--out-admin <path>', 'Output path for admin API', 'admin/redpanda-admin-api.yaml')
827
845
  .option('--out-connect <path>', 'Output path for connect API', 'connect/redpanda-connect-api.yaml')
828
- .option('--repo <url>', 'Repository URL', 'https://github.com/redpanda-data/redpanda.git')
846
+ .option('--repo <url>', 'Repository URL. The default is a private repo, so requires a GitHub token (GH_TOKEN, GITHUB_TOKEN, or REDPANDA_GITHUB_TOKEN)', 'https://github.com/redpanda-data/streaming-enterprise.git')
829
847
  .option('--admin-major <string>', 'Admin API major version', 'v2.0.0')
830
848
  .option('--use-admin-major-version', 'Use admin major version for info.version instead of git tag', false)
831
849
  .option('-q, --quiet', 'Suppress output', false)
@@ -2,6 +2,7 @@
2
2
 
3
3
  const GetLatestRedpandaVersion = require('../extensions/version-fetcher/get-latest-redpanda-version.js');
4
4
  const { getPrereleaseFromAntora } = require('../cli-utils/antora-utils.js');
5
+ const { getGitHubToken } = require('../cli-utils/github-token');
5
6
 
6
7
  /**
7
8
  * Fetches and prints the latest Redpanda version and Docker repository.
@@ -10,8 +11,20 @@ const { getPrereleaseFromAntora } = require('../cli-utils/antora-utils.js');
10
11
  * @param {boolean} options.fromAntora - Whether to derive beta flag from antora.yml
11
12
  */
12
13
  module.exports = async function getRedpandaVersion({ beta = false, fromAntora = false }) {
14
+ // streaming-enterprise, not the old public redpanda repo: the public repo
15
+ // still answers API requests but froze at its 2026-08-20 state when the
16
+ // source moved, so resolving "latest" from it silently pins to the last
17
+ // pre-freeze release forever. streaming-enterprise is private, and
18
+ // unauthenticated release listings 404 rather than fail loudly, so refuse
19
+ // to guess without a token instead of quietly resolving nothing.
13
20
  const owner = 'redpanda-data';
14
- const repo = 'redpanda';
21
+ const repo = 'streaming-enterprise';
22
+
23
+ if (!getGitHubToken()) {
24
+ console.error(`❌ redpanda-data/${repo} is a private repository.`);
25
+ console.error(' Set GH_TOKEN, REDPANDA_GITHUB_TOKEN, or GITHUB_TOKEN to a token with access.');
26
+ process.exit(1);
27
+ }
15
28
 
16
29
  // Determine whether to treat this as a beta (RC) release
17
30
  let useBeta = beta;
@@ -57,6 +57,17 @@ build: venv redpanda-git treesitter
57
57
  $(if $(CLOUD_SUPPORT),--cloud-support,)
58
58
  @echo "✅ JSON generated at $(TOOL_ROOT)/gen/properties-output.json"
59
59
  @echo "✅ Enhanced JSON (with overrides) generated at $(TOOL_ROOT)/gen/$(TAG)-properties.json"
60
+ @if [ -z "$(SKIP_RP_UTIL)" ]; then \
61
+ echo "🔀 Merging rp_util schema for cluster/broker scope…"; \
62
+ cd $(TOOL_ROOT) && node merge-rp-util.js \
63
+ --tag $(TAG) \
64
+ --enhanced gen/$(TAG)-properties.json \
65
+ --output gen/$(TAG)-properties.json \
66
+ $(if $(OVERRIDES),$(if $(shell [ -f "$(OVERRIDES)" ] && echo exists),--overrides $(OVERRIDES),),) \
67
+ $(if $(CLOUD_SUPPORT),--cloud-support,); \
68
+ else \
69
+ echo "⏭️ Skipping rp_util merge (SKIP_RP_UTIL set) -- cluster/broker scope stays Tree-sitter-only"; \
70
+ fi
60
71
  @$(MAKE) generate-docs
61
72
 
62
73
  # --- Ensure Python venv & dependencies ---
@@ -76,55 +87,101 @@ clean:
76
87
  @echo "🧹 Cleaning up…"
77
88
  @rm -rf $(VENV) $(TMP_ROOT) $(REPO_ROOT)/autogenerated
78
89
 
79
- # --- Clone or update Redpanda, checkout TAG or default branch ---
90
+ # --- Clone or update the Redpanda source (now in streaming-enterprise), checkout TAG or default branch ---
80
91
  # Clones are shallow: the extractor only reads source files at a single tag,
81
92
  # so full history is wasted time and disk.
82
- # Auth is passed as a per-invocation HTTP header (git -c before the clone
83
- # subcommand), never embedded in the remote URL, so no token is persisted in
84
- # the clone's .git/config. The clone lives inside the installed package dir,
85
- # so a persisted token would be readable by anything that can list it.
93
+ # Auth travels via a credential helper registered through GIT_CONFIG_*
94
+ # environment variables, never as a git -c argument (which would put the
95
+ # token in this process's argv, visible to anything that can list processes
96
+ # on the runner) and never embedded in the remote URL. The clone lives
97
+ # inside the installed package dir, so a persisted token would also be
98
+ # readable by anything that can list it -- GIT_CONFIG_* env vars don't get
99
+ # written to disk, so nothing persists in the clone's .git/config either.
100
+ # streaming-enterprise is private, so a token is required -- not just
101
+ # preferred the way it was when this cloned the public redpanda repo. GH_TOKEN
102
+ # is checked first because `doc-tools generate property-docs` pre-resolves it
103
+ # via cli-utils/github-token.js's full priority chain (notably GIT_CREDENTIALS,
104
+ # the token Antora/Netlify builds actually populate) before invoking this
105
+ # Makefile. REDPANDA_GITHUB_TOKEN/GITHUB_TOKEN are the fallback for invoking
106
+ # `make` directly, without going through doc-tools.js.
107
+ # An existing checkout may predate the streaming-enterprise migration and
108
+ # still have origin pointed at the old public redpanda repo, so the
109
+ # existing-directory path pins origin to REPO_URL before fetching. Pinning
110
+ # origin is not enough by itself: the old repo's cached remote-tracking refs
111
+ # and tags stay behind it, and a fetch that fails (expired token, outage,
112
+ # ref that does not exist) used to fall straight through to checking one of
113
+ # those out -- generating docs from stale public source under a tag that
114
+ # source never contained, with nothing in the log to say so. So a fetch has
115
+ # to succeed before any ref is resolved, the catch-all fetch prunes refs and
116
+ # tags the new origin does not have, the ref that gets checked out is the
117
+ # one the successful fetch actually wrote, and a TAG that is neither a tag
118
+ # nor a branch there is an error rather than a quiet swap to the default
119
+ # branch.
86
120
  redpanda-git:
87
121
  @mkdir -p "$(TMP_ROOT)"
88
- @echo "🔄 Cloning/updating Redpanda into $(REDPANDA_SRC)…"
89
- @if [ -d "$(REDPANDA_SRC)" ]; then \
90
- git -C "$(REDPANDA_SRC)" fetch --depth 1 -q origin "+refs/tags/$(TAG):refs/tags/$(TAG)" 2>/dev/null || \
91
- git -C "$(REDPANDA_SRC)" fetch --depth 1 -q origin "+refs/heads/$(TAG):refs/remotes/origin/$(TAG)" 2>/dev/null || \
92
- git -C "$(REDPANDA_SRC)" fetch --all --tags -q; \
93
- else \
94
- GH_TOKEN=$${REDPANDA_GITHUB_TOKEN:-$${GITHUB_TOKEN:-$${GH_TOKEN}}}; \
95
- REPO_URL="https://github.com/redpanda-data/redpanda.git"; \
96
- if [ -n "$$GH_TOKEN" ]; then \
97
- echo "🔑 Using authenticated clone (token provided)"; \
98
- AUTH_HEADER="AUTHORIZATION: basic $$(printf '%s' "x-access-token:$$GH_TOKEN" | base64 | tr -d '\n')"; \
99
- else \
100
- AUTH_HEADER=""; \
101
- fi; \
102
- git -c http.https://github.com/.extraheader="$$AUTH_HEADER" clone -q --depth 1 --branch "$(TAG)" "$$REPO_URL" "$(REDPANDA_SRC)" 2>/dev/null || \
103
- git -c http.https://github.com/.extraheader="$$AUTH_HEADER" clone -q --depth 1 "$$REPO_URL" "$(REDPANDA_SRC)"; \
122
+ @GH_TOKEN=$${GH_TOKEN:-$${REDPANDA_GITHUB_TOKEN:-$${GITHUB_TOKEN}}}; \
123
+ if [ -z "$$GH_TOKEN" ]; then \
124
+ echo "❌ redpanda-data/streaming-enterprise is a private repository."; \
125
+ echo " Set GH_TOKEN, REDPANDA_GITHUB_TOKEN, or GITHUB_TOKEN to a token with access."; \
126
+ exit 1; \
104
127
  fi; \
105
- if git -C "$(REDPANDA_SRC)" rev-parse --verify -q "origin/$(TAG)" >/dev/null 2>&1; then \
106
- echo "🔖 Checking out remote branch 'origin/$(TAG)'"; \
107
- git -C "$(REDPANDA_SRC)" checkout -q "$(TAG)" 2>/dev/null || git -C "$(REDPANDA_SRC)" checkout -q -b "$(TAG)" "origin/$(TAG)"; \
108
- git -C "$(REDPANDA_SRC)" reset --hard "origin/$(TAG)" -q; \
109
- elif git -C "$(REDPANDA_SRC)" rev-parse --verify -q "$(TAG)" >/dev/null 2>&1; then \
110
- echo "🔖 Checking out '$(TAG)'"; \
111
- git -C "$(REDPANDA_SRC)" checkout -q "$(TAG)"; \
128
+ export GIT_MAKEFILE_CLONE_TOKEN="$$GH_TOKEN"; \
129
+ export GIT_CONFIG_COUNT=2; \
130
+ export GIT_CONFIG_KEY_0=credential.helper; \
131
+ export GIT_CONFIG_VALUE_0=; \
132
+ export GIT_CONFIG_KEY_1=credential.https://github.com.helper; \
133
+ export GIT_CONFIG_VALUE_1='!f() { echo "username=x-access-token"; echo "password=$$GIT_MAKEFILE_CLONE_TOKEN"; }; f'; \
134
+ REPO_URL="https://github.com/redpanda-data/streaming-enterprise.git"; \
135
+ echo "🔄 Cloning/updating streaming-enterprise into $(REDPANDA_SRC)…"; \
136
+ FETCH_LOG="$$(mktemp)"; \
137
+ FETCHED=""; \
138
+ if [ -d "$(REDPANDA_SRC)" ]; then \
139
+ git -C "$(REDPANDA_SRC)" remote set-url origin "$$REPO_URL" 2>/dev/null || \
140
+ git -C "$(REDPANDA_SRC)" remote add origin "$$REPO_URL"; \
141
+ if git -C "$(REDPANDA_SRC)" fetch --depth 1 -q origin "+refs/tags/$(TAG):refs/tags/$(TAG)" >>"$$FETCH_LOG" 2>&1; then \
142
+ FETCHED=tag; \
143
+ elif git -C "$(REDPANDA_SRC)" fetch --depth 1 -q origin "+refs/heads/$(TAG):refs/remotes/origin/$(TAG)" >>"$$FETCH_LOG" 2>&1; then \
144
+ FETCHED=branch; \
145
+ elif git -C "$(REDPANDA_SRC)" fetch --all --tags --prune --prune-tags -q >>"$$FETCH_LOG" 2>&1; then \
146
+ FETCHED=probe; \
147
+ fi; \
112
148
  else \
113
- DEFAULT_BRANCH=$$(git -C "$(REDPANDA_SRC)" symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null || true); \
114
- if [ -n "$$DEFAULT_BRANCH" ]; then \
115
- echo "⚠️ Tag '$(TAG)' not found; falling back to '$${DEFAULT_BRANCH}'"; \
116
- git -C "$(REDPANDA_SRC)" checkout -q "$${DEFAULT_BRANCH}"; \
117
- else \
118
- DEFAULT_BRANCH=$$(git -C "$(REDPANDA_SRC)" ls-remote --symref origin HEAD | awk '/^ref:/ {sub(/^refs\/heads\//, "", $$2); print $$2; exit}'); \
119
- if [ -z "$$DEFAULT_BRANCH" ]; then \
120
- echo "❌ Tag '$(TAG)' not found and the default branch could not be determined"; \
121
- exit 1; \
122
- fi; \
123
- echo "⚠️ Tag '$(TAG)' not found; falling back to '$${DEFAULT_BRANCH}'"; \
124
- git -C "$(REDPANDA_SRC)" fetch --depth 1 -q origin "$$DEFAULT_BRANCH"; \
125
- git -C "$(REDPANDA_SRC)" checkout -q FETCH_HEAD; \
149
+ echo "🔑 Using authenticated clone"; \
150
+ if git clone -q --depth 1 --branch "$(TAG)" "$$REPO_URL" "$(REDPANDA_SRC)" >>"$$FETCH_LOG" 2>&1; then \
151
+ FETCHED=probe; \
126
152
  fi; \
127
- fi
153
+ fi; \
154
+ if [ -z "$$FETCHED" ]; then \
155
+ echo "❌ Could not fetch '$(TAG)' from redpanda-data/streaming-enterprise:"; \
156
+ sed 's/^/ /' "$$FETCH_LOG"; \
157
+ echo " Not continuing: anything already in $(REDPANDA_SRC) can predate the"; \
158
+ echo " streaming-enterprise migration, and generating docs from it would"; \
159
+ echo " publish stale public source under this tag. Check that the token is"; \
160
+ echo " valid and has access to the repository, and that '$(TAG)' exists there."; \
161
+ rm -f "$$FETCH_LOG"; \
162
+ exit 1; \
163
+ fi; \
164
+ rm -f "$$FETCH_LOG"; \
165
+ case "$$FETCHED" in \
166
+ tag) REF="refs/tags/$(TAG)";; \
167
+ branch) REF="refs/remotes/origin/$(TAG)";; \
168
+ *) REF=""; \
169
+ for candidate in "refs/tags/$(TAG)" "refs/remotes/origin/$(TAG)"; do \
170
+ if git -C "$(REDPANDA_SRC)" rev-parse --verify -q "$$candidate" >/dev/null 2>&1; then \
171
+ REF="$$candidate"; \
172
+ break; \
173
+ fi; \
174
+ done;; \
175
+ esac; \
176
+ if [ -z "$$REF" ]; then \
177
+ echo "❌ '$(TAG)' is neither a tag nor a branch in redpanda-data/streaming-enterprise."; \
178
+ echo " Not falling back to the default branch: that would publish docs labelled"; \
179
+ echo " '$(TAG)' built from entirely different source."; \
180
+ exit 1; \
181
+ fi; \
182
+ echo "🔖 Checking out '$$REF'"; \
183
+ git -C "$(REDPANDA_SRC)" checkout -q --detach "$$REF"; \
184
+ git -C "$(REDPANDA_SRC)" reset --hard -q "$$REF"
128
185
 
129
186
  # --- Clone Tree-sitter grammar & generate parser ---
130
187
  # Skips npm install and parser generation when the generated output already