Skip to content

Conversation

@MalteHerrmann
Copy link
Contributor

@MalteHerrmann MalteHerrmann commented Nov 14, 2025

This PR is adding a script to automatically check for required updates to the documentation based on the latest mainnet upgrade in the list of upgrades.

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented automated Noble version tracking system that monitors version updates and identifies required documentation changes when mismatches are detected.
  • Documentation

    • Added section describing the automated module reference update workflow and version tracking process.
  • Chores

    • Added development tool configuration for task workflows and Python dependencies for version tracking functionality.

@MalteHerrmann MalteHerrmann self-assigned this Nov 14, 2025
@MalteHerrmann MalteHerrmann added the enhancement New feature or request label Nov 14, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

Walkthrough

This PR introduces the Noble Documentation Version Tracker, a Python package that monitors Noble repository versions and manages documentation updates. It comprises CLI orchestration, GitHub API integration, Go module parsing, version tracking, configuration management, and comprehensive test coverage.

Changes

Cohort / File(s) Summary
Configuration & Initialization
.gitignore, .mise.toml, requirements.txt, .noble_version_tracker.json
Adds Python ignore patterns, defines tool versions and development workflows (install, start, build, test, check-version tasks), specifies dependencies (requests, pytest), and initializes version tracker metadata.
Documentation Updates
README.md, docs/build/endpoints/mainnet.mdx
Adds "Updating The Module References" section describing the version tracking workflow; inserts HTML comment note in mainnet.mdx.
Entry Point
scripts/check_noble_version.py
Adds CLI entry point script that delegates to the package's main CLI function.
Core Package Modules
scripts/check_noble_version/__init__.py, config.py, version.py, tracker.py, parser.py
Consolidates public API re-exports, defines configuration constants (paths, repo name), implements version parsing/comparison, provides JSON tracker persistence, and extracts latest version from MDX upgrades table.
GitHub & Module Integration
scripts/check_noble_version/github.py, modules.py, cli.py
Fetches and formats diffs from GitHub API, parses/filters Go module manifests with replace directive support, and orchestrates the version tracking workflow.
Test Suite
scripts/check_noble_version/test_*.py
Comprehensive unit tests covering version parsing, GitHub integration, Go module parsing, tracker persistence, MDX parsing, and edge cases.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as cli.main()
    participant Parser as parser
    participant Tracker as tracker
    participant GitHub as github
    participant Modules as modules

    User->>CLI: Execute
    CLI->>Parser: get_latest_version_from_upgrades(mainnet.mdx)
    Parser-->>CLI: latest_version
    
    alt No latest version
        CLI-->>User: Error: no version found
    else Latest version exists
        CLI->>Tracker: load_tracker()
        Tracker-->>CLI: tracked_data
        
        alt First run
            CLI->>Tracker: save_tracker(latest_version)
            CLI-->>User: Initialized tracker
        else Version unchanged
            CLI-->>User: Up to date
        else Version changed
            CLI->>GitHub: get_diff_between_tags(last_tracked, latest)
            GitHub-->>CLI: diff_data
            CLI->>GitHub: format_diff_summary(diff_data)
            GitHub-->>CLI: summary_text
            
            CLI->>Modules: get_module_versions_for_tag(last_tracked)
            Modules-->>CLI: old_modules
            CLI->>Modules: get_module_versions_for_tag(latest)
            Modules-->>CLI: new_modules
            
            CLI->>Modules: get_module_diffs(last_tracked, latest)
            Modules-->>CLI: module_diffs
            
            CLI->>Tracker: save_tracker(latest_version)
            CLI-->>User: Display diff, modules, and changes
        end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • scripts/check_noble_version/modules.py: Go module manifest parsing with replace directive handling requires careful verification of parsing logic, edge cases (single-line vs. block forms), and module filtering correctness.
  • scripts/check_noble_version/github.py: GitHub API integration, error handling, and diff formatting logic need validation for robustness and user-friendly output.
  • scripts/check_noble_version/cli.py: Orchestration and control flow across multiple subsystems; validate state transitions and error propagation.
  • Test coverage: Verify that test files exercise both happy paths and edge cases across all modules.
  • scripts/check_noble_version/parser.py: Regex-based version extraction and comparison logic; ensure suffix detection and error messaging work as intended.

Poem

🐰 A tracker hops through Noble's versioned halls,
Comparing tags where documentation calls,
With Go modules parsed and diffs on display,
The docs stay fresh—no version delays!
Hop, parse, compare, and save the day! 🌟

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'feat: add script to auto-update docs contents' clearly summarizes the main change: introducing an automated script for updating documentation. The title is specific, concise, and directly related to the substantial changes across the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-auto-update-script

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (13)
docs/build/endpoints/mainnet.mdx (1)

7-7: Inline TODO comment is fine; consider tracking as an issue.

The HTML TODO above the Chain ID is harmless and clear. If this is more than a quick note, consider also opening a GitHub issue so the action doesn’t get lost in the docs.

README.md (1)

27-34: Nice overview of the auto‑update flow; consider tightening wording for clarity.

The new “Updating The Module References” section is useful but a bit hard to parse. A slightly tighter version could read along these lines:

This repository tracks the exact Noble version (and its modules) used by the chain and applies any required updates to the documentation when new releases are published.
A Python script reads the latest mainnet upgrade version from the upgrades list and compares it to the last version recorded in these docs.
If there’s a mismatch, it fetches the Git diff between the corresponding Noble tags and sends it to an LLM, which returns a list of documentation changes to apply here.

You might also add a short “How to run” snippet (e.g., the Python entrypoint/command) so contributors know how to trigger the check locally.

scripts/check_noble_version/test_github.py (1)

3-18: Avoid real GitHub calls in unit tests; consider mocking and verify import path.

The TestGetDiffBetweenTags tests call the real GitHub API with invalid repo/tags. That makes the test suite:

  • Dependent on network availability and GitHub uptime.
  • Vulnerable to rate limiting and latency.
  • Harder to run offline or repeatedly in CI.

I’d strongly recommend:

  • Mocking requests.get (or get_diff_between_tags) using unittest.mock/pytest fixtures and returning canned responses for “invalid repo” / “invalid tags” cases.
  • As a side benefit, you can assert that the function constructs the expected URL and handles specific status codes.

Also, please confirm that from check_noble_version.github import ... works with your current repo layout (files live under scripts/check_noble_version/): depending on how tests are run, you may need to install the package or adjust PYTHONPATH so check_noble_version resolves correctly.

scripts/check_noble_version/config.py (1)

5-15: Config constants look correct; optional: add flexibility for alternate layouts.

The path and repo constants match the structure described in this PR:

  • REPO_ROOT three levels up from config.py is appropriate for scripts/check_noble_version/config.py.
  • Derived MAINNET_MDX_PATH and TRACKER_JSON_PATH look right.
  • GITHUB_REPO matches the Noble repo used elsewhere.

If you ever need to run this tooling from a different checkout layout or against a fork, you might optionally allow overriding these via environment variables (e.g., NOBLE_REPO_ROOT, NOBLE_GITHUB_REPO), but the current defaults are fine for now.

scripts/check_noble_version/github.py (2)

9-36: Consider adding GitHub authentication to avoid rate limits.

The GitHub API has stricter rate limits for unauthenticated requests (60 requests/hour vs 5,000 for authenticated). For a documentation tracking script that might run frequently, consider adding support for GitHub tokens via environment variables.

You can add authentication like this:

 def get_diff_between_tags(repo: str, base_tag: str, head_tag: str) -> Optional[Dict[str, Any]]:
     """
     Get the diff between two tags from GitHub API.
     
     Args:
         repo: Repository in format 'owner/repo'
         base_tag: Base tag (e.g., 'v11.0.0')
         head_tag: Head tag (e.g., 'v12.0.0')
     
     Returns:
         Dictionary with comparison data from GitHub API, or None on error
     """
     url = f"https://api.github.com/repos/{repo}/compare/{base_tag}...{head_tag}"
+    
+    headers = {}
+    github_token = os.getenv('GITHUB_TOKEN')
+    if github_token:
+        headers['Authorization'] = f'Bearer {github_token}'
     
     try:
-        response = requests.get(url, timeout=30)
+        response = requests.get(url, headers=headers, timeout=30)
         response.raise_for_status()
         return response.json()

Don't forget to add import os at the top of the file.


113-121: Address the TODO comment.

The TODO comment questions whether the relevant file keywords are correct. This list seems reasonable for documentation tracking (modules, proto files, upgrades, migrations, changelogs, releases), but you should verify it matches your documentation update workflow.

Would you like me to help refine this list based on your documentation structure, or would you prefer to open an issue to track this verification task?

scripts/check_noble_version/modules.py (1)

75-94: Consider adding GitHub authentication to avoid rate limits.

Similar to the get_diff_between_tags function in github.py, this function could benefit from GitHub token authentication to avoid rate limiting on raw content fetches.

Apply this diff to add authentication support:

 def fetch_go_mod(repo: str, tag: str) -> Optional[str]:
     """
     Fetch the go.mod file content from GitHub for a specific tag.
     
     Args:
         repo: Repository in format 'owner/repo'
         tag: Git tag (e.g., 'v11.0.0')
     
     Returns:
         Content of go.mod file as string, or None on error
     """
     url = f"https://raw.githubusercontent.com/{repo}/{tag}/go.mod"
+    
+    headers = {}
+    github_token = os.getenv('GITHUB_TOKEN')
+    if github_token:
+        headers['Authorization'] = f'Bearer {github_token}'
     
     try:
-        response = requests.get(url, timeout=30)
+        response = requests.get(url, headers=headers, timeout=30)
         response.raise_for_status()
         return response.text

Don't forget to add import os at the top of the file.

scripts/check_noble_version/test_tracker.py (1)

13-20: Consider using tempfile for better portability.

The hardcoded /tmp/ path works on Unix systems but isn't portable to Windows. While the static analysis warning about security is a false positive here (the path is intentionally non-existent), using tempfile would improve cross-platform compatibility.

Apply this diff:

+    import tempfile
+    
     def test_load_tracker_file_not_exists(self):
         """Test loading tracker when file doesn't exist"""
-        non_existent_path = Path("/tmp/non_existent_tracker_12345.json")
+        non_existent_path = Path(tempfile.gettempdir()) / "non_existent_tracker_12345.json"
         result = load_tracker(non_existent_path)

Note: tempfile is already imported at line 4, so you can use it directly.

scripts/check_noble_version/version.py (1)

36-42: Use exception chaining when wrapping ValueError for easier debugging

parse_version and compare_versions both catch a ValueError and raise a new ValueError with additional context, but they drop the original traceback. This makes it harder to pinpoint the root cause and is what Ruff’s B904 is flagging.

You can keep the current messages while preserving the original cause:

-    except ValueError as e:
-        raise ValueError(
-            f"Invalid version format: '{version_str}'\n"
-            f"All version components must be integers. Error: {e}"
-        )
+    except ValueError as e:
+        raise ValueError(
+            f"Invalid version format: '{version_str}'\n"
+            f"All version components must be integers. Error: {e}"
+        ) from e
-    except ValueError as e:
-        # Re-raise with context about which version failed
-        raise ValueError(f"Error comparing versions '{version1}' and '{version2}':\n{e}")
+    except ValueError as e:
+        # Re-raise with context about which version failed
+        raise ValueError(
+            f"Error comparing versions '{version1}' and '{version2}':\n{e}"
+        ) from e

This keeps the public behavior while improving observability and satisfying the linter.

Also applies to: 57-62

scripts/check_noble_version/tracker.py (1)

31-45: Narrow broad Exception handlers in tracker I/O paths

Both load_tracker and save_tracker catch bare Exception, which can hide unexpected programming errors and is what Ruff’s BLE001 is flagging. Since the intent is to handle I/O/JSON issues and fall back to a safe default, you can narrow the handlers without changing behavior:

-    except json.JSONDecodeError as e:
+    except json.JSONDecodeError as e:
         print(f"Error: Invalid JSON in tracker file: {e}", file=sys.stderr)
         return {
             "last_tracked_version": None,
             "last_checked": None
         }
-    except Exception as e:
+    except OSError as e:
         print(f"Error reading tracker file: {e}", file=sys.stderr)
         return {
             "last_tracked_version": None,
             "last_checked": None
         }
-    try:
-        with open(tracker_path, 'w', encoding='utf-8') as f:
-            json.dump(tracker_data, f, indent=2)
-    except Exception as e:
+    try:
+        with open(tracker_path, 'w', encoding='utf-8') as f:
+            json.dump(tracker_data, f, indent=2)
+    except OSError as e:
         print(f"Error writing tracker file: {e}", file=sys.stderr)

This keeps the “fail soft” semantics while avoiding overly broad catching.

Also applies to: 64-68

scripts/check_noble_version/parser.py (1)

21-29: Tighten the generic Exception handler when reading the MDX file

The generic except Exception as e: around open/read is what Ruff flags as BLE001. Given the intent is to handle file access problems and fail soft by returning None, you can narrow this without changing behavior:

-    try:
-        with open(mdx_path, 'r', encoding='utf-8') as f:
-            content = f.read()
-    except FileNotFoundError:
-        print(f"Error: File not found: {mdx_path}", file=sys.stderr)
-        return None
-    except Exception as e:
-        print(f"Error reading file {mdx_path}: {e}", file=sys.stderr)
-        return None
+    try:
+        with open(mdx_path, 'r', encoding='utf-8') as f:
+            content = f.read()
+    except FileNotFoundError:
+        print(f"Error: File not found: {mdx_path}", file=sys.stderr)
+        return None
+    except OSError as e:
+        print(f"Error reading file {mdx_path}: {e}", file=sys.stderr)
+        return None

That keeps the current UX while avoiding a blind catch‑all.

scripts/check_noble_version/cli.py (1)

49-58: Clarify exit codes for mismatch scenarios and drop unused f-strings

Two related points around the mismatch paths:

  1. Exit codes for automation

When latest_version is newer than last_tracked (version mismatch) or when last_tracked is newer than the docs (reverted docs warning), the script currently runs to completion without calling sys.exit, so it exits with status 0. If this CLI is intended for CI or other automation, you may want non‑zero exit codes so “action required” states are machine-detectable, for example:

        elif comparison < 0:
             print(f"\n⚠ Version mismatch detected!")
             ...
-            else:
-                print(f"\n  ⚠ Could not fetch diff from GitHub API.")
-                print(f"  You can view the comparison manually at:")
-                print(f"  https://github.com/{GITHUB_REPO}/compare/{last_tracked}...{latest_version}")
+            else:
+                print("\n  ⚠ Could not fetch diff from GitHub API.")
+                print("  You can view the comparison manually at:")
+                print(f"  https://github.com/{GITHUB_REPO}/compare/{last_tracked}...{latest_version}")
+            sys.exit(2)
        else:
             print(f"\n⚠ Warning: Last tracked version ({last_tracked}) is newer than latest in docs ({latest_version})")
             print("  This shouldn't happen - the docs may have been reverted.")
+            sys.exit(3)

Exit codes are illustrative; you can pick values that fit your conventions.

  1. Remove unnecessary f prefixes

Several print calls use f-strings without interpolation (lines 55, 58, 92, 121, 122). These can be plain strings to satisfy Ruff F541 and slightly simplify the code:

-            print(f"\n⚠ Version mismatch detected!")
+            print("\n⚠ Version mismatch detected!")
...
-            print(f"\n  The documentation has been updated with a new version.")
+            print("\n  The documentation has been updated with a new version.")
...
-                print(f"\nFetching module-specific diffs...")
+                print("\nFetching module-specific diffs...")
...
-                print(f"\n  ⚠ Could not fetch diff from GitHub API.")
-                print(f"  You can view the comparison manually at:")
+                print("\n  ⚠ Could not fetch diff from GitHub API.")
+                print("  You can view the comparison manually at:")

This keeps behavior unchanged while aligning with the linter.

Also applies to: 92-93, 121-126

scripts/check_noble_version/__init__.py (1)

25-41: Consider sorting __all__ alphabetically.

The __all__ list correctly includes all public API members, and the current grouping by functionality is logical. However, alphabetical sorting would improve consistency and make it easier to verify additions.

Apply this diff to sort __all__ alphabetically:

 __all__ = [
-    "parse_version",
+    "GITHUB_REPO",
+    "MAINNET_MDX_PATH",
+    "MODULE_MAPPINGS",
+    "REPO_ROOT",
+    "TRACKER_JSON_PATH",
     "compare_versions",
-    "get_latest_version_from_upgrades",
-    "load_tracker",
-    "save_tracker",
     "get_diff_between_tags",
     "format_diff_summary",
+    "get_latest_version_from_upgrades",
+    "get_module_diffs",
+    "get_module_versions_for_tag",
     "get_relevant_module_paths",
-    "get_module_versions_for_tag",
-    "get_module_diffs",
-    "MODULE_MAPPINGS",
-    "REPO_ROOT",
-    "MAINNET_MDX_PATH",
-    "TRACKER_JSON_PATH",
-    "GITHUB_REPO",
+    "load_tracker",
+    "parse_version",
+    "save_tracker",
 ]

Based on static analysis hints.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1260c2 and 73ca44c.

📒 Files selected for processing (20)
  • .gitignore (1 hunks)
  • .mise.toml (1 hunks)
  • .noble_version_tracker.json (1 hunks)
  • README.md (1 hunks)
  • docs/build/endpoints/mainnet.mdx (1 hunks)
  • requirements.txt (1 hunks)
  • scripts/check_noble_version.py (1 hunks)
  • scripts/check_noble_version/__init__.py (1 hunks)
  • scripts/check_noble_version/cli.py (1 hunks)
  • scripts/check_noble_version/config.py (1 hunks)
  • scripts/check_noble_version/github.py (1 hunks)
  • scripts/check_noble_version/modules.py (1 hunks)
  • scripts/check_noble_version/parser.py (1 hunks)
  • scripts/check_noble_version/test_github.py (1 hunks)
  • scripts/check_noble_version/test_modules.py (1 hunks)
  • scripts/check_noble_version/test_parser.py (1 hunks)
  • scripts/check_noble_version/test_tracker.py (1 hunks)
  • scripts/check_noble_version/test_version.py (1 hunks)
  • scripts/check_noble_version/tracker.py (1 hunks)
  • scripts/check_noble_version/version.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (10)
scripts/check_noble_version/parser.py (1)
scripts/check_noble_version/version.py (2)
  • parse_version (6-42)
  • compare_versions (45-69)
scripts/check_noble_version/test_tracker.py (1)
scripts/check_noble_version/tracker.py (2)
  • load_tracker (12-45)
  • save_tracker (48-68)
scripts/check_noble_version/test_github.py (1)
scripts/check_noble_version/github.py (2)
  • get_diff_between_tags (9-36)
  • format_diff_summary (39-149)
scripts/check_noble_version/test_parser.py (1)
scripts/check_noble_version/parser.py (1)
  • get_latest_version_from_upgrades (11-69)
scripts/check_noble_version/test_version.py (1)
scripts/check_noble_version/version.py (2)
  • parse_version (6-42)
  • compare_versions (45-69)
scripts/check_noble_version.py (1)
scripts/check_noble_version/cli.py (1)
  • main (19-133)
scripts/check_noble_version/modules.py (1)
scripts/check_noble_version/github.py (1)
  • get_diff_between_tags (9-36)
scripts/check_noble_version/__init__.py (5)
scripts/check_noble_version/version.py (2)
  • parse_version (6-42)
  • compare_versions (45-69)
scripts/check_noble_version/parser.py (1)
  • get_latest_version_from_upgrades (11-69)
scripts/check_noble_version/tracker.py (2)
  • load_tracker (12-45)
  • save_tracker (48-68)
scripts/check_noble_version/github.py (2)
  • get_diff_between_tags (9-36)
  • format_diff_summary (39-149)
scripts/check_noble_version/modules.py (3)
  • get_relevant_module_paths (62-72)
  • get_module_versions_for_tag (270-285)
  • get_module_diffs (330-377)
scripts/check_noble_version/test_modules.py (1)
scripts/check_noble_version/modules.py (7)
  • get_relevant_module_paths (62-72)
  • parse_go_mod (97-142)
  • parse_replace_directives (145-196)
  • apply_replace_directives (199-224)
  • get_relevant_modules_from_go_mod (227-267)
  • get_module_versions_for_tag (270-285)
  • get_module_diffs (330-377)
scripts/check_noble_version/cli.py (5)
scripts/check_noble_version/parser.py (1)
  • get_latest_version_from_upgrades (11-69)
scripts/check_noble_version/tracker.py (2)
  • load_tracker (12-45)
  • save_tracker (48-68)
scripts/check_noble_version/version.py (1)
  • compare_versions (45-69)
scripts/check_noble_version/github.py (2)
  • get_diff_between_tags (9-36)
  • format_diff_summary (39-149)
scripts/check_noble_version/modules.py (2)
  • get_module_versions_for_tag (270-285)
  • get_module_diffs (330-377)
🪛 markdownlint-cli2 (0.18.1)
README.md

8-8: Dollar signs used before commands without showing output

(MD014, commands-show-output)


14-14: Dollar signs used before commands without showing output

(MD014, commands-show-output)


22-22: Dollar signs used before commands without showing output

(MD014, commands-show-output)

🪛 Ruff (0.14.4)
scripts/check_noble_version/parser.py

27-27: Do not catch blind exception: Exception

(BLE001)

scripts/check_noble_version/tracker.py

40-40: Do not catch blind exception: Exception

(BLE001)


67-67: Do not catch blind exception: Exception

(BLE001)

scripts/check_noble_version/version.py

21-25: Avoid specifying long messages outside the exception class

(TRY003)


31-34: Avoid specifying long messages outside the exception class

(TRY003)


39-42: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


39-42: Avoid specifying long messages outside the exception class

(TRY003)


62-62: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


62-62: Avoid specifying long messages outside the exception class

(TRY003)

scripts/check_noble_version/test_tracker.py

15-15: Probable insecure usage of temporary file or directory: "/tmp/non_existent_tracker_12345.json"

(S108)

scripts/check_noble_version/test_parser.py

88-88: Probable insecure usage of temporary file or directory: "/tmp/non_existent_file_12345.mdx"

(S108)

scripts/check_noble_version/modules.py

91-91: Consider moving this statement to an else block

(TRY300)

scripts/check_noble_version/__init__.py

25-41: __all__ is not sorted

Apply an isort-style sorting to __all__

(RUF022)

scripts/check_noble_version/cli.py

55-55: f-string without any placeholders

Remove extraneous f prefix

(F541)


58-58: f-string without any placeholders

Remove extraneous f prefix

(F541)


92-92: f-string without any placeholders

Remove extraneous f prefix

(F541)


121-121: f-string without any placeholders

Remove extraneous f prefix

(F541)


122-122: f-string without any placeholders

Remove extraneous f prefix

(F541)

🔇 Additional comments (14)
.gitignore (1)

22-24: Python ignore patterns look good.

Ignoring __pycache__ directories and .venv is appropriate for the new Python tooling in this repo.

requirements.txt (1)

1-3: Dependencies are reasonable; verify version and environment constraints.

requests>=2.31.0 and pytest>=8.0.0 make sense for the new script and tests. Please double‑check:

  • That these versions are compatible with the Python versions used in CI and locally.
  • Whether you want a separate dev/test requirements file (e.g., for pytest) vs. a single runtime requirements list.
scripts/check_noble_version/test_github.py (1)

20-77: format_diff_summary tests give good coverage of key behaviors.

The tests for format_diff_summary nicely cover:

  • Empty input handling.
  • Basic summary fields (status, ahead/behind counts, file counts, commits, URL).
  • The “Potentially relevant files for documentation” filtering.

This should make refactoring that formatter much safer.

scripts/check_noble_version/modules.py (3)

7-11: LGTM: Import error handling is appropriate.

The hard exit when requests is missing is reasonable since it's a required dependency listed in requirements.txt. The error message clearly guides users to install the dependency.


18-59: Well-structured module mapping.

The MODULE_MAPPINGS constant is comprehensive and accounts for alternative module paths (e.g., dollar.noble.xyz vs github.com/noble-assets/dollar). The comment clearly explains its purpose.


97-196: LGTM: Parsing logic is well-structured.

The go.mod parsing functions use appropriate state machine logic to handle both block and single-line formats. The regex patterns correctly handle various go.mod syntaxes including comments, indirect dependencies, and version constraints.

scripts/check_noble_version/test_modules.py (1)

1-241: LGTM: Comprehensive test coverage.

The test suite provides excellent coverage of the modules.py functionality:

  • Parsing variations (blocks, single-line, with/without comments)
  • Replace directive handling and precedence
  • Edge cases (invalid tags, empty results)
  • Integration between parsing and filtering functions

The tests are well-organized with clear docstrings and appropriate assertions.

.noble_version_tracker.json (1)

1-4: LGTM: Version tracker initialization.

The initial tracker state is properly formatted and provides a reasonable starting point (v10.0.0). This file will be automatically updated by the tracking script.

scripts/check_noble_version.py (1)

1-11: LGTM: Clean entry point delegation.

The entry point script follows Python best practices with a shebang, clear docstring, and clean delegation to the package CLI. This separation allows the package to be imported and tested independently.

scripts/check_noble_version/test_version.py (1)

1-83: LGTM: Thorough version parsing tests.

The test suite comprehensively covers:

  • Valid version formats (with/without 'v' prefix)
  • Suffix rejection (critical for ensuring only release versions are used)
  • Invalid format detection
  • All comparison scenarios (equal, less than, greater than)
  • Error propagation in compare_versions

The tests align well with the documented version format requirements.

.mise.toml (1)

1-34: LGTM: Well-structured tooling configuration.

The mise configuration provides:

  • Clear tool version specifications
  • Documented task workflows
  • Modern tooling choices (Python 3.12, uv for fast package installation)
  • Integration with the new version tracking workflow

The task definitions make it easy for contributors to run common operations.

scripts/check_noble_version/test_tracker.py (1)

22-74: LGTM: Comprehensive tracker tests.

The test suite properly covers:

  • Non-existent file handling (returns defaults)
  • Valid JSON loading and parsing
  • Invalid JSON graceful fallback
  • File creation and content verification

The use of tempfile.NamedTemporaryFile with proper cleanup is good practice.

scripts/check_noble_version/__init__.py (2)

1-6: LGTM!

The module docstring clearly describes the package purpose and scope.


8-23: LGTM!

The imports are well-organized by source module, and all imported names are properly re-exported in __all__. The structure provides a clean public API for the package.

Comment on lines 7 to 9
```sh
$ yarn
$ bun
```
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Shell command snippets: drop the $ prompt to satisfy markdownlint and ease copy‑paste.

The commands are currently written with a $ prompt (e.g., $ bun), which triggers MD014 and makes copy‑paste slightly less convenient. I’d suggest removing the prompt symbol:

-```sh
-$ bun
-```
+```sh
+bun
+```

-```sh
-$ bun start
-```
+```sh
+bun start
+```

-```sh
-$ bun build
-```
+```sh
+bun build
+```

This keeps the docs lint‑clean and avoids confusion about what should actually be typed.

Also applies to: 14-15, 22-23

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

8-8: Dollar signs used before commands without showing output

(MD014, commands-show-output)

🤖 Prompt for AI Agents
In README.md around lines 7 to 9 (also apply the same change at lines 14-15 and
22-23), remove the leading "$ " prompt from the fenced shell code blocks so the
examples are raw commands; update each block to use the ```sh fence with the
command on the next line (for example replace "$ bun" with "bun"), ensuring
there is no "$" prompt so markdownlint MD014 is satisfied and users can
copy‑paste the commands directly.

return base_mapping


def get_module_diffs(repo: str, base_tag: str, head_tag: str) -> Dict[str, Dict[str, any]]:
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix type hint: use 'Any' instead of 'any'.

The return type annotation uses lowercase any which is invalid. It should be Any (already imported from typing on line 3).

Apply this diff:

-def get_module_diffs(repo: str, base_tag: str, head_tag: str) -> Dict[str, Dict[str, any]]:
+def get_module_diffs(repo: str, base_tag: str, head_tag: str) -> Dict[str, Dict[str, Any]]:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def get_module_diffs(repo: str, base_tag: str, head_tag: str) -> Dict[str, Dict[str, any]]:
def get_module_diffs(repo: str, base_tag: str, head_tag: str) -> Dict[str, Dict[str, Any]]:
🤖 Prompt for AI Agents
In scripts/check_noble_version/modules.py around line 330, the return type
annotation uses the invalid lowercase 'any'; update the function signature to
use the proper typing Any (i.e., change Dict[str, Dict[str, any]] to Dict[str,
Dict[str, Any]]), relying on the existing import from typing.

Comment on lines +21 to +29
with tempfile.NamedTemporaryFile(mode='w', suffix='.mdx', delete=False) as f:
f.write(content)
f.flush()
path = Path(f.name)

result = get_latest_version_from_upgrades(path)
assert result == "v3.0.0"

path.unlink()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Unlink temporary files after closing the handle to avoid cross‑platform issues

Each test unlinks the temporary file inside the with tempfile.NamedTemporaryFile(...): block while the file is still open. This works on POSIX but is likely to fail on Windows (PermissionError), making tests platform‑dependent.

Consider moving path.unlink() outside the with block (or using TemporaryDirectory / a test helper that creates and cleans up the file) so deletion happens after the file handle is closed.

Also applies to: 41-49, 59-67, 76-84

🤖 Prompt for AI Agents
In scripts/check_noble_version/test_parser.py around lines 21-29 (and similarly
for 41-49, 59-67, 76-84), the test unlinks the temporary file while the
NamedTemporaryFile handle is still open which can raise PermissionError on
Windows; move the path.unlink() call so it executes after the with-block (i.e.,
after the file handle is closed), or alternatively replace the temporary-file
pattern with TemporaryDirectory or a test helper that creates and cleans up
files to ensure deletion happens only after the file handle is closed.

@MalteHerrmann MalteHerrmann marked this pull request as draft November 14, 2025 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants