@redpanda-data/docs-extensions-and-macros 4.11.1 → 4.12.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 (29) hide show
  1. package/bin/doc-tools.js +4 -2
  2. package/package.json +3 -1
  3. package/tools/property-extractor/COMPUTED_CONSTANTS.md +173 -0
  4. package/tools/property-extractor/Makefile +12 -1
  5. package/tools/property-extractor/README.adoc +828 -97
  6. package/tools/property-extractor/compare-properties.js +38 -13
  7. package/tools/property-extractor/constant_resolver.py +610 -0
  8. package/tools/property-extractor/file_pair.py +42 -0
  9. package/tools/property-extractor/generate-handlebars-docs.js +41 -8
  10. package/tools/property-extractor/helpers/gt.js +9 -0
  11. package/tools/property-extractor/helpers/includes.js +17 -0
  12. package/tools/property-extractor/helpers/index.js +3 -0
  13. package/tools/property-extractor/helpers/isEnterpriseEnum.js +24 -0
  14. package/tools/property-extractor/helpers/renderPropertyExample.js +6 -5
  15. package/tools/property-extractor/overrides.json +248 -0
  16. package/tools/property-extractor/parser.py +254 -32
  17. package/tools/property-extractor/property_bag.py +40 -0
  18. package/tools/property-extractor/property_extractor.py +1417 -430
  19. package/tools/property-extractor/requirements.txt +1 -0
  20. package/tools/property-extractor/templates/property-backup.hbs +161 -0
  21. package/tools/property-extractor/templates/property.hbs +104 -49
  22. package/tools/property-extractor/templates/topic-property-backup.hbs +148 -0
  23. package/tools/property-extractor/templates/topic-property.hbs +72 -34
  24. package/tools/property-extractor/tests/test_known_values.py +617 -0
  25. package/tools/property-extractor/tests/transformers_test.py +81 -6
  26. package/tools/property-extractor/topic_property_extractor.py +23 -10
  27. package/tools/property-extractor/transformers.py +2191 -369
  28. package/tools/property-extractor/type_definition_extractor.py +669 -0
  29. package/tools/property-extractor/definitions.json +0 -245
package/bin/doc-tools.js CHANGED
@@ -1148,8 +1148,10 @@ automation
1148
1148
 
1149
1149
  // If we used Antora's latest-redpanda-tag for diff, update it to the new tag
1150
1150
  if (!options.diff && !tagsAreSame) {
1151
- setAntoraValue('asciidoc.attributes.latest-redpanda-tag', newTag);
1152
- console.log(`✅ Updated Antora latest-redpanda-tag to: ${newTag}`);
1151
+ const success = setAntoraValue('asciidoc.attributes.latest-redpanda-tag', newTag);
1152
+ if (success) {
1153
+ console.log(`✅ Updated Antora latest-redpanda-tag to: ${newTag}`);
1154
+ }
1153
1155
  }
1154
1156
 
1155
1157
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redpanda-data/docs-extensions-and-macros",
3
- "version": "4.11.1",
3
+ "version": "4.12.0",
4
4
  "description": "Antora extensions and macros developed for Redpanda documentation.",
5
5
  "keywords": [
6
6
  "antora",
@@ -22,6 +22,8 @@
22
22
  "build": "antora --to-dir docs --fetch local-antora-playbook.yml",
23
23
  "serve": "wds --node-resolve --open preview/test/ --watch --root-dir docs",
24
24
  "test": "jest",
25
+ "test:python": "./__tests__/tools/property-extractor/setup-and-test.sh",
26
+ "test:all": "npm run test && npm run test:python",
25
27
  "bundle:admin": "doc-tools generate bundle-openapi --surface admin",
26
28
  "bundle:connect": "doc-tools generate bundle-openapi --surface connect",
27
29
  "bundle:both": "doc-tools generate bundle-openapi --surface both"
@@ -0,0 +1,173 @@
1
+ # Computed C++ Constants Resolution
2
+
3
+ ## Overview
4
+
5
+ Some C++ constants in Redpanda are defined with complex compile-time expressions that cannot be easily parsed by the property-extractor. These constants need to be pre-computed and mapped to their actual values.
6
+
7
+ ## Problem Statement
8
+
9
+ Properties like `log_message_timestamp_before_max_ms` use constants like `max_serializable_ms` as their default values. These constants are defined with complex expressions:
10
+
11
+ ```cpp
12
+ // From src/v/serde/rw/chrono.h:20
13
+ inline constexpr auto max_serializable_ms
14
+ = std::chrono::duration_cast<std::chrono::milliseconds>(
15
+ std::chrono::nanoseconds::max());
16
+ ```
17
+
18
+ Without resolution, the extracted schema would show:
19
+ ```json
20
+ {
21
+ "log_message_timestamp_before_max_ms": {
22
+ "default": "max_serializable_ms" // ❌ String instead of numeric value
23
+ }
24
+ }
25
+ ```
26
+
27
+ ## Solution
28
+
29
+ ### 1. COMPUTED_CONSTANTS Dictionary
30
+
31
+ Added a dictionary in `transformers.py` that maps constant names to their computed values:
32
+
33
+ ```python
34
+ COMPUTED_CONSTANTS = {
35
+ # From src/v/serde/rw/chrono.h:20
36
+ # inline constexpr auto max_serializable_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds::max());
37
+ # Calculation: std::numeric_limits<int64_t>::max() / 1,000,000 = 9223372036854775807 / 1000000 = 9223372036854 ms
38
+ "max_serializable_ms": 9223372036854, # ~292 years in milliseconds
39
+ }
40
+ ```
41
+
42
+ ### 2. FriendlyDefaultTransformer Enhancement
43
+
44
+ Updated the `FriendlyDefaultTransformer` to check the `COMPUTED_CONSTANTS` dictionary before falling back to string normalization:
45
+
46
+ ```python
47
+ # ------------------------------------------------------------------
48
+ # Computed C++ constants (max_serializable_ms, etc.)
49
+ # ------------------------------------------------------------------
50
+ if d in COMPUTED_CONSTANTS:
51
+ property["default"] = COMPUTED_CONSTANTS[d]
52
+ return property
53
+ ```
54
+
55
+ ### 3. Test Coverage
56
+
57
+ Added comprehensive test in `tests/test_known_values.py`:
58
+
59
+ ```python
60
+ def test_max_serializable_ms_constant_resolution(self):
61
+ """Test that max_serializable_ms constant is resolved to actual numeric value"""
62
+ info = create_complete_property_info(
63
+ name="log_message_timestamp_before_max_ms",
64
+ description="Maximum timestamp difference for record validation",
65
+ declaration="property<std::chrono::milliseconds> log_message_timestamp_before_max_ms;",
66
+ metadata="meta{.needs_restart = needs_restart::no, .visibility = visibility::user}",
67
+ default_value="max_serializable_ms"
68
+ )
69
+
70
+ property = apply_transformer_pipeline(info)
71
+
72
+ self.assertEqual(property["name"], "log_message_timestamp_before_max_ms")
73
+ self.assertEqual(property["type"], "integer")
74
+ # max_serializable_ms = std::numeric_limits<int64_t>::max() / 1,000,000 = 9223372036854 ms
75
+ self.assertEqual(property["default"], 9223372036854)
76
+ self.assertFalse(property["needs_restart"])
77
+ self.assertEqual(property["visibility"], "user")
78
+ ```
79
+
80
+ ## Calculation Details
81
+
82
+ ### max_serializable_ms
83
+
84
+ **Definition Location:** `src/v/serde/rw/chrono.h:20`
85
+
86
+ **C++ Expression:**
87
+ ```cpp
88
+ std::chrono::duration_cast<std::chrono::milliseconds>(
89
+ std::chrono::nanoseconds::max()
90
+ )
91
+ ```
92
+
93
+ **Calculation:**
94
+ 1. `std::chrono::nanoseconds::max()` = `std::numeric_limits<int64_t>::max()` = `9223372036854775807` nanoseconds
95
+ 2. Convert to milliseconds (truncating division): `9223372036854775807 / 1000000` = `9223372036854` milliseconds
96
+ 3. This is approximately **292.47 years**
97
+
98
+ **Verification:**
99
+ ```python
100
+ import sys
101
+
102
+ # std::chrono::nanoseconds uses int64_t for rep
103
+ max_int64 = 9223372036854775807
104
+
105
+ # Convert nanoseconds to milliseconds (duration_cast truncates)
106
+ max_ms = max_int64 // 1000000
107
+
108
+ print(f'max_serializable_ms = {max_ms} ms')
109
+ print(f'Which is approximately {max_ms / (1000 * 60 * 60 * 24 * 365):.2f} years')
110
+ ```
111
+
112
+ Output:
113
+ ```
114
+ max_serializable_ms = 9223372036854 ms
115
+ Which is approximately 292.47 years
116
+ ```
117
+
118
+ ## Result
119
+
120
+ After the fix, the extracted schema correctly shows:
121
+ ```json
122
+ {
123
+ "log_message_timestamp_before_max_ms": {
124
+ "default": 9223372036854, // ✅ Correct numeric value
125
+ "type": "integer"
126
+ }
127
+ }
128
+ ```
129
+
130
+ ## Adding New Computed Constants
131
+
132
+ To add support for new computed constants:
133
+
134
+ 1. **Find the definition** in the Redpanda source code
135
+ 2. **Compute the value** - either manually or with a Python/C++ test
136
+ 3. **Add to COMPUTED_CONSTANTS** dictionary in `transformers.py`:
137
+ ```python
138
+ COMPUTED_CONSTANTS = {
139
+ "existing_constant": 12345,
140
+ "new_constant_name": computed_value, # Add comment with source location
141
+ }
142
+ ```
143
+ 4. **Add a test** in `tests/test_known_values.py` to verify resolution
144
+ 5. **Document the calculation** with comments including:
145
+ - Source file location
146
+ - C++ expression
147
+ - Calculation steps
148
+ - Human-readable interpretation
149
+
150
+ ## Test Coverage
151
+
152
+ All 53 tests pass, including the new test for `max_serializable_ms` resolution:
153
+
154
+ ```bash
155
+ cd tools/property-extractor
156
+ python -m pytest tests/ -v --tb=short
157
+ # ================================================= 53 passed =================================================
158
+ ```
159
+
160
+ ## Benefits
161
+
162
+ ✅ **Accurate defaults** - Properties show actual numeric values instead of symbolic names
163
+ ✅ **Type safety** - Numeric properties have numeric defaults, not strings
164
+ ✅ **Documentation quality** - Users see real values they can use
165
+ ✅ **Maintainability** - Centralized mapping makes updates easy
166
+ ✅ **Test coverage** - Ensures constants resolve correctly
167
+
168
+ ## Related Files
169
+
170
+ - `tools/property-extractor/transformers.py` - COMPUTED_CONSTANTS dictionary and resolution logic
171
+ - `tools/property-extractor/tests/test_known_values.py` - Test for constant resolution
172
+ - `src/v/serde/rw/chrono.h` - Source definition of max_serializable_ms
173
+ - `tools/property-extractor/CI_INTEGRATION.md` - Updated test count documentation
@@ -119,7 +119,18 @@ generate-docs: node-deps
119
119
  fi
120
120
  @echo "📄 Copying properties JSON files to $(OUTPUT_JSON_DIR)…"
121
121
  @if [ -f "$(TOOL_ROOT)/gen/$(TAG)-properties.json" ]; then \
122
- cp "$(TOOL_ROOT)/gen/$(TAG)-properties.json" "$(OUTPUT_JSON_DIR)/"; \
122
+ echo " Source: $(TOOL_ROOT)/gen/$(TAG)-properties.json"; \
123
+ echo " Target: $(OUTPUT_JSON_DIR)/$(TAG)-properties.json"; \
124
+ cp "$(TOOL_ROOT)/gen/$(TAG)-properties.json" "$(OUTPUT_JSON_DIR)/" && \
125
+ echo " ✅ Successfully copied $(TAG)-properties.json" || \
126
+ { echo " ❌ Failed to copy $(TAG)-properties.json"; exit 1; }; \
127
+ if [ -f "$(OUTPUT_JSON_DIR)/$(TAG)-properties.json" ]; then \
128
+ echo " 📊 Verification: Target file exists and has $$(wc -c < "$(OUTPUT_JSON_DIR)/$(TAG)-properties.json") bytes"; \
129
+ else \
130
+ echo " ❌ Verification failed: Target file does not exist"; exit 1; \
131
+ fi; \
132
+ else \
133
+ echo " ⚠️ Source file $(TOOL_ROOT)/gen/$(TAG)-properties.json not found, skipping copy"; \
123
134
  fi
124
135
  @echo "✅ Docs generated at $(OUTPUT_AUTOGENERATED_DIR)"
125
136