Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions .github/scripts/verify-code-references.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#!/usr/bin/env bash
# Verify that code references in documentation match actual source code
# This script extracts CODE_REFERENCE comments from markdown files and validates
# that the referenced code still exists at the specified line numbers

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
DOCS_DIR="${REPO_ROOT}/website/docs"
EXIT_CODE=0
TOTAL_REFS=0
VALID_REFS=0
INVALID_REFS=0

echo "Verifying code references in documentation..."
echo "Repository root: ${REPO_ROOT}"
echo ""

# Find all markdown files with CODE_REFERENCE comments
while IFS= read -r doc_file; do
# Extract CODE_REFERENCE comments from this file
while IFS= read -r line_num; do
# Get the actual line content
comment_line=$(sed -n "${line_num}p" "$doc_file")

# Extract file path and line range from comment
# Format: <!-- CODE_REFERENCE: path/to/file.rs#L123-L456 -->
if [[ $comment_line =~ CODE_REFERENCE:\ *([^#]+)#L([0-9]+)-L([0-9]+) ]]; then
file_path="${BASH_REMATCH[1]}"
start_line="${BASH_REMATCH[2]}"
end_line="${BASH_REMATCH[3]}"

# Trim whitespace from file_path
file_path=$(echo "$file_path" | xargs)

TOTAL_REFS=$((TOTAL_REFS + 1))

# Check if the source file exists
source_file="${REPO_ROOT}/${file_path}"
if [[ ! -f "$source_file" ]]; then
echo -e "${RED}✗${NC} Invalid reference in ${doc_file}:${line_num}"
echo " File not found: ${file_path}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this case cover the file existing but not having permissions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And by the way, this works only for the related repo? As in, our doc website will. check only references from the rust node repo or can it check any arbitrary repository as long as you configure it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this case cover the file existing but not having permissions?

-f filename checks if the file exists. We should not care about the permissions as it would be on code that is supposed to have at least the read permissions (code, toml, yaml, etc).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And by the way, this works only for the related repo? As in, our doc website will. check only references from the rust node repo or can it check any arbitrary repository as long as you configure it?

Yes, only related repo for now. I will think about something else for other repositories. We will need to add something for the Caml repo for instance.

INVALID_REFS=$((INVALID_REFS + 1))
EXIT_CODE=1
continue
fi

# Check if the line range is valid
total_lines=$(wc -l < "$source_file")
if [[ $end_line -gt $total_lines ]]; then
echo -e "${RED}✗${NC} Invalid reference in ${doc_file}:${line_num}"
echo " Line range L${start_line}-L${end_line} exceeds file length (${total_lines} lines)"
echo " File: ${file_path}"
INVALID_REFS=$((INVALID_REFS + 1))
EXIT_CODE=1
continue
fi

# Extract the actual code from source file
actual_code=$(sed -n "${start_line},${end_line}p" "$source_file")

# Find the corresponding code block in the markdown (should be right after the comment)
# Look for ```rust reference block within next 5 lines
code_block_start=$((line_num + 1))
code_block_end=$((line_num + 10))

# Extract GitHub URL from the reference block
github_url=$(sed -n "${code_block_start},${code_block_end}p" "$doc_file" | grep "github.com" | head -1)

if [[ -n "${github_url}" ]]; then
# Verify the GitHub URL contains correct line range
line_range_pattern="#L${start_line}-L${end_line}"
if [[ "${github_url}" =~ ${line_range_pattern} ]]; then
# Extract GitHub raw URL from the reference
# Convert: https://github.com/o1-labs/mina-rust/blob/develop/path/to/file.rs#L10-L20
# To: https://raw.githubusercontent.com/o1-labs/mina-rust/develop/path/to/file.rs
if [[ "${github_url}" =~ github\.com/([^/]+)/([^/]+)/blob/([^/]+)/([^#]+) ]]; then
org="${BASH_REMATCH[1]}"
repo="${BASH_REMATCH[2]}"
branch="${BASH_REMATCH[3]}"
gh_file_path="${BASH_REMATCH[4]}"

raw_url="https://raw.githubusercontent.com/${org}/${repo}/${branch}/${gh_file_path}"

# Fetch the code from GitHub
github_code=$(curl -s "${raw_url}" | sed -n "${start_line},${end_line}p")

# Compare local code with GitHub code
if [[ "${actual_code}" == "${github_code}" ]]; then
echo -e "${GREEN}✓${NC} Valid reference in ${doc_file}:${line_num}"
echo " ${file_path}#L${start_line}-L${end_line}"
echo " Local code matches GitHub (${branch})"
VALID_REFS=$((VALID_REFS + 1))
else
echo -e "${RED}✗${NC} Code mismatch in ${doc_file}:${line_num}"
echo " ${file_path}#L${start_line}-L${end_line}"
echo " Local code differs from GitHub (${branch})"
echo " This may indicate uncommitted changes or branch divergence"
INVALID_REFS=$((INVALID_REFS + 1))
EXIT_CODE=1
fi
else
echo -e "${YELLOW}⚠${NC} Could not parse GitHub URL in ${doc_file}:${line_num}"
echo " URL: ${github_url}"
INVALID_REFS=$((INVALID_REFS + 1))
EXIT_CODE=1
fi
else
echo -e "${YELLOW}⚠${NC} Mismatched line range in ${doc_file}:${line_num}"
echo " CODE_REFERENCE comment specifies: L${start_line}-L${end_line}"
echo " But GitHub URL has different line range"
INVALID_REFS=$((INVALID_REFS + 1))
EXIT_CODE=1
fi
else
echo -e "${YELLOW}⚠${NC} No GitHub URL found for reference in ${doc_file}:${line_num}"
echo " Expected rust reference block with GitHub URL"
INVALID_REFS=$((INVALID_REFS + 1))
EXIT_CODE=1
fi
fi
done < <(grep -n "CODE_REFERENCE:" "$doc_file" | cut -d: -f1)
done < <(find "$DOCS_DIR" -name "*.md" -o -name "*.mdx")

echo ""
echo "================================"
echo "Code Reference Verification Summary"
echo "================================"
echo -e "Total references checked: ${TOTAL_REFS}"
echo -e "${GREEN}Valid references: ${VALID_REFS}${NC}"
if [[ $INVALID_REFS -gt 0 ]]; then
echo -e "${RED}Invalid references: ${INVALID_REFS}${NC}"
else
echo -e "${GREEN}Invalid references: ${INVALID_REFS}${NC}"
fi
echo ""

if [[ $EXIT_CODE -eq 0 ]]; then
echo -e "${GREEN}✓ All code references are valid!${NC}"
else
echo -e "${RED}✗ Some code references are invalid. Please update the documentation.${NC}"
fi

exit $EXIT_CODE
3 changes: 3 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ jobs:
# - ./github/workflows/lint.yaml
toolchain: nightly

- name: Verify code references in documentation
run: bash .github/scripts/verify-code-references.sh

- name: Build documentation
run: make docs-build

Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Website**: add "Join devnet" page with instructions for community members to
join the devnet program and test the Rust node implementation
([#1425](https://github.com/o1-labs/mina-rust/issues/1425))
- **Website**: add documentation guidelines
([#1493](https://github.com/o1-labs/mina-rust/pull/1493))

### Changed

Expand Down
124 changes: 124 additions & 0 deletions website/docs/developers/documentation-guidelines.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
---
sidebar_position: 10
title: Documentation Guidelines
description: Best practices for writing and maintaining documentation
slug: /developers/documentation-guidelines
---

# Documentation Guidelines

This guide explains how to write and maintain documentation for the Mina Rust
project, including how to reference code from the codebase. Referencing code
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as always, check the line breaks 🙏

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The line breaks at 80 characters, and it is fine as in markdown, it adds a new line only when you have two new lines.

`\n` -> no new line when rendered
`\n\n` -> a new line when rendered

from codebases can be useful to check compatibility between implementations. For
instance, we can have pages where the Rust code is compared to the OCaml code to
discuss the differences or similarities.

## Referencing Code in Documentation

To keep documentation synchronized with the actual codebase, we use the
[`docusaurus-theme-github-codeblock`](https://github.com/christian-bromann/docusaurus-theme-github-codeblock)
plugin that automatically fetches code from GitHub.

### How to add code references

Use this pattern to reference code snippets:

````
<!-- CODE_REFERENCE: path/to/file.rs#LStartLine-LEndLine -->

```rust reference title="path/to/file.rs"
https://github.com/o1-labs/mina-rust/blob/develop/path/to/file.rs#LStartLine-LEndLine
```
````

### Example

Here's a real example from the zkApps documentation:

<!-- CODE_REFERENCE: ledger/src/scan_state/transaction_logic.rs#L3588-L3592 -->

```rust reference title="ledger/src/scan_state/transaction_logic.rs"
https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L3588-L3592
```

### Components explained

1. **CODE_REFERENCE comment**: Acts as the source of truth for verification

```markdown
<!-- CODE_REFERENCE: path/to/file.rs#LStartLine-LEndLine -->
```

- Must match the GitHub URL line range exactly
- Used by CI to verify references are valid
- Path is relative to repository root

2. **Code block with reference**: Displays the actual code

```markdown
(triple backticks)rust reference title="path/to/file.rs"
https://github.com/o1-labs/mina-rust/blob/develop/path/to/file.rs#LStartLine-LEndLine
(triple backticks)
```

- Language: Use appropriate language identifier (`rust`, `toml`, `bash`,
etc.)
- `reference` keyword: Tells the plugin to fetch code from GitHub
- `title`: Optional, shows the file path above the code block
- URL: Full GitHub URL with line range (`#L10-L20`)

### Verification

A verification script runs in CI to ensure all code references are valid:

```bash
bash .github/scripts/verify-code-references.sh
```

The script checks:

- ✓ Referenced files exist
- ✓ Line ranges are valid
- ✓ GitHub URLs match CODE_REFERENCE comments
- ✓ Code blocks have corresponding references
- ✓ Local code matches what's deployed on GitHub

### When code changes

If code is added or removed and line numbers shift:

1. The verification script will detect the mismatch in CI
2. Update the `CODE_REFERENCE` comment with new line numbers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear from reading this if this happens automatically or not. My understanding is that NOT, but could be a bit clearer

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not happen automatically. It is manual.

3. Update the GitHub URL with matching line numbers
4. The plugin will automatically fetch the updated code

### Important: workflow for adding code references

<!-- prettier-ignore-start -->

:::caution

Code references must always point to code that exists on the `develop` branch.
The verification script compares local code with GitHub's `develop` branch.

:::

<!-- prettier-ignore-end -->

**Recommended workflow:**

1. **First PR**: Implement and merge your code changes to `develop`
2. **Second PR**: Add documentation with code references

This ensures:

- Code references are always valid in CI
- Documentation doesn't break due to uncommitted changes
- The plugin can fetch code from GitHub successfully

**Why separate PRs?**

- The verification script compares local code with GitHub's `develop` branch
- If code isn't merged yet, the script will fail with a "code mismatch" error
- This prevents documentation from referencing code that doesn't exist on
`develop`
2 changes: 2 additions & 0 deletions website/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ const config: Config = {
],
],

themes: ['docusaurus-theme-github-codeblock'],


themeConfig: {
// Replace with your project's social card
Expand Down
10 changes: 10 additions & 0 deletions website/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@docusaurus/preset-classic": "^3.8.1",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"docusaurus-theme-github-codeblock": "^2.0.2",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
"react-dom": "^19.0.0"
Expand Down
7 changes: 7 additions & 0 deletions website/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ const sidebars: SidebarsConfig = {
'developers/testing/ocaml-node-tests',
],
},
{
type: 'category',
label: 'Documentation',
items: [
'developers/documentation-guidelines',
],
},
{
type: 'category',
label: 'Future Work',
Expand Down
Loading