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
18 changes: 18 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Summary

<!-- Explain the documentation change and why it is needed. Example: "Update the NCCIA complaint link and clarify the reporting steps." -->

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Great addition of a summary section to clarify the purpose of the documentation changes.

🤖 WarpFix

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💅 Nitpick documentation

Consider providing a more specific example in the summary section to guide contributors.

🤖 WarpFix


## Safety and privacy checklist

<!-- Check every applicable item before requesting review. -->

- [ ] No victim, client, or active-case data is included
- [ ] No credentials, financial records, identity numbers, or private media are included

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

The safety and privacy checklist is a valuable addition to ensure compliance and protect sensitive information.

🤖 WarpFix

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Great addition of a safety and privacy checklist to ensure compliance.

🤖 WarpFix

- [ ] New factual claims cite an authoritative source
- [ ] Official links were checked

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Great inclusion of a safety and privacy checklist to ensure sensitive data is not included.

🤖 WarpFix

- [ ] All added or changed documentation links work
- [ ] Guidance is defensive and does not promise recovery or legal outcomes

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💅 Nitpick documentation

Consider adding a brief explanation for each checklist item for clarity.

🤖 WarpFix

## Validation

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Including a validation section is excellent for ensuring that documentation checks are performed.

🤖 WarpFix


Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💅 Nitpick documentation

Consider adding a checklist item for ensuring that all links in the documentation are functional.

🤖 WarpFix

- [ ] Documentation checks pass
113 changes: 113 additions & 0 deletions .github/scripts/check_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"""Validate required documentation and local Markdown links."""

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Good use of docstrings to explain the purpose of the script.

🤖 WarpFix


from __future__ import annotations

import re
import sys
from pathlib import Path
from urllib.parse import unquote

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise style

Using pathlib for file handling improves readability and cross-platform compatibility.

🤖 WarpFix


ROOT = Path(__file__).resolve().parents[2]
REQUIRED = (
Path("README.md"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💅 Nitpick style

Consider using a constant for the encoding type to avoid magic strings.

Suggested change
Path("README.md"),
ENCODING = 'utf-8'
text = path.read_text(encoding=ENCODING)

🤖 WarpFix

Path("SECURITY.md"),
Path("CONTRIBUTING.md"),
Path("docs/seo-metadata.md"),
Comment thread
TehseenTech marked this conversation as resolved.
)
IGNORED_PARTS = {".git", ".venv", "venv", "env", "node_modules"}
LINK_PATTERN = re.compile(r"!?\[[^\]]*\]\(([^)]*)\)")
URI_SCHEME_PATTERN = re.compile(r"^[a-z][a-z0-9+.-]*:", re.IGNORECASE)


def link_target(raw: str) -> str:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 Critical bug

The script does not handle the case where the required files are missing gracefully. Consider adding error handling.

Suggested change
def link_target(raw: str) -> str:
Add a try-except block around file reading operations.

🤖 WarpFix

"""Return the file component of a Markdown link target."""
value = raw.strip()
if not value:
return ""
if value.startswith("<") and ">" in value:
value = value[1 : value.index(">")]
else:
value = value.split(maxsplit=1)[0]
return unquote(value.split("#", 1)[0].split("?", 1)[0])

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Warning logic

Consider adding a check to ensure that the 'REQUIRED' files are not empty or contain only comments.

Suggested change
Add a check after loading the files to validate their content.

🤖 WarpFix


def main() -> int:
"""Validate required files and repository-local Markdown links."""
errors: list[str] = []

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Warning logic

Ensure that the 'REQUIRED' files are always present in the repository to avoid runtime errors.

🤖 WarpFix

for relative in REQUIRED:
path = ROOT / relative
if not path.is_file():
errors.append(
f"missing required file: {relative} "
"(restore the file or update REQUIRED)"
)

markdown_files = sorted(
path
for path in ROOT.rglob("*.md")
if not any(part in IGNORED_PARTS for part in path.parts)
)
Comment thread
TehseenTech marked this conversation as resolved.
if not markdown_files:
errors.append("no Markdown files found")

for path in markdown_files:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Warning error handling

The error handling for reading files could be more specific to differentiate between OSError and UnicodeError.

Suggested change
for path in markdown_files:
Consider logging specific error messages for different exceptions.

🤖 WarpFix

relative = path.relative_to(ROOT)
try:
text = path.read_text(encoding="utf-8")
except (OSError, UnicodeError) as exc:
errors.append(f"unable to read {relative}: {exc}")
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 Critical error handling

The script does not handle cases where the Markdown file cannot be read due to permission issues.

Suggested change
Consider adding a specific error message for permission errors.

🤖 WarpFix

if not text.strip():
errors.append(f"empty Markdown file: {relative}")
continue

for line_number, line in enumerate(text.splitlines(), start=1):
for match in LINK_PATTERN.finditer(line):
raw = match.group(1).strip()
if raw.startswith("#") or URI_SCHEME_PATTERN.match(raw):
continue

target = link_target(raw)
if not target:
errors.append(
f"{relative}:{line_number}: empty relative link target "
"(add a path or remove the link)"
)
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 Critical logic

The link validation does not account for external links, which could lead to false positives.

Suggested change
continue
Add a condition to skip validation for links that start with http or https.

🤖 WarpFix


if target.startswith("/"):
resolved = (ROOT / target.lstrip("/")).resolve()
else:
resolved = (path.parent / target).resolve()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Warning performance

The link validation logic could be optimized to avoid multiple calls to resolve paths.

Suggested change
resolved = (path.parent / target).resolve()
Cache resolved paths to improve performance.

🤖 WarpFix


try:
resolved.relative_to(ROOT)
except ValueError:
errors.append(
f"{relative}:{line_number}: link escapes repository: "
f"{raw} (use a path inside the repository)"
)
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Warning documentation

The error message for broken links could be more informative by suggesting possible fixes.

Suggested change
continue
Include a suggestion to check the target path and filename in the error message.

🤖 WarpFix


if not resolved.exists():
errors.append(
f"{relative}:{line_number}: broken relative link: {raw} "
"(check the target path and filename)"
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Warning style

Consider logging the errors instead of printing them directly for better traceability.

Suggested change
)
Use the logging module to log errors.

🤖 WarpFix


if errors:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚨 Critical logic

The script does not exit with a non-zero status code if no Markdown files are found, which may lead to false positives in CI.

Suggested change
if errors:
Return 1 if errors are found, including the case of no Markdown files.

🤖 WarpFix

print("Documentation checks failed:")
for error in errors:
print(f"- {error}")
return 1

print(
f"Documentation checks passed for {len(markdown_files)} Markdown files."
)
return 0


if __name__ == "__main__":
sys.exit(main())
26 changes: 26 additions & 0 deletions .github/workflows/documentation-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Documentation checks

on:
push:
pull_request:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Well-defined triggers for the workflow to ensure documentation checks on relevant events.

🤖 WarpFix

workflow_dispatch:

permissions:
contents: read

concurrency:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise performance

The use of concurrency settings is a good practice to optimize workflow execution.

🤖 WarpFix

group: docs-${{ github.workflow }}-${{ github.ref }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise documentation

Well-structured workflow configuration for documentation checks.

🤖 WarpFix

cancel-in-progress: true

jobs:
validate:
name: Validate documentation
runs-on: ubuntu-latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💅 Nitpick style

Consider specifying a specific version for the checkout action to avoid unexpected changes.

Suggested change
runs-on: ubuntu-latest
Use a specific version like `actions/checkout@v2.3.4`.

🤖 WarpFix

timeout-minutes: 5

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise performance

Specifying a timeout for the job is a good way to prevent hanging processes.

🤖 WarpFix

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💅 Nitpick style

Consider specifying a specific version for the checkout action to avoid unexpected changes.

Suggested change
uses: actions/checkout@v4.0.0

🤖 WarpFix

steps:
- name: Check out repository
uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Praise style

Using the latest version of the checkout action ensures that you benefit from the latest features and fixes.

🤖 WarpFix

- name: Check required files and relative links
run: python .github/scripts/check_docs.py
Loading