BlockWatch: Never Let Your Code and Docs Go Stale Again
Automatically spot inconsistencies in your documentation, configuration, and code whenever they change.
Why
Have you ever updated a function but forgotten to update the README.md example that uses it? Or changed a list of
supported items in your code but forgot to update the corresponding list in the documentation?
Keeping everything in sync manually is tedious and error-prone.
What
BlockWatch is a dependency tracker for your codebase. You declare relationships between blocks of code, if a block changes, BlockWatch will require that its dependents are also updated, catching inconsistencies before they are committed.
It keeps your codebase consistent by making dependencies between code and documentation explicit and verifiable.
How It Works
It's a simple two-step process:
1. Declare your blocks
Mark a "source" block of code and give a name to a "dependent" block in another file (like your documentation).
In src/parsers/mod.rs, we define a list of languages. This block is marked as
affects="README.md:supported-grammar", creating a dependency link.
// src/parsers/mod.rs
// <block affects="README.md:supported-grammar-example">
pub
// </block>
In README.md, we define the block that depends on the code above.
- --
2. Run validation
When you make a change, BlockWatch checks the git diff. If you modify the
SUPPORTED_LANGUAGES array in src/parsers/mod.rs without also modifying the block in README.md, BlockWatch will
exit with an error, helping to prevent a bad commit.
# This command will now fail until README.md is updated
git diff --patch | blockwatch
This simple mechanism ensures your documentation and code never drift apart.
Key Features
- 🔗 Link Code to Docs: Create explicit, verifiable dependencies between code snippets and your documentation.
- 🤖 Automated Git Workflow: Integrates seamlessly with
git diffto automatically validate changes before you commit. - 🛠️ Pre-commit & CI/CD Ready: Includes support for pre-commit hooks and a dedicated GitHub Action for robust CI/CD pipelines.
- 🌍 Broad Language Support: Works with over 20 programming and markup languages out of the box.
- ⚡ Fast and Lightweight: Written in Rust for maximum performance with no runtime dependencies.
Installation
From Source
Requires the Rust toolchain:
cargo install blockwatch
Prebuilt Binary
Download a pre-built binary for your platform from the Releases page.
Usage & Integration
Command Line
The simplest way to run it is by piping a git diff into the command:
git diff --patch | blockwatch
Pre-commit Hook
For automatic checks before each commit, use it with the pre-commit framework.
Add this to your .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: blockwatch
name: blockwatch
entry: bash -c 'git diff --patch --unified=0 | blockwatch'
language: system
stages:
pass_filenames: false
GitHub Action
Add the following job to your workflow file to check for inconsistencies in pull requests.
# .github/workflows/main.yml
jobs:
blockwatch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2 # Required to diff against the base branch
- uses: mennanov/blockwatch-action@v1
Supported Languages
BlockWatch supports a wide range of common languages.
- Bash (
.sh,.bash) - C# (
.cs) - C/C++ (
.c,.cpp,.cc,.h) - CSS (
.css) - Golang (
.go) - HTML (
.html,.htm) - Java (
.java) - JavaScript (
.js,.jsx) - Kotlin (
.kt,.kts) - Markdown (
.md,.markdown) - PHP (
.php,.phtml) - Python (
.py,.pyi) - Rust (
.rs) - SQL (
.sql) - TOML (
.toml) - TypeScript (+TSX) (
.ts,.d.ts,.tsx) - XML (
.xml) - YAML (
.yaml,.yml)
Have a custom file extension?
You can map it to a supported grammar:
# Treat .xhtml files as .xml
git diff --patch | blockwatch -E xhtml=xml
Advanced Patterns
Same-File Dependencies
Blocks can affect other blocks in the same file. Just omit the filename in the affects attribute.
// <block name="foo" affects=":bar, :buzz">
// </block>
// <block name="bar">
// Some other piece of code.
// </block>
// <block name="buzz">
// One more.
// </block>
Mutual Dependencies
Blocks can reference each other.
// <block name="alice" affects=":bob">
// </block>
// <block name="bob" affects=":alice">
// </block>
Nested Blocks
Blocks can be nested inside one another.
// <block name="entire-file">
// <block name="small-block">
// </block>
// </block>
Known Limitations
- Deleted blocks are currently ignored.
- Files with unsupported grammar are ignored.
- Multiple blocks cannot be declared on a single line:
<block><block>will not work</block></block>.
Contributing
Contributions are welcome! A good place to start is by adding support for a new grammar.
Run Tests
cargo test