Skip to content

Commit 2bfefca

Browse files
committed
pre-commit autocreate Markdown report of rake -T output
1 parent 2d054d5 commit 2bfefca

5 files changed

Lines changed: 193 additions & 0 deletions

File tree

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ indent_style = tab
2828
[*.bat]
2929
end_of_line = crlf
3030
#max_line_length = 80
31+
32+
[*.sha256]
33+
insert_final_newline = false

.pre-commit-config.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ repos:
1919
description: check hooks apply to the repository
2020
- repo: local
2121
hooks:
22+
- id: generate-rake-docs
23+
name: generate Rake task documentation
24+
description: generates a Markdown report of the output when running 'rake -T'
25+
# The command to execute. 'python generate_rake_docs.py' will run our script.
26+
entry: python scripts/generate_rake_docs.py
27+
# 'language: system' means pre-commit will execute the 'entry' command
28+
# directly in your system's environment. Ensure Python is in your PATH.
29+
language: system
30+
# 'files: \.rake$' specifies that this hook should only run if any
31+
# file ending with '.rake' (e.g., your Rakefiles) is staged for commit.
32+
files: \.rake$
33+
# 'pass_filenames: false' means the hook script does not receive
34+
# the names of the staged files as arguments. Our script doesn't need them.
35+
pass_filenames: false
36+
# 'always_run: false' (default) means the hook only runs if files matching
37+
# the 'files' regex are staged. This is desired behavior for this hook.
38+
# If set to 'true', it would run on every commit regardless of file changes.
2239
- id: prettier
2340
name: run prettier
2441
description: format files with prettier
@@ -59,6 +76,7 @@ repos:
5976
args: [--allow-missing-credentials]
6077
- id: detect-private-key
6178
- id: end-of-file-fixer
79+
exclude: \.sha256$
6280
- id: file-contents-sorter
6381
args: [--unique]
6482
files: ^\.github/linters/codespell\.txt$
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
698a9cc526b7f92d1479b5a61721f3b9d02220e89b2f89dea5dc76b770ada009

doc/guides/rake-tasks.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Rake Tasks
2+
3+
This file is automatically generated by a pre-commit hook. Do not edit manually.
4+
5+
```
6+
rake all # build all targets, install (locally) in-repo
7+
rake benchmark # run benchmark tests
8+
rake check # run all pre-commit hooks against all files
9+
rake checkinstall # install the pre-commit hooks
10+
rake checkupdate # check the pre-commit hooks for updates
11+
rake clean # clean all built and in-repo installed artifacts
12+
rake composecheck # run all pre-commit hooks against all files with docker-compose
13+
rake composetest # build and run all mruby tests with docker-compose
14+
rake deep_clean # clean everything
15+
rake doc # generate document
16+
rake doc:api # generate yard docs
17+
rake doc:capi # generate doxygen docs
18+
rake doc:clean # clean all built docs
19+
rake doc:clean:api # clean yard docs
20+
rake doc:clean:capi # clean doxygen docs
21+
rake doc:update-opcode.md # update doc/internal/opcode.md
22+
rake doc:view:api # open yard docs
23+
rake doc:view:capi # open doxygen docs
24+
rake generate_active_gems_txt # generate the active gems text files
25+
rake install # install compiled products (on host)
26+
rake install:bin # install compiled executable (all build targets)
27+
rake install:full # install compiled products (all build targets)
28+
rake install_bin # install compiled executable (on host)
29+
rake test # build and run all mruby tests
30+
rake test:bin # build and run command binaries tests
31+
rake test:build # build all mruby tests
32+
rake test:build:lib # build library tests
33+
rake test:lib # build and run library tests
34+
rake test:run # run all mruby tests
35+
rake test:run:bin # run command binaries tests
36+
rake test:run:lib # run library tests
37+
rake test:run:serial # run all mruby tests serially
38+
rake test:run:serial:bin # run library tests serially
39+
rake test:run:serial:lib # run command binaries tests serially
40+
```

scripts/generate_rake_docs.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/usr/bin/env python3
2+
3+
import subprocess
4+
import hashlib
5+
import os
6+
import sys
7+
8+
# --- Configuration ---
9+
# Define the directory where the Markdown and checksum files will be stored.
10+
# This will create 'doc/guides' relative to your repository root.
11+
DOCS_DIR = os.path.join("doc", "guides")
12+
13+
# Define the directory for checksums within the docs directory.
14+
# This will create 'doc/guides/checksums'.
15+
CHECKSUMS_DIR = os.path.join(DOCS_DIR, "checksums")
16+
17+
# Define the filename for the generated Rake tasks Markdown file.
18+
RAKE_MD_FILENAME = "rake-tasks.md"
19+
20+
# Construct the full path for the Markdown file.
21+
RAKE_MD_PATH = os.path.join(DOCS_DIR, RAKE_MD_FILENAME)
22+
23+
# Define the filename for the checksum file.
24+
CHECKSUM_FILENAME = f"{RAKE_MD_FILENAME}.sha256"
25+
26+
# Construct the full path for the checksum file.
27+
CHECKSUM_PATH = os.path.join(CHECKSUMS_DIR, CHECKSUM_FILENAME)
28+
29+
# --- Helper Functions ---
30+
31+
def run_rake_tasks():
32+
"""
33+
Executes the 'rake -T' command and captures its standard output.
34+
Handles cases where 'rake' is not found or the command fails.
35+
"""
36+
print("Running 'rake -T' to capture task list...")
37+
try:
38+
# subprocess.run executes the command.
39+
# capture_output=True redirects stdout and stderr.
40+
# text=True decodes stdout/stderr as text using default encoding.
41+
# check=True raises CalledProcessError if the command returns a non-zero exit code.
42+
result = subprocess.run(["rake", "-T"], capture_output=True, text=True, check=True)
43+
print("Successfully captured Rake tasks.")
44+
return result.stdout
45+
except FileNotFoundError:
46+
# Error if 'rake' command is not found in the system's PATH.
47+
print("Error: 'rake' command not found. Please ensure Rake is installed and in your PATH.", file=sys.stderr)
48+
sys.exit(1) # Exit with a non-zero code to indicate failure to the pre-commit hook.
49+
except subprocess.CalledProcessError as e:
50+
# Error if 'rake -T' command itself fails (e.g., syntax errors in Rakefiles).
51+
print(f"Error running 'rake -T':\n{e.stderr}", file=sys.stderr)
52+
sys.exit(1) # Exit with a non-zero code.
53+
54+
def generate_markdown_file(output):
55+
"""
56+
Creates or updates the RAKE_TASKS.md file with the captured Rake output.
57+
The content includes a header and the raw output embedded in a Markdown code block.
58+
"""
59+
print(f"Generating Markdown file: {RAKE_MD_PATH}...")
60+
# Ensure the directory structure exists. `exist_ok=True` prevents an error if it already exists.
61+
os.makedirs(DOCS_DIR, exist_ok=True)
62+
63+
# Construct the full Markdown content.
64+
markdown_content = f"""# Rake Tasks
65+
66+
This file is automatically generated by a pre-commit hook. Do not edit manually.
67+
68+
```
69+
{output.strip()}
70+
```
71+
"""
72+
# Write the content to the Markdown file.
73+
with open(RAKE_MD_PATH, "w") as f:
74+
f.write(markdown_content)
75+
print(f"Successfully generated {RAKE_MD_PATH}")
76+
77+
def calculate_sha256(filepath):
78+
"""
79+
Calculates the SHA256 hash of a given file.
80+
Reads the file in chunks to handle potentially large files efficiently.
81+
"""
82+
hasher = hashlib.sha256()
83+
# Open the file in binary read mode.
84+
with open(filepath, "rb") as f:
85+
# Read the file in 8KB chunks until the end.
86+
while chunk := f.read(8192):
87+
hasher.update(chunk) # Update the hash with each chunk.
88+
return hasher.hexdigest() # Return the hexadecimal representation of the hash.
89+
90+
def generate_checksum_file():
91+
"""
92+
Generates a SHA256 checksum file for RAKE_TASKS.md.
93+
The checksum is stored in a separate file in the 'checksums' subdirectory.
94+
"""
95+
print(f"Generating checksum file: {CHECKSUM_PATH}...")
96+
# Ensure the checksums directory exists.
97+
os.makedirs(CHECKSUMS_DIR, exist_ok=True)
98+
99+
# Calculate the checksum of the Markdown file.
100+
checksum = calculate_sha256(RAKE_MD_PATH)
101+
102+
# Write the checksum to its dedicated file.
103+
with open(CHECKSUM_PATH, "w") as f:
104+
f.write(checksum)
105+
print(f"Successfully generated {CHECKSUM_PATH}")
106+
107+
# --- Main Execution ---
108+
109+
def main():
110+
"""
111+
Main function to orchestrate the Rake documentation generation process.
112+
"""
113+
# Step 1: Run 'rake -T' and get its output.
114+
rake_output = run_rake_tasks()
115+
116+
# Step 2: Generate the Markdown file with the captured Rake output.
117+
generate_markdown_file(rake_output)
118+
119+
# Step 3: Generate the checksum file for the newly created Markdown file.
120+
generate_checksum_file()
121+
122+
# If the script reaches this point, it means all operations (running rake,
123+
# generating markdown, and generating checksum) were successful.
124+
# The pre-commit framework will automatically check if these newly generated
125+
# files are unstaged. If they are, it will fail the commit and prompt the
126+
# user to 'git add' them. This is the standard and recommended behavior.
127+
print("\nRake documentation generation complete.")
128+
sys.exit(0) # Exit with 0 to indicate success to the pre-commit hook.
129+
130+
if __name__ == "__main__":
131+
main()

0 commit comments

Comments
 (0)