-
Notifications
You must be signed in to change notification settings - Fork 16
Add Node example validator #253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0979fd7
8c50af8
d401df7
8b2b0d4
b52e90e
810f371
062a72d
29c542a
255b9b1
244a629
0761d6a
8a7a4fb
7ac52e6
04cbc86
17eb384
934eb20
2dda231
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| name: Check Node Examples | ||
|
|
||
| # Full-compilation validates the Node.js (TypeScript) code examples in the | ||
| # docs against the real @valkey/valkey-glide type definitions built from source. | ||
| # See scripts/validators/check-node-examples.py. | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [main] | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| check-node-examples: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout valkey-glide-docs | ||
| uses: actions/checkout@v4 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One of the security findings for the C# repo was that we should use commit hashes rather than version numbers, e.g. (As I understand it, a commit hash cannot be changed, but a malicious actor who was able to gain control of a repo could update the tag to point to a new commit and so download different code). Are you able to raise an issue for this on the docs repo? Should be a very easy issue to fix with AI.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Created #261 |
||
|
|
||
| - name: Checkout valkey-glide | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| repository: valkey-io/valkey-glide | ||
| path: valkey-glide | ||
|
Comment on lines
+22
to
+26
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would there be any advantages to doing a limited checkout of the few directories (e.g. (The C# validator workflow doesn't checkout the
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could restrict it but I don't think it would net us much improvements. The main bottleneck currently is during the Node client build phase. It has to build the Rust layer and Node, essentially building the full client. The C# checker only has to build the C# layer so it doesn't need valkey-glide submodule, and is a lot quicker. |
||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: 20 | ||
|
|
||
| - name: Install Rust toolchain | ||
| uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # stable | ||
| with: | ||
| toolchain: stable | ||
| targets: x86_64-unknown-linux-gnu | ||
|
|
||
| - name: Install protoc | ||
| uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3 | ||
| with: | ||
| version: "25.1" | ||
| repo-token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Install system dependencies | ||
| run: sudo apt-get update && sudo apt-get install -y pkg-config libssl-dev | ||
|
|
||
| - name: Build Node client | ||
| working-directory: valkey-glide/node | ||
| run: | | ||
| npm ci | ||
| npm run build:release | ||
|
Comment on lines
+48
to
+52
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the C# example, we are able to skip building the Rust core because it actually isn't needed to validate the examples syntax. Are there any similar optimizations that we could perform here? I know that building the Rust core can be quite slow. What about installing all of the node modules?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup this is currently the biggest bottleneck here. Updating this to match C# would require a code change on Node side although I haven't looked at the scope of this. |
||
|
|
||
| - name: Setup Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: "3.x" | ||
|
|
||
| - name: Validate Node examples | ||
| run: python scripts/validators/check-node-examples.py --glide-index valkey-glide/node/build-ts/index.d.ts | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # Example Validators | ||
|
|
||
| Compile the code examples in the docs against the real GLIDE client libraries, to catch broken syntax, wrong method names, and outdated APIs. | ||
|
|
||
| ## How they work | ||
|
|
||
| 1. Extract fenced code blocks (e.g. ` ```csharp `, ` ```typescript `) from the MDX docs. | ||
| 2. Wrap each snippet into a compilable file, injecting common imports/client declarations. | ||
| 3. Compile everything against a GLIDE client you've already built and point the script at. | ||
| 4. Report any compiler errors per source file/line. | ||
|
|
||
| `_common.py` holds the shared extraction logic used by every language-specific validator. | ||
|
|
||
| ## Usage | ||
|
|
||
| **C#** | ||
|
|
||
| You must build `Valkey.Glide.dll` yourself first — the script does not do this for you: | ||
|
|
||
| ```bash | ||
| cd <path_to_valkey-glide-csharp> && dotnet build sources/Valkey.Glide/ --configuration Release /p:SkipCargo=true | ||
| ``` | ||
|
|
||
| Then run the validator: | ||
|
|
||
| ```bash | ||
| python scripts/validators/check-csharp-examples.py \ | ||
| --validator <path_to_valkey-glide-csharp>/dev/scripts/validate_examples.py \ | ||
| --glide-dll <path_to_valkey-glide-csharp>/sources/Valkey.Glide/bin/Release/net8.0/Valkey.Glide.dll | ||
| ``` | ||
|
|
||
| **Node.js** | ||
|
|
||
| You must build the client yourself first — the script does not do this for you: | ||
|
|
||
| ```bash | ||
| cd <path_to_valkey-glide>/node && npm ci && npm run build:release | ||
| ``` | ||
|
|
||
| Then run the validator: | ||
|
|
||
| ```bash | ||
| python scripts/validators/check-node-examples.py --glide-index <path_to_valkey-glide>/node/build-ts/index.d.ts | ||
| ``` | ||
|
|
||
| Both scripts run automatically in CI on every PR (see `.github/workflows/check-csharp-examples.yml` and `.github/workflows/check-node-examples.yml`). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| """Shared helpers for the per-language example validators. | ||
|
|
||
| Every validator (C#, Node, and any future language) extracts fenced code | ||
| blocks from the MDX docs the same way — only the language tag(s) and the | ||
| files to skip differ. Centralizing that logic keeps future validators | ||
| consistent and makes it easy to fix bugs (e.g. in the extraction regex) | ||
| in one place. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import os | ||
| import re | ||
|
|
||
| # Repository root is two levels up from this script's directory | ||
| # (scripts/validators/). | ||
| REPO_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||
| DOCS_DIR = os.path.join(REPO_ROOT, "src", "content", "docs") | ||
|
|
||
|
|
||
| def extract_all( | ||
| languages: list[str], | ||
| *, | ||
| skip_patterns: list[str] | None = None, | ||
| ) -> dict[str, str]: | ||
| """Recursively walk the docs directory and extract fenced code blocks. | ||
|
|
||
| Args: | ||
| languages: Fence language tags to match, e.g. ``["csharp"]`` or | ||
| ``["typescript", "ts", "javascript", "js"]``. | ||
| skip_patterns: Regexes matched against the path of each MDX file | ||
| (relative to the docs directory). Any file matching one of | ||
| these patterns is skipped entirely. For example, Node skips | ||
| migration guides (``r"^migration"``) and IAM guides | ||
| (``r"iam-"``) because they reference APIs outside GLIDE. | ||
|
|
||
| Returns: | ||
| A dict mapping ``"<repo_relative_path>:<line_number>"`` to the | ||
| extracted code string. | ||
| """ | ||
| fence_re = re.compile( | ||
| r"^\s*```(?:" + "|".join(languages) + r")\s*\n(.*?)^\s*```\s*$", | ||
| re.MULTILINE | re.DOTALL, | ||
| ) | ||
| compiled_skips = [re.compile(p) for p in (skip_patterns or [])] | ||
|
|
||
| examples: dict[str, str] = {} | ||
| for root, _dirs, files in os.walk(DOCS_DIR): | ||
| for fname in sorted(files): | ||
| if not fname.endswith(".mdx"): | ||
| continue | ||
|
|
||
| filepath = os.path.join(root, fname) | ||
| rel_path = os.path.relpath(filepath, DOCS_DIR) | ||
| if any(skip.search(rel_path) for skip in compiled_skips): | ||
| continue | ||
|
|
||
| with open(filepath, encoding="utf-8") as fh: | ||
| content = fh.read() | ||
|
|
||
| for match in fence_re.finditer(content): | ||
| key_path = os.path.relpath(filepath, REPO_ROOT) | ||
| line_number = content[: match.start()].count("\n") + 1 | ||
| examples[f"{key_path}:{line_number}"] = match.group(1) | ||
|
|
||
| return examples |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
workflow_dispatchisn't included in the corresponding C# workflow. Should we add it for consistency?