Skip to content

Commit 8b136fb

Browse files
authored
Use Antora config to determine current version (#145)
* Use Antora config to determine current version * Trigger update on api-docs repo * Apply suggestion
1 parent 72f96e4 commit 8b136fb

File tree

8 files changed

+147
-131
lines changed

8 files changed

+147
-131
lines changed

.github/workflows/publish-to-npm.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
needs: publish
3838
strategy:
3939
matrix:
40-
repo: ['redpanda-data/docs', 'redpanda-data/cloud-docs', 'redpanda-data/rp-connect-docs']
40+
repo: ['redpanda-data/docs', 'redpanda-data/cloud-docs', 'redpanda-data/rp-connect-docs', 'redpanda-data/api-docs']
4141
runs-on: ubuntu-latest
4242
steps:
4343
- uses: aws-actions/configure-aws-credentials@v4

bin/doc-tools.js

Lines changed: 84 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ const { execSync, spawnSync } = require('child_process');
44
const os = require('os');
55
const { Command, Option } = require('commander');
66
const path = require('path');
7-
const yaml = require('yaml');
87
const fs = require('fs');
9-
const handlebars = require('handlebars');
108
const { determineDocsBranch } = require('../cli-utils/self-managed-docs-branch.js');
119
const fetchFromGithub = require('../tools/fetch-from-github.js');
1210
const { urlToXref } = require('../cli-utils/convert-doc-links.js');
@@ -1031,12 +1029,12 @@ automation
10311029
});
10321030

10331031
automation
1034-
.command('property-docs')
1032+
.command('property-docs')
10351033
.description(
1036-
'Generate JSON and consolidated AsciiDoc partials for Redpanda configuration properties. ' +
1037-
'By default, only extracts properties to JSON. Use --generate-partials to create consolidated ' +
1038-
'AsciiDoc partials (including deprecated properties).'
1039-
)
1034+
'Generate JSON and consolidated AsciiDoc partials for Redpanda configuration properties. ' +
1035+
'By default, only extracts properties to JSON. Use --generate-partials to create consolidated ' +
1036+
'AsciiDoc partials (including deprecated properties).'
1037+
)
10401038
.option('--tag <tag>', 'Git tag or branch to extract from', 'dev')
10411039
.option('--diff <oldTag>', 'Also diff autogenerated properties from <oldTag> to <tag>')
10421040
.option('--overrides <path>', 'Optional JSON file with property description overrides')
@@ -1049,14 +1047,12 @@ automation
10491047
.option('--template-deprecated-property <path>', 'Custom Handlebars template for individual deprecated property sections')
10501048
.option('--generate-partials', 'Generate consolidated property partials (cluster-properties.adoc, topic-properties.adoc, etc.) in the partials directory')
10511049
.option('--partials-dir <path>', 'Directory for property partials (relative to output-dir)', 'partials')
1052-
.action((options) => {
1053-
verifyPropertyDependencies();
1050+
.action((options) => {
1051+
verifyPropertyDependencies();
10541052

10551053
// Validate cloud support dependencies if requested
10561054
if (options.cloudSupport) {
10571055
console.log('🔍 Validating cloud support dependencies...');
1058-
1059-
// Check for GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN
10601056
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN || process.env.REDPANDA_GITHUB_TOKEN;
10611057
if (!token) {
10621058
console.error('❌ Cloud support requires GITHUB_TOKEN, GH_TOKEN, or REDPANDA_GITHUB_TOKEN environment variable');
@@ -1068,7 +1064,6 @@ automation
10681064
console.error(' Or: export REDPANDA_GITHUB_TOKEN=your_token_here');
10691065
process.exit(1);
10701066
}
1071-
10721067
console.log('📦 Cloud support enabled - Python dependencies will be validated during execution');
10731068
if (process.env.VIRTUAL_ENV) {
10741069
console.log(` Using virtual environment: ${process.env.VIRTUAL_ENV}`);
@@ -1077,87 +1072,88 @@ automation
10771072
console.log('✅ GitHub token validated');
10781073
}
10791074

1080-
const newTag = options.tag;
1081-
const oldTag = options.diff;
1082-
const overridesPath = options.overrides;
1083-
const outputDir = options.outputDir;
1084-
const cwd = path.resolve(__dirname, '../tools/property-extractor');
1085-
1086-
const make = (tag, overrides, templates = {}, outDir = 'modules/reference/', tempDir = null) => {
1087-
console.log(`⏳ Building property docs for ${tag}${tempDir ? ' (for diff)' : ''}…`);
1088-
const args = ['build', `TAG=${tag}`];
1089-
1090-
// Pass all paths as environment variables for consistency
1091-
const env = { ...process.env };
1092-
1093-
if (overrides) {
1094-
env.OVERRIDES = path.resolve(overrides);
1095-
}
1096-
if (options.cloudSupport) {
1097-
env.CLOUD_SUPPORT = '1';
1098-
}
1099-
if (templates.property) {
1100-
env.TEMPLATE_PROPERTY = path.resolve(templates.property);
1101-
}
1102-
if (templates.topicProperty) {
1103-
env.TEMPLATE_TOPIC_PROPERTY = path.resolve(templates.topicProperty);
1104-
}
1105-
if (templates.topicPropertyMappings) {
1106-
env.TEMPLATE_TOPIC_PROPERTY_MAPPINGS = path.resolve(templates.topicPropertyMappings);
1107-
}
1108-
if (templates.deprecated) {
1109-
env.TEMPLATE_DEPRECATED = path.resolve(templates.deprecated);
1110-
}
1111-
if (templates.deprecatedProperty) {
1112-
env.TEMPLATE_DEPRECATED_PROPERTY = path.resolve(templates.deprecatedProperty);
1113-
}
1114-
1115-
if (tempDir) {
1116-
env.OUTPUT_JSON_DIR = path.resolve(tempDir, 'examples');
1117-
env.OUTPUT_AUTOGENERATED_DIR = path.resolve(tempDir);
1118-
} else {
1119-
env.OUTPUT_JSON_DIR = path.resolve(outDir, 'examples');
1120-
env.OUTPUT_AUTOGENERATED_DIR = path.resolve(outDir);
1121-
}
1122-
1123-
// Partials generation options
1124-
if (options.generatePartials) {
1125-
env.GENERATE_PARTIALS = '1';
1126-
env.OUTPUT_PARTIALS_DIR = path.resolve(outDir, options.partialsDir || 'partials');
1127-
}
1128-
1129-
const r = spawnSync('make', args, { cwd, stdio: 'inherit', env });
1130-
if (r.error) {
1131-
console.error(`❌ ${r.error.message}`);
1132-
process.exit(1);
1133-
}
1134-
if (r.status !== 0) process.exit(r.status);
1135-
};
1136-
1137-
// Collect template options
1138-
const templates = {
1139-
property: options.templateProperty,
1140-
topicProperty: options.templateTopicProperty,
1141-
topicPropertyMappings: options.templateTopicPropertyMappings,
1142-
deprecated: options.templateDeprecated,
1143-
deprecatedProperty: options.templateDeprecatedProperty,
1144-
};
1145-
1075+
const newTag = options.tag;
1076+
let oldTag = options.diff;
1077+
const overridesPath = options.overrides;
1078+
const outputDir = options.outputDir;
1079+
const cwd = path.resolve(__dirname, '../tools/property-extractor');
1080+
1081+
// If --diff is not provided, try to get the latest-redpanda-tag from Antora attributes
1082+
if (!oldTag) {
1083+
oldTag = getAntoraValue('asciidoc.attributes.latest-redpanda-tag');
11461084
if (oldTag) {
1147-
// Build old version first so its JSON exists for the diff step
1148-
make(oldTag, overridesPath, templates, outputDir, null);
1085+
console.log(`Using latest-redpanda-tag from Antora attributes for --diff: ${oldTag}`);
1086+
} else {
1087+
console.log('No --diff provided and no latest-redpanda-tag found in Antora attributes. Skipping diff.');
11491088
}
1089+
}
11501090

1151-
// Build new version
1152-
make(newTag, overridesPath, templates, outputDir, null);
1153-
1154-
if (oldTag) {
1155-
// Generate property comparison report using the JSON now in outputDir/examples
1156-
generatePropertyComparisonReport(oldTag, newTag, outputDir);
1091+
const make = (tag, overrides, templates = {}, outDir = 'modules/reference/') => {
1092+
console.log(`⏳ Building property docs for ${tag}…`);
1093+
const args = ['build', `TAG=${tag}`];
1094+
const env = { ...process.env };
1095+
if (overrides) {
1096+
env.OVERRIDES = path.resolve(overrides);
1097+
}
1098+
if (options.cloudSupport) {
1099+
env.CLOUD_SUPPORT = '1';
1100+
}
1101+
if (templates.property) {
1102+
env.TEMPLATE_PROPERTY = path.resolve(templates.property);
1103+
}
1104+
if (templates.topicProperty) {
1105+
env.TEMPLATE_TOPIC_PROPERTY = path.resolve(templates.topicProperty);
1106+
}
1107+
if (templates.topicPropertyMappings) {
1108+
env.TEMPLATE_TOPIC_PROPERTY_MAPPINGS = path.resolve(templates.topicPropertyMappings);
1109+
}
1110+
if (templates.deprecated) {
1111+
env.TEMPLATE_DEPRECATED = path.resolve(templates.deprecated);
1112+
}
1113+
if (templates.deprecatedProperty) {
1114+
env.TEMPLATE_DEPRECATED_PROPERTY = path.resolve(templates.deprecatedProperty);
11571115
}
1116+
env.OUTPUT_JSON_DIR = path.resolve(outDir, 'examples');
1117+
env.OUTPUT_AUTOGENERATED_DIR = path.resolve(outDir);
1118+
if (options.generatePartials) {
1119+
env.GENERATE_PARTIALS = '1';
1120+
env.OUTPUT_PARTIALS_DIR = path.resolve(outDir, options.partialsDir || 'partials');
1121+
}
1122+
const r = spawnSync('make', args, { cwd, stdio: 'inherit', env });
1123+
if (r.error) {
1124+
console.error(`❌ ${r.error.message}`);
1125+
process.exit(1);
1126+
}
1127+
if (r.status !== 0) process.exit(r.status);
1128+
};
1129+
1130+
const templates = {
1131+
property: options.templateProperty,
1132+
topicProperty: options.templateTopicProperty,
1133+
topicPropertyMappings: options.templateTopicPropertyMappings,
1134+
deprecated: options.templateDeprecated,
1135+
deprecatedProperty: options.templateDeprecatedProperty,
1136+
};
1137+
1138+
const tagsAreSame = oldTag && newTag && oldTag === newTag;
1139+
if (oldTag && !tagsAreSame) {
1140+
make(oldTag, overridesPath, templates, outputDir);
1141+
}
1142+
make(newTag, overridesPath, templates, outputDir);
1143+
if (oldTag && !tagsAreSame) {
1144+
generatePropertyComparisonReport(oldTag, newTag, outputDir);
1145+
} else if (tagsAreSame) {
1146+
console.log('--diff and --tag are the same. Skipping diff and Antora config update.');
1147+
}
11581148

1159-
process.exit(0);
1160-
});
1149+
// If we used Antora's latest-redpanda-tag for diff, update it to the new tag
1150+
if (!options.diff && !tagsAreSame) {
1151+
setAntoraValue('asciidoc.attributes.latest-redpanda-tag', newTag);
1152+
console.log(`✅ Updated Antora latest-redpanda-tag to: ${newTag}`);
1153+
}
1154+
1155+
process.exit(0);
1156+
});
11611157

11621158
automation
11631159
.command('rpk-docs')

cli-utils/antora-utils.js

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,30 @@ const yaml = require('js-yaml');
1010
* @returns {Object|undefined} The parsed YAML as a JavaScript object, or undefined if not found or on error.
1111
*/
1212
function loadAntoraConfig() {
13-
const antoraPath = path.join(process.cwd(), 'antora.yml');
14-
if (!fs.existsSync(antoraPath)) {
15-
// No antora.yml in project root
13+
// Support both antora.yml and antora.yaml
14+
const cwd = process.cwd();
15+
const ymlPath = path.join(cwd, 'antora.yml');
16+
const yamlPath = path.join(cwd, 'antora.yaml');
17+
let antoraPath;
18+
if (fs.existsSync(ymlPath)) {
19+
antoraPath = ymlPath;
20+
} else if (fs.existsSync(yamlPath)) {
21+
antoraPath = yamlPath;
22+
} else {
23+
// No antora.yml or antora.yaml in project root
1624
return undefined;
1725
}
1826

1927
try {
2028
const fileContents = fs.readFileSync(antoraPath, 'utf8');
2129
const config = yaml.load(fileContents);
2230
if (typeof config !== 'object' || config === null) {
23-
console.error('Warning: antora.yml parsed to a non‐object value.');
31+
console.error(`Warning: ${path.basename(antoraPath)} parsed to a non‐object value.`);
2432
return undefined;
2533
}
2634
return config;
2735
} catch (err) {
28-
console.error(`Error reading/parsing antora.yml: ${err.message}`);
36+
console.error(`Error reading/parsing ${path.basename(antoraPath)}: ${err.message}`);
2937
return undefined;
3038
}
3139
}
@@ -74,9 +82,17 @@ function getAntoraValue(keyPath) {
7482
* True if it succeeded, false otherwise.
7583
*/
7684
function setAntoraValue(keyPath, newValue) {
77-
const antoraPath = path.join(process.cwd(), 'antora.yml');
78-
if (!fs.existsSync(antoraPath)) {
79-
console.error('Cannot update antora.yml: file not found in project root.');
85+
// Support both antora.yml and antora.yaml
86+
const cwd = process.cwd();
87+
const ymlPath = path.join(cwd, 'antora.yml');
88+
const yamlPath = path.join(cwd, 'antora.yaml');
89+
let antoraPath;
90+
if (fs.existsSync(ymlPath)) {
91+
antoraPath = ymlPath;
92+
} else if (fs.existsSync(yamlPath)) {
93+
antoraPath = yamlPath;
94+
} else {
95+
console.error('Cannot update antora.yml or antora.yaml: file not found in project root.');
8096
return false;
8197
}
8298

@@ -88,7 +104,7 @@ function setAntoraValue(keyPath, newValue) {
88104
config = {};
89105
}
90106
} catch (err) {
91-
console.error(`Error reading/parsing antora.yml: ${err.message}`);
107+
console.error(`Error reading/parsing ${path.basename(antoraPath)}: ${err.message}`);
92108
return false;
93109
}
94110

@@ -115,7 +131,37 @@ function setAntoraValue(keyPath, newValue) {
115131
fs.writeFileSync(antoraPath, newYaml, 'utf8');
116132
return true;
117133
} catch (err) {
118-
console.error(`Error writing antora.yml: ${err.message}`);
134+
console.error(`Error writing ${path.basename(antoraPath)}: ${err.message}`);
135+
return false;
136+
}
137+
}
138+
139+
/**
140+
* Look for antora.yml in the current working directory
141+
* (the project's root), load it if present, and return
142+
* its `prerelease` value (boolean). If missing or on error,
143+
* returns false.
144+
*/
145+
function getPrereleaseFromAntora() {
146+
// Support both antora.yml and antora.yaml
147+
const cwd = process.cwd();
148+
const ymlPath = path.join(cwd, 'antora.yml');
149+
const yamlPath = path.join(cwd, 'antora.yaml');
150+
let antoraPath;
151+
if (fs.existsSync(ymlPath)) {
152+
antoraPath = ymlPath;
153+
} else if (fs.existsSync(yamlPath)) {
154+
antoraPath = yamlPath;
155+
} else {
156+
return false;
157+
}
158+
159+
try {
160+
const fileContents = fs.readFileSync(antoraPath, 'utf8');
161+
const antoraConfig = yaml.load(fileContents);
162+
return antoraConfig.prerelease === true;
163+
} catch (error) {
164+
console.error(`Error reading ${path.basename(antoraPath)}:`, error.message);
119165
return false;
120166
}
121167
}
@@ -124,4 +170,5 @@ module.exports = {
124170
loadAntoraConfig,
125171
getAntoraValue,
126172
setAntoraValue,
173+
getPrereleaseFromAntora
127174
};

cli-utils/beta-from-antora.js

Lines changed: 0 additions & 27 deletions
This file was deleted.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@redpanda-data/docs-extensions-and-macros",
3-
"version": "4.10.6",
3+
"version": "4.10.7",
44
"description": "Antora extensions and macros developed for Redpanda documentation.",
55
"keywords": [
66
"antora",

tools/get-console-version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const yaml = require('js-yaml');
44
const fs = require('fs');
55
const path = require('path');
66
const GetLatestConsoleVersion = require('../extensions/version-fetcher/get-latest-console-version.js');
7-
const { getPrereleaseFromAntora } = require('../cli-utils/beta-from-antora.js');
7+
const { getPrereleaseFromAntora } = require('../cli-utils/antora-utils.js');
88

99
/**
1010
* Fetches and prints the latest Console version and Docker repo.

0 commit comments

Comments
 (0)