-
Notifications
You must be signed in to change notification settings - Fork 3
DOC-1275 Add a doc-tools CLI command so that writers and our tests have access to a consistent set of tools #99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 27 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
35d809b
Add a doc-tools CLI command so that writers and our tests have access…
JakeSCahill f09ea25
Bump version
JakeSCahill 3da4141
Merge branch 'main' into doc-tools
JakeSCahill ed2e113
Add submodule
JakeSCahill ddfe72c
Add tree-sitter-cpp submodule
JakeSCahill 8ff09b1
Add tree-sitter-c grammar as dependency of C++ parser
JakeSCahill 5159233
Add tree-sitter-c grammar as required by tree-sitter-cpp
JakeSCahill 2c8801e
Add property automation to CLI
JakeSCahill 4b7799b
Add CLI help
JakeSCahill 07872cd
doc-tools CLI
JakeSCahill 8777736
Remove tree‑sitter‑cpp submodule; clone on demand instead
JakeSCahill c811ae8
Fix paths
JakeSCahill f858ba7
Fix makefile
JakeSCahill 5e4e26f
Merge branch 'main' into doc-tools
JakeSCahill 93f4877
Update package.json
JakeSCahill 1d741a9
Update package-lock.json
JakeSCahill b655325
Fix packages
JakeSCahill 4588b07
Cleanup
JakeSCahill c839f7b
Apply suggestions from code review
JakeSCahill 84df438
Refactor
JakeSCahill 9102dff
Merge branch 'doc-tools' of https://github.com/redpanda-data/docs-ext…
JakeSCahill ef814d4
Add Iceberg support in test cluster
JakeSCahill bc2c48d
Fix error
JakeSCahill 7b92f26
Apply suggestions from code review
JakeSCahill 68ee36f
Final fixes
JakeSCahill db15af2
Apply suggestions
JakeSCahill 4936687
Add support for the new gets_restored metadata introduced in https://…
JakeSCahill 8dfd458
Add fetch command for saving files from other repos locally
JakeSCahill 11f1b65
Apply suggestions from code review
JakeSCahill ecde8ba
Add support for a --diff flag
JakeSCahill File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,10 @@ | ||
| /node_modules/* | ||
| /wip/* | ||
| /docs/* | ||
| .vscode | ||
| .vscode | ||
| autogenerated/ | ||
| tmp/ | ||
| venv/ | ||
| __pycache__/ | ||
| gen/ | ||
| tree-sitter/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| local-antora-playbook.yml | ||
| /modules/* | ||
| /node_modules/* | ||
| antora.yml | ||
| antora.yml | ||
| tools/property-extractor/tmp/ | ||
| tools/property-extractor/tmp/** | ||
| gen/** | ||
| __pycache__ | ||
| tests/* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,240 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| const { execSync, spawnSync } = require('child_process'); | ||
| const { Command } = require('commander'); | ||
| const path = require('path'); | ||
|
|
||
| // -------------------------------------------------------------------- | ||
| // Dependency check functions | ||
| // -------------------------------------------------------------------- | ||
| function checkDependency(command, versionArg, name, helpURL) { | ||
| try { | ||
| execSync(`${command} ${versionArg}`, { stdio: 'ignore' }); | ||
| } catch (error) { | ||
| console.error(`Error: ${name} is required but not found or not working properly. | ||
| Please install ${name} and try again. | ||
| For more info, see: ${helpURL}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function checkCommandExists(command) { | ||
| try { | ||
| execSync(`which ${command}`, { stdio: 'ignore' }); | ||
| return true; | ||
| } catch (error) { | ||
| console.error(`Error: \`${command}\` is required but not found. Please install \`${command}\` and try again.`); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| function checkMake() { | ||
| if (!checkCommandExists('make')) { | ||
| console.error('Error: `make` is required but not found. Please install `make` to use the automation Makefile. For help, see: https://www.google.com/search?q=how+to+install+make'); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function checkPython() { | ||
| const candidates = ['python3', 'python']; | ||
| let found = false; | ||
|
|
||
| for (const cmd of candidates) { | ||
| try { | ||
| const versionOutput = execSync(`${cmd} --version`, { | ||
| encoding: 'utf8', | ||
| stdio: ['pipe', 'pipe', 'ignore'] | ||
| }).trim(); | ||
| // versionOutput looks like "Python 3.x.y" | ||
| const versionString = versionOutput.split(' ')[1]; | ||
| const [major, minor] = versionString.split('.').map(Number); | ||
| if (major > 3 || (major === 3 && minor >= 10)) { | ||
| found = true; | ||
| break; | ||
| } else { | ||
| console.error(`Error: Python 3.10 or higher is required. Detected version: ${versionString}`); | ||
| process.exit(1); | ||
| } | ||
| } catch { | ||
| // this candidate didn’t exist or errored—try the next one | ||
| } | ||
| } | ||
| if (!found) { | ||
| console.error('Error: Python 3.10 or higher is required but not found.\nPlease install Python and ensure `python3 --version` or `python --version` returns at least 3.10.'); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function checkCompiler() { | ||
| const gccInstalled = checkCommandExists('gcc'); | ||
| const clangInstalled = checkCommandExists('clang'); | ||
| if (!gccInstalled && !clangInstalled) { | ||
| console.error('Error: A C++ compiler (such as gcc or clang) is required but not found. Please install one.'); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function checkDocker() { | ||
| checkDependency('docker', '--version', 'Docker', 'https://docs.docker.com/get-docker/'); | ||
| try { | ||
| execSync('docker info', { stdio: 'ignore' }); | ||
| } catch (error) { | ||
| console.error('Error: Docker daemon appears to be not running. Please start Docker.'); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function verifyPropertyDependencies() { | ||
| checkMake(); | ||
| checkPython(); | ||
| checkCompiler(); | ||
| } | ||
|
|
||
| function verifyMetricsDependencies() { | ||
| checkPython(); | ||
| if (!checkCommandExists('curl') || !checkCommandExists('tar')) { | ||
| // `checkCommandExists` already prints a helpful message. | ||
| process.exit(1); | ||
| } | ||
| checkDocker(); | ||
| } | ||
| // -------------------------------------------------------------------- | ||
| // Main CLI Definition | ||
| // -------------------------------------------------------------------- | ||
| const programCli = new Command(); | ||
|
|
||
| programCli | ||
| .name('doc-tools') | ||
| .description('Redpanda Document Automation CLI') | ||
| .version('1.0.0'); | ||
|
|
||
| // Top-level commands. | ||
| programCli | ||
| .command('install-test-dependencies') | ||
| .description('Install packages for doc test workflows') | ||
| .action(() => { | ||
| const scriptPath = path.join(__dirname, '../cli-utils/install-test-dependencies.sh'); | ||
| const result = spawnSync(scriptPath, { stdio: 'inherit', shell: true }); | ||
| process.exit(result.status); | ||
| }); | ||
|
|
||
| programCli | ||
| .command('get-redpanda-version') | ||
| .description('Print the latest Redpanda version') | ||
| .option('--beta', 'Return the latest RC (beta) version if available') | ||
| .option('--from-antora', 'Read prerelease flag from local antora.yml') | ||
| .action(async (options) => { | ||
| try { | ||
| await require('../tools/get-redpanda-version.js')(options); | ||
| } catch (err) { | ||
| console.error(err); | ||
| process.exit(1); | ||
| } | ||
| }); | ||
|
|
||
| programCli | ||
| .command('get-console-version') | ||
| .description('Print the latest Console version') | ||
| .option('--beta', 'Return the latest beta version if available') | ||
| .option('--from-antora', 'Read prerelease flag from local antora.yml') | ||
| .action(async (options) => { | ||
| try { | ||
| await require('../tools/get-console-version.js')(options); | ||
| } catch (err) { | ||
| console.error(err); | ||
| process.exit(1); | ||
| } | ||
| }); | ||
|
|
||
| // Create an "automation" subcommand group. | ||
| const automation = new Command('generate') | ||
| .description('Run docs automations (properties, metrics, and rpk docs generation)'); | ||
|
|
||
| // -------------------------------------------------------------------- | ||
| // Automation Subcommands: Delegate to a unified Bash script internally. | ||
| // -------------------------------------------------------------------- | ||
|
|
||
| // Common options for both automation tasks. | ||
| const commonOptions = { | ||
| tag: 'latest', | ||
| dockerRepo: 'redpanda', | ||
| consoleTag: 'latest', | ||
| consoleDockerRepo: 'console' | ||
| }; | ||
|
|
||
| // Subcommand: generate-metrics-docs. | ||
| automation | ||
| .command('metrics-docs') | ||
| .description('Extract Redpanda metrics and generate JSON/AsciiDoc docs') | ||
| .option('--tag <tag>', 'Redpanda tag (default: latest)', commonOptions.tag) | ||
| .option('--docker-repo <repo>', 'Redpanda Docker repository (default: redpanda or redpanda-unstable when --tag is an RC version)', commonOptions.dockerRepo) | ||
| .option('--console-tag <tag>', 'Redpanda Console tag (default: latest)', commonOptions.consoleTag) | ||
| .option('--console-docker-repo <repo>', 'Redpanda Console Docker repository (default: console)', commonOptions.consoleDockerRepo) | ||
| .action((options) => { | ||
| // Verify dependencies common to these automations. | ||
| verifyMetricsDependencies(); | ||
| // Build argument array for the Bash automation script. | ||
| const args = [ | ||
| 'metrics', | ||
| options.tag, | ||
| options.dockerRepo, | ||
| options.consoleTag, | ||
| options.consoleDockerRepo | ||
| ]; | ||
| const scriptPath = path.join(__dirname, '../cli-utils/generate-cluster-docs.sh'); | ||
| console.log(`Running ${scriptPath} with arguments: ${args.join(' ')}`); | ||
| const result = spawnSync('bash', [scriptPath, ...args], { stdio: 'inherit', shell: true }); | ||
| process.exit(result.status); | ||
| }); | ||
|
|
||
| // Subcommand: generate-property-docs. | ||
| automation | ||
| .command('property-docs') | ||
| .description('Extract properties from Redpanda source') | ||
| .option('--tag <tag>', 'Git tag or branch of Redpanda to extract from (default: dev)', 'dev') | ||
| .action((options) => { | ||
| verifyPropertyDependencies(); | ||
| const cwd = path.resolve(__dirname, '../tools/property-extractor'); | ||
| const tag = options.tag || 'dev'; | ||
| const result = spawnSync('make', ['build', `TAG=${tag}`], { | ||
| cwd, | ||
| stdio: 'inherit' | ||
| }); | ||
| if (result.error) { | ||
| console.error('Failed to run `make build`:', result.error.message); | ||
| process.exit(1); | ||
| } else if (result.status !== 0) { | ||
| console.error(`make build exited with status code ${result.status}`); | ||
| process.exit(result.status); | ||
| } | ||
| process.exit(result.status); | ||
| }); | ||
|
|
||
| // Subcommand: generate-rpk-docs. | ||
| automation | ||
| .command('rpk-docs') | ||
| .description('Generate documentation for rpk commands') | ||
| .option('--tag <tag>', 'Redpanda tag (default: latest)', commonOptions.tag) | ||
| .option('--docker-repo <repo>', 'Redpanda Docker repository (default: redpanda or redpanda-unstable when --tag is an RC version)', commonOptions.dockerRepo) | ||
| .option('--console-tag <tag>', 'Redpanda Console tag (default: latest)', commonOptions.consoleTag) | ||
| .option('--console-docker-repo <repo>', 'Redpanda Console Docker repository (default: console)', commonOptions.consoleDockerRepo) | ||
| .action((options) => { | ||
| verifyMetricsDependencies(); | ||
| const args = [ | ||
| 'rpk', | ||
| options.tag, | ||
| options.dockerRepo, | ||
| options.consoleTag, | ||
| options.consoleDockerRepo | ||
| ]; | ||
| const scriptPath = path.join(__dirname, '../cli-utils/generate-cluster-docs.sh'); | ||
| console.log(`Running ${scriptPath} with arguments: ${args.join(' ')}`); | ||
| const result = spawnSync('bash', [scriptPath, ...args], { stdio: 'inherit', shell: true }); | ||
| process.exit(result.status); | ||
| }); | ||
|
|
||
| // Attach the automation group to the main program. | ||
| programCli.addCommand(automation); | ||
|
|
||
| programCli.parse(process.argv); | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import os | ||
| import re | ||
|
|
||
| # Define the regular expression pattern to match the links | ||
| pattern = r'(https://[^\]]+)\[([^\]]+)\](?!\^)' | ||
|
|
||
| # Function to process a single file | ||
| def process_file(file_path): | ||
| with open(file_path, 'r', encoding='utf-8') as file: | ||
| content = file.read() | ||
|
|
||
| def replace_link(match): | ||
| link = match.group(1) | ||
| text = match.group(2) | ||
| if text.endswith('^'): | ||
| return match.group(0) # No modification if caret is already present | ||
| else: | ||
| return f"{link}[{text}^]" | ||
|
|
||
| lines = content.split('\n') | ||
| updated_lines = [] | ||
| for line in lines: | ||
| if re.search(pattern, line): | ||
| line = re.sub(pattern, replace_link, line) | ||
| updated_lines.append(line) | ||
|
|
||
| # Write the updated content back to the file | ||
| - with open(file_path, 'w', encoding='utf-8') as file: | ||
| - file.write('\n'.join(updated_lines)) | ||
| + try: | ||
| + with open(file_path, 'w', encoding='utf-8') as file: | ||
| + file.write('\n'.join(updated_lines)) | ||
| + except Exception as e: | ||
| + print(f"Error writing to {file_path}: {e}") | ||
| + return False | ||
| + return True | ||
| # Get the directory of the current script | ||
| script_directory = os.path.dirname(os.path.abspath(__file__)) | ||
|
|
||
| # Construct the directory path for the 'modules' directory | ||
| directory_path = os.path.join(script_directory, '..', 'modules') | ||
|
|
||
| # List of excluded file paths (relative paths) | ||
| # List of excluded file paths (relative paths) | ||
| exclusion_list = [ | ||
| os.path.join('reference', 'pages', 'redpanda-operator', 'crd.adoc'), | ||
| os.path.join('reference', 'pages', 'k-console-helm-spec.adoc'), | ||
| os.path.join('reference', 'pages', 'crd.adoc'), | ||
| os.path.join('reference', 'pages', 'k-redpanda-helm-spec.adoc'), | ||
| os.path.join('reference', 'partials', 'bundle-contents-k8s.adoc'), | ||
| os.path.join('reference', 'partials', 'bundle-contents-linux.adoc'), | ||
| ] | ||
|
|
||
| # Function to process all .adoc files in a directory | ||
| def process_directory(directory_path): | ||
| for root, _, files in os.walk(directory_path): | ||
| for file in files: | ||
| if file.endswith('.adoc'): | ||
| file_path = os.path.join(root, file) | ||
| relative_file_path = os.path.relpath(file_path, directory_path) | ||
| if relative_file_path not in exclusion_list: | ||
| if process_file(file_path): | ||
| print(f"Processed: {file_path}") | ||
| else: | ||
| print(f"Failed to process: {file_path}") | ||
|
|
||
| # Call the function with the constructed directory path | ||
| process_directory(directory_path) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const yaml = require('js-yaml'); | ||
|
|
||
| /** | ||
| * Look for antora.yml in the current working directory | ||
| * (the project's root), load it if present, and return | ||
| * its `prerelease` value (boolean). If missing or on error, | ||
| * returns false. | ||
| */ | ||
| function getPrereleaseFromAntora() { | ||
| const antoraPath = path.join(process.cwd(), 'antora.yml'); | ||
| if (!fs.existsSync(antoraPath)) { | ||
| return false; | ||
| } | ||
|
|
||
| try { | ||
| const fileContents = fs.readFileSync(antoraPath, 'utf8'); | ||
| const antoraConfig = yaml.load(fileContents); | ||
| return antoraConfig.prerelease === true; | ||
| } catch (error) { | ||
| console.error('Error reading antora.yml:', error.message); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| module.exports = { getPrereleaseFromAntora }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.