@redpanda-data/docs-extensions-and-macros 4.8.0 β†’ 4.9.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.
Files changed (30) hide show
  1. package/bin/doc-tools.js +236 -54
  2. package/package.json +1 -1
  3. package/tools/property-extractor/Makefile +68 -50
  4. package/tools/property-extractor/cloud_config.py +594 -0
  5. package/tools/property-extractor/compare-properties.js +378 -0
  6. package/tools/property-extractor/generate-handlebars-docs.js +444 -0
  7. package/tools/property-extractor/helpers/and.js +10 -0
  8. package/tools/property-extractor/helpers/eq.js +9 -0
  9. package/tools/property-extractor/helpers/formatPropertyValue.js +128 -0
  10. package/tools/property-extractor/helpers/formatUnits.js +26 -0
  11. package/tools/property-extractor/helpers/index.js +13 -0
  12. package/tools/property-extractor/helpers/join.js +18 -0
  13. package/tools/property-extractor/helpers/ne.js +9 -0
  14. package/tools/property-extractor/helpers/not.js +8 -0
  15. package/tools/property-extractor/helpers/or.js +10 -0
  16. package/tools/property-extractor/helpers/renderPropertyExample.js +42 -0
  17. package/tools/property-extractor/package-lock.json +77 -0
  18. package/tools/property-extractor/package.json +6 -0
  19. package/tools/property-extractor/parser.py +27 -1
  20. package/tools/property-extractor/property_extractor.py +1428 -49
  21. package/tools/property-extractor/requirements.txt +2 -0
  22. package/tools/property-extractor/templates/deprecated-properties.hbs +25 -0
  23. package/tools/property-extractor/templates/deprecated-property.hbs +7 -0
  24. package/tools/property-extractor/templates/property-cloud.hbs +105 -0
  25. package/tools/property-extractor/templates/property-page.hbs +22 -0
  26. package/tools/property-extractor/templates/property.hbs +85 -0
  27. package/tools/property-extractor/templates/topic-property-cloud.hbs +97 -0
  28. package/tools/property-extractor/templates/topic-property.hbs +73 -0
  29. package/tools/property-extractor/transformers.py +178 -6
  30. package/tools/property-extractor/json-to-asciidoc/generate_docs.py +0 -491
package/bin/doc-tools.js CHANGED
@@ -98,7 +98,7 @@ function requireCmd(cmd, help, versionFlag = '--version') {
98
98
  * @param {number} [minMinor=10] - Minimum required minor version of Python.
99
99
  */
100
100
  function requirePython(minMajor = 3, minMinor = 10) {
101
- const candidates = ['python3', 'python'];
101
+ const candidates = ['python3', 'python', 'python3.12', 'python3.11', 'python3.10'];
102
102
  for (const p of candidates) {
103
103
  try {
104
104
  const out = execSync(`${p} --version`, { encoding: 'utf8' }).trim();
@@ -234,12 +234,16 @@ For more details, visit: https://github.com/norwoodj/helm-docs
234
234
  /**
235
235
  * Ensures all dependencies required for generating property documentation are installed.
236
236
  *
237
- * Checks for the presence of `make`, Python 3.10 or newer, C++ compiler, and C++ standard library headers.
237
+ * Checks for the presence of `make`, Python 3.10 or newer, Node.js, C++ compiler, and C++ standard library headers.
238
238
  * Exits the process with an error message if any dependency is missing.
239
239
  */
240
240
  function verifyPropertyDependencies() {
241
241
  requireCmd('make', 'Your OS package manager');
242
242
  requirePython();
243
+
244
+ // Check for Node.js (required for Handlebars templates)
245
+ requireCmd('node', 'https://nodejs.org/en/download/ or use your package manager (e.g., brew install node)');
246
+ requireCmd('npm', 'Usually installed with Node.js');
243
247
 
244
248
  // Check for C++ compiler
245
249
  let cppCompiler = null;
@@ -455,33 +459,135 @@ const commonOptions = {
455
459
  consoleDockerRepo: 'console',
456
460
  };
457
461
 
462
+ /**
463
+ * Run the cluster documentation generator script for a specific release/tag.
464
+ *
465
+ * Invokes the external `generate-cluster-docs.sh` script with the provided mode, tag,
466
+ * and Docker-related options. The script's stdout/stderr are forwarded to the current
467
+ * process; if the script exits with a non-zero status, this function will terminate
468
+ * the Node.js process with that status code.
469
+ *
470
+ * @param {string} mode - Operation mode passed to the script (e.g., "generate" or "clean").
471
+ * @param {string} tag - Release tag or version to generate docs for.
472
+ * @param {Object} options - Runtime options.
473
+ * @param {string} options.dockerRepo - Docker repository used by the script.
474
+ * @param {string} options.consoleTag - Console image tag passed to the script.
475
+ * @param {string} options.consoleDockerRepo - Console Docker repository used by the script.
476
+ */
458
477
  function runClusterDocs(mode, tag, options) {
459
478
  const script = path.join(__dirname, '../cli-utils/generate-cluster-docs.sh');
460
479
  const args = [mode, tag, options.dockerRepo, options.consoleTag, options.consoleDockerRepo];
461
480
  console.log(`⏳ Running ${script} with arguments: ${args.join(' ')}`);
462
- const r = spawnSync('bash', [script, ...args], { stdio: 'inherit', shell: true });
481
+ const r = spawnSync('bash', [script, ...args], { stdio: 'inherit' });
463
482
  if (r.status !== 0) process.exit(r.status);
464
483
  }
465
484
 
466
- // helper to diff two autogenerated directories
467
- function diffDirs(kind, oldTag, newTag) {
468
- const oldDir = path.join('autogenerated', oldTag, kind);
469
- const newDir = path.join('autogenerated', newTag, kind);
470
- const diffDir = path.join('autogenerated', 'diffs', kind, `${oldTag}_to_${newTag}`);
471
- const patch = path.join(diffDir, 'changes.patch');
485
+ /**
486
+ * Generate a detailed JSON report describing property changes between two releases.
487
+ *
488
+ * Looks for `<oldTag>-properties.json` and `<newTag>-properties.json` in
489
+ * `modules/reference/examples`. If both files exist, invokes the external
490
+ * property comparison tool to produce `property-changes-<oldTag>-to-<newTag>.json`
491
+ * in the provided output directory.
492
+ *
493
+ * If either input JSON is missing the function logs a message and returns without
494
+ * error. Any errors from the comparison tool are logged; the function does not
495
+ * throw.
496
+ *
497
+ * @param {string} oldTag - Release tag or identifier for the "old" properties set.
498
+ * @param {string} newTag - Release tag or identifier for the "new" properties set.
499
+ * @param {string} outputDir - Directory where the comparison report will be written.
500
+ */
501
+ function generatePropertyComparisonReport(oldTag, newTag, outputDir) {
502
+ try {
503
+ console.log(`\nπŸ“Š Generating detailed property comparison report...`);
504
+
505
+ // Look for the property JSON files in modules/reference/examples
506
+ const repoRoot = findRepoRoot();
507
+ const examplesDir = path.join(repoRoot, 'modules', 'reference', 'examples');
508
+ const oldJsonPath = path.join(examplesDir, `${oldTag}-properties.json`);
509
+ const newJsonPath = path.join(examplesDir, `${newTag}-properties.json`);
510
+
511
+ // Check if JSON files exist
512
+ if (!fs.existsSync(oldJsonPath)) {
513
+ console.log(`⚠️ Old properties JSON not found at: ${oldJsonPath}`);
514
+ console.log(` Skipping detailed property comparison.`);
515
+ return;
516
+ }
517
+
518
+ if (!fs.existsSync(newJsonPath)) {
519
+ console.log(`⚠️ New properties JSON not found at: ${newJsonPath}`);
520
+ console.log(` Skipping detailed property comparison.`);
521
+ return;
522
+ }
523
+
524
+ // Ensure output directory exists (use absolute path)
525
+ const absoluteOutputDir = path.resolve(outputDir);
526
+ fs.mkdirSync(absoluteOutputDir, { recursive: true });
527
+
528
+ // Run the property comparison tool with descriptive filename
529
+ const propertyExtractorDir = path.resolve(__dirname, '../tools/property-extractor');
530
+ const compareScript = path.join(propertyExtractorDir, 'compare-properties.js');
531
+ const reportFilename = `property-changes-${oldTag}-to-${newTag}.json`;
532
+ const reportPath = path.join(absoluteOutputDir, reportFilename);
533
+ const args = [compareScript, oldJsonPath, newJsonPath, oldTag, newTag, absoluteOutputDir, reportFilename];
534
+
535
+ const result = spawnSync('node', args, {
536
+ stdio: 'inherit',
537
+ cwd: propertyExtractorDir
538
+ });
539
+
540
+ if (result.error) {
541
+ console.error(`❌ Property comparison failed: ${result.error.message}`);
542
+ } else if (result.status !== 0) {
543
+ console.error(`❌ Property comparison exited with code: ${result.status}`);
544
+ } else {
545
+ console.log(`βœ… Property comparison report saved to: ${reportPath}`);
546
+ }
547
+ } catch (error) {
548
+ console.error(`❌ Error generating property comparison: ${error.message}`);
549
+ }
550
+ }
551
+
552
+ /**
553
+ * Create a unified diff patch between two temporary directories and clean them up.
554
+ *
555
+ * Ensures both source directories exist, writes a recursive unified diff
556
+ * (changes.patch) to tmp/diffs/<kind>/<oldTag>_to_<newTag>/, and removes the
557
+ * provided temporary directories. On missing inputs or if the diff subprocess
558
+ * fails to spawn, the process exits with a non-zero status.
559
+ *
560
+ * @param {string} kind - Logical category for the diff (e.g., "metrics" or "rpk"); used in the output path.
561
+ * @param {string} oldTag - Identifier for the "old" version (used in the output path).
562
+ * @param {string} newTag - Identifier for the "new" version (used in the output path).
563
+ * @param {string} oldTempDir - Path to the existing temporary directory containing the old output; must exist.
564
+ * @param {string} newTempDir - Path to the existing temporary directory containing the new output; must exist.
565
+ */
566
+ function diffDirs(kind, oldTag, newTag, oldTempDir, newTempDir) {
567
+ // Backwards compatibility: if temp directories not provided, use autogenerated paths
568
+ if (!oldTempDir) {
569
+ oldTempDir = path.join('autogenerated', oldTag, kind);
570
+ }
571
+ if (!newTempDir) {
572
+ newTempDir = path.join('autogenerated', newTag, kind);
573
+ }
472
574
 
473
- if (!fs.existsSync(oldDir)) {
474
- console.error(`❌ Cannot diff: missing ${oldDir}`);
575
+ const diffDir = path.join('tmp', 'diffs', kind, `${oldTag}_to_${newTag}`);
576
+
577
+ if (!fs.existsSync(oldTempDir)) {
578
+ console.error(`❌ Cannot diff: missing ${oldTempDir}`);
475
579
  process.exit(1);
476
580
  }
477
- if (!fs.existsSync(newDir)) {
478
- console.error(`❌ Cannot diff: missing ${newDir}`);
581
+ if (!fs.existsSync(newTempDir)) {
582
+ console.error(`❌ Cannot diff: missing ${newTempDir}`);
479
583
  process.exit(1);
480
584
  }
481
585
 
482
586
  fs.mkdirSync(diffDir, { recursive: true });
483
587
 
484
- const cmd = `diff -ru "${oldDir}" "${newDir}" > "${patch}" || true`;
588
+ // Generate traditional patch for metrics and rpk
589
+ const patch = path.join(diffDir, 'changes.patch');
590
+ const cmd = `diff -ru "${oldTempDir}" "${newTempDir}" > "${patch}" || true`;
485
591
  const res = spawnSync(cmd, { stdio: 'inherit', shell: true });
486
592
 
487
593
  if (res.error) {
@@ -489,6 +595,36 @@ function diffDirs(kind, oldTag, newTag) {
489
595
  process.exit(1);
490
596
  }
491
597
  console.log(`βœ… Wrote patch: ${patch}`);
598
+
599
+ // Safety guard: only clean up directories that are explicitly passed as temp directories
600
+ // For backwards compatibility with autogenerated paths, don't clean up automatically
601
+ const tmpRoot = path.resolve('tmp') + path.sep;
602
+ const workspaceRoot = path.resolve('.') + path.sep;
603
+
604
+ // Only clean up if directories were explicitly provided as temp directories
605
+ // (indicated by having all 5 parameters) and they're in the tmp/ directory
606
+ const explicitTempDirs = arguments.length >= 5;
607
+
608
+ if (explicitTempDirs) {
609
+ [oldTempDir, newTempDir].forEach(dirPath => {
610
+ const resolvedPath = path.resolve(dirPath) + path.sep;
611
+ const isInTmp = resolvedPath.startsWith(tmpRoot);
612
+ const isInWorkspace = resolvedPath.startsWith(workspaceRoot);
613
+
614
+ if (isInWorkspace && isInTmp) {
615
+ try {
616
+ fs.rmSync(dirPath, { recursive: true, force: true });
617
+ console.log(`🧹 Cleaned up temporary directory: ${dirPath}`);
618
+ } catch (err) {
619
+ console.warn(`⚠️ Warning: Could not clean up directory ${dirPath}: ${err.message}`);
620
+ }
621
+ } else {
622
+ console.log(`ℹ️ Skipping cleanup of directory outside tmp/: ${dirPath}`);
623
+ }
624
+ });
625
+ } else {
626
+ console.log(`ℹ️ Using autogenerated directories - skipping cleanup for safety`);
627
+ }
492
628
  }
493
629
 
494
630
  automation
@@ -747,50 +883,85 @@ automation
747
883
  .description('Generate JSON and AsciiDoc documentation for Redpanda configuration properties')
748
884
  .option('--tag <tag>', 'Git tag or branch to extract from', 'dev')
749
885
  .option('--diff <oldTag>', 'Also diff autogenerated properties from <oldTag> β†’ <tag>')
886
+ .option('--overrides <path>', 'Optional JSON file with property description overrides')
887
+ .option('--output-dir <dir>', 'Where to write all generated files', 'modules/reference')
888
+ .option('--cloud-support', 'Enable cloud support metadata by fetching configuration from the cloudv2 repository (requires GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN)')
889
+ .option('--template-property-page <path>', 'Custom Handlebars template for property page layout')
890
+ .option('--template-property <path>', 'Custom Handlebars template for individual property sections')
891
+ .option('--template-topic-property <path>', 'Custom Handlebars template for individual topic property sections')
892
+ .option('--template-deprecated <path>', 'Custom Handlebars template for deprecated properties page')
893
+ .option('--template-deprecated-property <path>', 'Custom Handlebars template for individual deprecated property sections')
750
894
  .action((options) => {
751
895
  verifyPropertyDependencies();
752
896
 
753
- const newTag = options.tag;
754
- const oldTag = options.diff;
755
- const cwd = path.resolve(__dirname, '../tools/property-extractor');
756
- const make = (tag) => {
757
- console.log(`⏳ Building property docs for ${tag}…`);
758
- const r = spawnSync('make', ['build', `TAG=${tag}`], { cwd, stdio: 'inherit' });
759
- if (r.error) {
760
- console.error(`❌ ${r.error.message}`);
897
+ // Validate cloud support dependencies if requested
898
+ if (options.cloudSupport) {
899
+ console.log('πŸ” Validating cloud support dependencies...');
900
+
901
+ // Check for GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN
902
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || process.env.REDPANDA_GITHUB_TOKEN;
903
+ if (!token) {
904
+ console.error('❌ Cloud support requires GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN environment variable');
905
+ console.error(' Set up GitHub token:');
906
+ console.error(' 1. Go to https://github.com/settings/tokens');
907
+ console.error(' 2. Generate token with "repo" scope');
908
+ console.error(' 3. Set: export GITHUB_TOKEN=your_token_here');
909
+ console.error(' Or: export GH_TOKEN=your_token_here');
910
+ console.error(' Or: export REDPANDA_GITHUB_TOKEN=your_token_here');
761
911
  process.exit(1);
762
912
  }
763
- if (r.status !== 0) process.exit(r.status);
764
- };
765
-
766
- if (oldTag) {
767
- const oldDir = path.join('autogenerated', oldTag, 'properties');
768
- if (!fs.existsSync(oldDir)) make(oldTag);
769
- }
770
-
771
- make(newTag);
772
-
773
- if (oldTag) {
774
- diffDirs('properties', oldTag, newTag);
913
+
914
+ console.log('πŸ“¦ Cloud support enabled - Python dependencies will be validated during execution');
915
+ if (process.env.VIRTUAL_ENV) {
916
+ console.log(` Using virtual environment: ${process.env.VIRTUAL_ENV}`);
917
+ }
918
+ console.log(' Required packages: pyyaml, requests');
919
+ console.log('βœ… GitHub token validated');
775
920
  }
776
921
 
777
- process.exit(0);
778
- });
779
-
780
- automation
781
- .command('topic-property-docs')
782
- .description('Generate JSON and AsciiDoc documentation for Redpanda topic configuration properties')
783
- .option('--tag <tag>', 'Git tag or branch to extract from', 'dev')
784
- .option('--diff <oldTag>', 'Also diff autogenerated topic properties from <oldTag> β†’ <tag>')
785
- .action((options) => {
786
- verifyPropertyDependencies();
787
-
788
922
  const newTag = options.tag;
789
923
  const oldTag = options.diff;
924
+ const overridesPath = options.overrides;
925
+ const outputDir = options.outputDir;
790
926
  const cwd = path.resolve(__dirname, '../tools/property-extractor');
791
- const make = (tag) => {
792
- console.log(`⏳ Building topic property docs for ${tag}…`);
793
- const r = spawnSync('make', ['topic-properties', `TAG=${tag}`], { cwd, stdio: 'inherit' });
927
+
928
+ const make = (tag, overrides, templates = {}, outputDir = 'modules/reference/', tempDir = null, cloudSupport = false) => {
929
+ console.log(`⏳ Building property docs for ${tag}${tempDir ? ' (for diff)' : ''}…`);
930
+ const args = ['build', `TAG=${tag}`];
931
+
932
+ // Pass all paths as environment variables for consistency
933
+ const env = { ...process.env };
934
+ if (overrides) {
935
+ env.OVERRIDES = path.resolve(overrides);
936
+ }
937
+ if (cloudSupport) {
938
+ env.CLOUD_SUPPORT = '1';
939
+ }
940
+ if (templates.propertyPage) {
941
+ env.TEMPLATE_PROPERTY_PAGE = path.resolve(templates.propertyPage);
942
+ }
943
+ if (templates.property) {
944
+ env.TEMPLATE_PROPERTY = path.resolve(templates.property);
945
+ }
946
+ if (templates.topicProperty) {
947
+ env.TEMPLATE_TOPIC_PROPERTY = path.resolve(templates.topicProperty);
948
+ }
949
+ if (templates.deprecated) {
950
+ env.TEMPLATE_DEPRECATED = path.resolve(templates.deprecated);
951
+ }
952
+ if (templates.deprecatedProperty) {
953
+ env.TEMPLATE_DEPRECATED_PROPERTY = path.resolve(templates.deprecatedProperty);
954
+ }
955
+
956
+ if (tempDir) {
957
+ env.OUTPUT_JSON_DIR = path.resolve(tempDir, 'examples');
958
+ env.OUTPUT_AUTOGENERATED_DIR = path.resolve(tempDir);
959
+ } else {
960
+ env.OUTPUT_JSON_DIR = path.resolve(outputDir, 'examples');
961
+ env.OUTPUT_AUTOGENERATED_DIR = path.resolve(outputDir);
962
+ }
963
+
964
+ const r = spawnSync('make', args, { cwd, stdio: 'inherit', env });
794
965
  if (r.error) {
795
966
  console.error(`❌ ${r.error.message}`);
796
967
  process.exit(1);
@@ -798,15 +969,26 @@ automation
798
969
  if (r.status !== 0) process.exit(r.status);
799
970
  };
800
971
 
972
+ // Collect template options
973
+ const templates = {
974
+ propertyPage: options.templatePropertyPage,
975
+ property: options.templateProperty,
976
+ topicProperty: options.templateTopicProperty,
977
+ deprecated: options.templateDeprecated,
978
+ deprecatedProperty: options.templateDeprecatedProperty
979
+ };
980
+
801
981
  if (oldTag) {
802
- const oldDir = path.join('autogenerated', oldTag, 'properties');
803
- if (!fs.existsSync(oldDir)) make(oldTag);
982
+ // Generate old version directly to final destination so its JSON is available for comparison
983
+ make(oldTag, overridesPath, templates, outputDir, null, options.cloudSupport);
804
984
  }
805
985
 
806
- make(newTag);
986
+ // Generate new version to final destination
987
+ make(newTag, overridesPath, templates, outputDir, null, options.cloudSupport);
807
988
 
808
989
  if (oldTag) {
809
- diffDirs('properties', oldTag, newTag);
990
+ // Generate property comparison report using the JSON files now in modules/reference/examples
991
+ generatePropertyComparisonReport(oldTag, newTag, 'modules/reference');
810
992
  }
811
993
 
812
994
  process.exit(0);
@@ -1015,9 +1197,9 @@ automation
1015
1197
  const { generateCloudRegions } = require('../tools/cloud-regions/generate-cloud-regions.js');
1016
1198
 
1017
1199
  try {
1018
- const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
1200
+ const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || process.env.REDPANDA_GITHUB_TOKEN;
1019
1201
  if (!token) {
1020
- throw new Error('GITHUB_TOKEN environment variable is required to fetch from private cloudv2-infra repo.');
1202
+ throw new Error('GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN environment variable is required to fetch from private cloudv2-infra repo.');
1021
1203
  }
1022
1204
  const fmt = (options.format || 'md').toLowerCase();
1023
1205
  let templatePath = undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -1,16 +1,4 @@
1
- .PHONY: build venv clean redpanda-git treesitter topic-properties generate-docs check
2
-
3
- # --- Main build: venv, fetch code, build parser, extract & docgen ---
4
- build: venv redpanda-git treesitter
5
- @echo "πŸ”§ Building with Redpanda tag: $(TAG)"
6
- @mkdir -p $(TOOL_ROOT)/gen
7
- @cd $(TOOL_ROOT) && \
8
- $(PYTHON) -W ignore::FutureWarning property_extractor.py \
9
- --recursive \
10
- --path $(REDPANDA_SRC) \
11
- --output gen/properties-output.json
12
- @echo "βœ… Cluster properties JSON generated at $(TOOL_ROOT)/gen/properties-output.json"
13
- @$(MAKE) generate-docs
1
+ .PHONY: build venv clean redpanda-git treesitter generate-docs check
14
2
 
15
3
  # Default tag (can be overridden via `make TAG=v25.1.1`)
16
4
  TAG ?= dev
@@ -18,11 +6,11 @@ TAG ?= dev
18
6
  # Derive a β€œmajor.minor” or rc identifier from TAG for folder naming
19
7
  VERSION := $(shell \
20
8
  if echo "$(TAG)" | grep -qE '^v?[0-9]+\.[0-9]+'; then \
21
- echo "$(TAG)" \
22
- | sed -E 's/^v?([0-9]+\.[0-9]+)(\.[0-9]+)?(-rc[0-9]+)?.*/\1\3/' \
23
- | sed 's/-rc/rc/'; \
9
+ echo "$(TAG)" \
10
+ | sed -E 's/^v?([0-9]+\.[0-9]+)(\.[0-9]+)?(-rc[0-9]+)?.*/\1\3/' \
11
+ | sed 's/-rc/rc/'; \
24
12
  else \
25
- echo "$(TAG)"; \
13
+ echo "$(TAG)"; \
26
14
  fi)
27
15
 
28
16
  # Paths
@@ -34,19 +22,45 @@ REDPANDA_SRC := $(TMP_ROOT)/redpanda
34
22
  TREESITTER_DIR:= $(TOOL_ROOT)/tree-sitter/tree-sitter-cpp
35
23
  VENV := $(TOOL_ROOT)/tmp/redpanda-property-extractor-venv
36
24
  PYTHON := $(VENV)/bin/python
37
- OUTPUT_DIR := $(REPO_ROOT)/autogenerated/$(TAG)/properties
38
25
  TREE_SITTER := npx tree-sitter
39
26
 
27
+ # Output directory configuration (can be overridden by environment variables)
28
+ OUTPUT_AUTOGENERATED_DIR ?= $(REPO_ROOT)/modules/reference
29
+ OUTPUT_ASCIIDOC_DIR ?= $(OUTPUT_AUTOGENERATED_DIR)/pages
30
+ OUTPUT_JSON_DIR ?= $(OUTPUT_AUTOGENERATED_DIR)/examples
31
+
32
+ # --- Main build: venv, fetch code, build parser, extract & docgen ---
33
+ build: venv redpanda-git treesitter
34
+ @echo "πŸ”§ Building with Redpanda tag: $(TAG)"
35
+ @mkdir -p $(TOOL_ROOT)/gen
36
+ @if [ -n "$(OVERRIDES)" ] && [ ! -f "$(OVERRIDES)" ]; then \
37
+ echo "❌ Error: Overrides file '$(OVERRIDES)' does not exist."; \
38
+ echo " Please check the path or omit the OVERRIDES variable to continue without overrides."; \
39
+ exit 1; \
40
+ fi
41
+ @cd $(TOOL_ROOT) && \
42
+ $(PYTHON) -W ignore property_extractor.py \
43
+ --recursive \
44
+ --path $(REDPANDA_SRC) \
45
+ --output gen/properties-output.json \
46
+ --enhanced-output gen/$(TAG)-properties.json \
47
+ $(if $(OVERRIDES),$(if $(shell [ -f "$(OVERRIDES)" ] && echo exists),--overrides $(OVERRIDES),),) \
48
+ $(if $(CLOUD_SUPPORT),--cloud-support,)
49
+ @echo "βœ… JSON generated at $(TOOL_ROOT)/gen/properties-output.json"
50
+ @echo "βœ… Enhanced JSON (with overrides) generated at $(TOOL_ROOT)/gen/$(TAG)-properties.json"
51
+ @$(MAKE) generate-docs
52
+
40
53
  # --- Ensure Python venv & dependencies ---
41
54
  venv: $(TOOL_ROOT)/requirements.txt
42
55
  @if [ ! -d "$(VENV)" ]; then \
43
56
  echo "🐍 Creating virtual environment in $(VENV)..."; \
44
57
  python3 -m venv $(VENV); \
45
- $(VENV)/bin/pip install --upgrade pip --quiet; \
46
- $(VENV)/bin/pip install --no-cache-dir -r $<; \
47
58
  else \
48
59
  echo "🐍 Virtual environment already exists at $(VENV)"; \
49
- fi
60
+ fi; \
61
+ echo "πŸ”„ Upgrading pip and installing requirements..."; \
62
+ $(VENV)/bin/pip install --upgrade pip --quiet; \
63
+ $(VENV)/bin/pip install --no-cache-dir -r $<;
50
64
 
51
65
  # --- Clean out all generated state ---
52
66
  clean:
@@ -82,36 +96,40 @@ treesitter:
82
96
  git fetch --tags -q && \
83
97
  git checkout -q v0.20.5
84
98
  @echo "πŸ”§ Generating parser in $(TREESITTER_DIR)…"
85
- @cd "$(TREESITTER_DIR)" && npm install --silent && $(TREE_SITTER) generate
99
+ @cd "$(TREESITTER_DIR)" && export CFLAGS="-Wno-unused-but-set-variable" && npm install --silent && export CFLAGS="-Wno-unused-but-set-variable" && $(TREE_SITTER) generate
86
100
 
87
- # --- Turn the JSON into AsciiDoc pages under autogen/<version>/properties ---
88
- generate-docs:
89
- @echo "πŸ“ Generating AsciiDoc pages in $(OUTPUT_DIR)…"
90
- @mkdir -p "$(OUTPUT_DIR)"
91
- @cd $(TOOL_ROOT) && \
92
- $(PYTHON) json-to-asciidoc/generate_docs.py --output-dir "$(OUTPUT_DIR)"
93
- @echo "πŸ“„ Copying properties-output.json to $(OUTPUT_DIR)…"
94
- @cp "$(TOOL_ROOT)/gen/properties-output.json" "$(OUTPUT_DIR)/"
95
- @echo "βœ… Docs generated at $(OUTPUT_DIR)"
101
+ # --- Install Node.js dependencies for Handlebars ---
102
+ node-deps:
103
+ @echo "πŸ“¦ Installing Node.js dependencies…"
104
+ @cd $(TOOL_ROOT) && npm install --silent
105
+
106
+ # --- Turn the JSON into AsciiDoc pages under the specified output directories ---
107
+ generate-docs: node-deps
108
+ @echo "πŸ“ Generating AsciiDoc pages in $(OUTPUT_ASCIIDOC_DIR)…"
109
+ @mkdir -p "$(OUTPUT_ASCIIDOC_DIR)"
110
+ @mkdir -p "$(OUTPUT_JSON_DIR)"
111
+ @# Use the enhanced properties file (with overrides) for documentation generation if it exists
112
+ @if [ -f "$(TOOL_ROOT)/gen/$(TAG)-properties.json" ]; then \
113
+ cd $(TOOL_ROOT) && \
114
+ node generate-handlebars-docs.js "gen/$(TAG)-properties.json" "$(OUTPUT_AUTOGENERATED_DIR)"; \
115
+ else \
116
+ cd $(TOOL_ROOT) && \
117
+ node generate-handlebars-docs.js "gen/properties-output.json" "$(OUTPUT_AUTOGENERATED_DIR)"; \
118
+ fi
119
+ @echo "πŸ“„ Copying properties JSON files to $(OUTPUT_JSON_DIR)…"
120
+ @if [ -f "$(TOOL_ROOT)/gen/$(TAG)-properties.json" ]; then \
121
+ cp "$(TOOL_ROOT)/gen/$(TAG)-properties.json" "$(OUTPUT_JSON_DIR)/"; \
122
+ fi
123
+ @echo "βœ… Docs generated at $(OUTPUT_AUTOGENERATED_DIR)"
96
124
 
97
125
  # --- Debug helper to print all the key paths/vars ---
98
126
  check:
99
- @echo "MODULE_ROOT: $(MODULE_ROOT)"
100
- @echo "TOOL_ROOT: $(TOOL_ROOT)"
101
- @echo "REDPANDA_SRC: $(REDPANDA_SRC)"
102
- @echo "TREESITTER: $(TREESITTER_DIR)"
103
- @echo "VENV: $(VENV)"
104
- @echo "PYTHON: $(PYTHON)"
105
- @echo "OUTPUT_DIR: $(OUTPUT_DIR)"
106
-
107
- # --- Extract topic properties ---
108
- topic-properties: venv redpanda-git treesitter
109
- @echo "πŸ”§ Extracting topic properties with Redpanda tag: $(TAG)"
110
- @mkdir -p $(TOOL_ROOT)/gen
111
- @mkdir -p "$(OUTPUT_DIR)"
112
- @cd $(TOOL_ROOT) && \
113
- $(PYTHON) topic_property_extractor.py \
114
- --source-path $(REDPANDA_SRC) \
115
- --output-json "$(OUTPUT_DIR)/topic-properties-output.json" \
116
- --output-adoc "$(OUTPUT_DIR)/topic-properties.adoc"
117
- @echo "βœ… Topic properties extracted"
127
+ @echo "MODULE_ROOT: $(MODULE_ROOT)"
128
+ @echo "TOOL_ROOT: $(TOOL_ROOT)"
129
+ @echo "REDPANDA_SRC: $(REDPANDA_SRC)"
130
+ @echo "TREESITTER: $(TREESITTER_DIR)"
131
+ @echo "VENV: $(VENV)"
132
+ @echo "PYTHON: $(PYTHON)"
133
+ @echo "OUTPUT_ASCIIDOC_DIR: $(OUTPUT_ASCIIDOC_DIR)"
134
+ @echo "OUTPUT_JSON_DIR: $(OUTPUT_JSON_DIR)"
135
+ @echo "OUTPUT_AUTOGENERATED_DIR: $(OUTPUT_AUTOGENERATED_DIR)"