Skip to content

fix(gl): point doctor's version check at Gitlawb/node, not the frozen Gitlawb/releases repo#198

Open
euxaristia wants to merge 4 commits into
Gitlawb:mainfrom
euxaristia:fix/gl-doctor-release-repo
Open

fix(gl): point doctor's version check at Gitlawb/node, not the frozen Gitlawb/releases repo#198
euxaristia wants to merge 4 commits into
Gitlawb:mainfrom
euxaristia:fix/gl-doctor-release-repo

Conversation

@euxaristia

@euxaristia euxaristia commented Jul 14, 2026

Copy link
Copy Markdown

Summary

check_version in crates/gl/src/doctor.rs queries gitlawb/releases/releases/latest. Gitlawb/releases is a separate repo that stopped receiving tags after v0.3.8 (2026-03-30). Releases have shipped directly on Gitlawb/node since v0.4.0, via release-please, and install.sh already treats Gitlawb/node as the canonical release source (REPO="${GITLAWB_RELEASE_REPO:-Gitlawb/node}"). The old query target meant the version check could never again detect a real update once past v0.3.8.

Closes #197

What changed

  • check_version now queries Gitlawb/node's releases endpoint instead of gitlawb/releases.
  • The GitHub API base is now a parameter (github_api_base), so the fix can be covered by a test against a mocked server instead of hitting the real GitHub API.
  • Two new tests: one asserting a warning fires when a newer tag is returned, one asserting "up to date" when the tag matches current.

How a reviewer can verify

cargo test -p gl doctor
cargo fmt --all -- --check
cargo clippy -p gl --all-targets -- -D warnings

Kind of change

  • Bug fix
  • Feature
  • Security fix
  • Docs
  • Tests / CI
  • Refactor (no behavior change)
  • Breaking or protocol change

Summary by CodeRabbit

  • Bug Fixes
    • Improved gl doctor version checks by retrieving release information from the correct project endpoint.
    • Added support for configurable API endpoints, improving reliability in environments that use alternate GitHub API URLs.

… Gitlawb/releases repo

check_version queried https://api.github.com/repos/gitlawb/releases/releases/latest.
Gitlawb/releases is a separate repo that stopped receiving tags after v0.3.8
(2026-03-30). Releases have shipped directly on Gitlawb/node since v0.4.0, via
release-please, and install.sh already treats Gitlawb/node as the canonical
release source. The old query target meant gl doctor's version check could
never again detect a real update.

Points the check at Gitlawb/node instead, matching install.sh's own default,
and makes the GitHub API base injectable so the fix is covered by a test
against a mocked server rather than the real GitHub API.

Closes Gitlawb#197
@github-actions github-actions Bot added the needs-tests Source changed without accompanying tests (advisory) label Jul 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution. A couple of things will help us review this faster:

  • This changes Rust source but no tests changed. Tests are required for fixes and strongly encouraged for features.

See CONTRIBUTING.md. Update the PR and these notes will clear automatically.

@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@euxaristia, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71026183-8ca4-49d9-8760-adb1acfa0c36

📥 Commits

Reviewing files that changed from the base of the PR and between 32a7ff0 and a46f891.

📒 Files selected for processing (1)
  • crates/gl/src/doctor.rs
📝 Walkthrough

Walkthrough

The gl doctor version check now queries the Gitlawb/node latest release through a configurable GitHub API base URL, with tests covering mocked endpoint responses and version-status outcomes.

Changes

Doctor version check

Layer / File(s) Summary
Release endpoint and version-check wiring
crates/gl/src/doctor.rs
Adds the default GitHub API base, passes it into check_version, and targets the Gitlawb/node latest release endpoint.
Mocked release endpoint validation
crates/gl/src/doctor.rs
Updates async tests to use the new endpoint and validate warning and up-to-date states.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: kevincodex1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR matches issue #197 by pointing gl doctor at Gitlawb/node and adding tests for the updated release endpoint.
Out of Scope Changes check ✅ Passed The changes stay focused on the version-check fix and its tests, with no clear unrelated churn.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title clearly and concisely summarizes the main change: redirecting the version check to Gitlawb/node.
Description check ✅ Passed The description covers the required summary, what changed, verification steps, and kind of change, with only minor template details left implicit.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
crates/gl/src/doctor.rs (1)

336-338: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider checking the HTTP status before parsing the response body.

If GitHub rate-limits the IP, it returns a 403 status with a JSON error payload. The current code parses the error JSON, finds tag_name missing, and defaults to (could not parse latest tag). Explicitly checking resp.status().is_success() before parsing would allow for a more accurate diagnostic message when the API rate-limits the request or fails.

♻️ Proposed refactor
     let resp = match client
         .get(format!(
             "{github_api_base}/repos/Gitlawb/node/releases/latest"
         ))
         .send()
         .await
     {
         Ok(r) => r,
         Err(_) => return Check::pass("version", format!("v{current} (offline — could not check)")),
     };
+
+    if !resp.status().is_success() {
+        return Check::pass("version", format!("v{current} (API returned HTTP {})", resp.status()));
+    }
 
     let body: serde_json::Value = match resp.json().await {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/gl/src/doctor.rs` around lines 336 - 338, Update the GitHub release
request flow in the surrounding doctor logic to check resp.status().is_success()
before parsing the response body. For non-success responses, return or report a
diagnostic that includes the HTTP failure status, while preserving the existing
tag parsing behavior for successful responses.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/gl/src/doctor.rs`:
- Around line 441-454: Strengthen test_check_version_up_to_date by asserting the
returned check’s expected detail/message in addition to CheckState::Ok. Use the
existing detail field or accessor on the check and verify it contains the
up-to-date version information, ensuring the mocked successful response was
actually processed.

---

Nitpick comments:
In `@crates/gl/src/doctor.rs`:
- Around line 336-338: Update the GitHub release request flow in the surrounding
doctor logic to check resp.status().is_success() before parsing the response
body. For non-success responses, return or report a diagnostic that includes the
HTTP failure status, while preserving the existing tag parsing behavior for
successful responses.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 86b29b3a-1ecc-47a4-b1b4-b05e1aa05ea3

📥 Commits

Reviewing files that changed from the base of the PR and between ad7c2b2 and 32a7ff0.

📒 Files selected for processing (1)
  • crates/gl/src/doctor.rs

Comment thread crates/gl/src/doctor.rs
@euxaristia

Copy link
Copy Markdown
Author

Re: the needs-tests note — this PR does add tests, in the same commit and file. `test_check_version_queries_gitlawb_node_releases` and `test_check_version_up_to_date` are both in `crates/gl/src/doctor.rs`'s existing `mod tests` block, covering the warn and up-to-date branches of `check_version` against a mocked GitHub API.

The triage workflow's test-detection regex (`.github/workflows/pr-triage.yml:73-75`) only matches `#[test]` or `#[cfg(test)` literally. Both new tests use `#[tokio::test]`, since `check_version` is async, which doesn't match either alternative. That looks like a gap in the regex rather than anything about this PR: it would false-flag any PR whose only new tests are async (`#[tokio::test]`, `#[async_std::test]`, etc.), which given this codebase already uses `#[tokio::test]` throughout is probably worth a follow-up fix on its own.

…gthen up-to-date test

Addresses CodeRabbit review on Gitlawb#198:
- check_version now checks resp.status().is_success() before parsing the body,
  so a GitHub rate-limit or other API error surfaces as its actual HTTP status
  instead of a generic "could not parse latest tag".
- test_check_version_up_to_date now also asserts the detail message, so the
  test can't silently pass on an unmatched mock request (mockito's fallback for
  an unhandled request is a 501, which check_version also maps to Ok).
@euxaristia

Copy link
Copy Markdown
Author

Pushed a fixup addressing both CodeRabbit comments:

  • `check_version` now checks `resp.status().is_success()` before parsing the body, so a rate-limit (403) or other API error reports its actual HTTP status instead of falling through to the generic "could not parse latest tag".
  • `test_check_version_up_to_date` now also asserts `check.detail.contains("up to date")`, so the test can't silently pass if the mock is never hit (mockito's unmatched-request fallback is a 501, which `check_version` also maps to `Ok`, so the state-only assertion wasn't proving the mock was exercised).

`cargo test -p gl doctor`, `cargo fmt --check`, and `cargo clippy -D warnings` all still clean.

@beardthelion beardthelion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verified by execution: reverting just the production URL (leaving the mocks) turns both new tests red, so they're genuinely pinned to the fix, and the retarget to Gitlawb/node matches the GITLAWB_RELEASE_REPO default in install.sh/install.ps1. The core change is correct. One thing to add before merge.

Findings

  • [P2] Add a test for the new non-2xx branch
    crates/gl/src/doctor.rs:346
    The if !resp.status().is_success() guard is the branch the fixup was written for (the 403 rate-limit case), but it has no test. Disabling the whole block leaves all 9 tests green, so nothing currently drives the error response class, only the 200 path. This is the adversarial gap that matters on a diff whose second half exists specifically to handle non-2xx.

    A with_status(403) mock closes it (I ran this against the branch; it passes):

    #[tokio::test]
    async fn test_check_version_http_error() {
        let mut server = mockito::Server::new_async().await;
        let _m = server
            .mock("GET", "/repos/Gitlawb/node/releases/latest")
            .with_status(403)
            .create_async()
            .await;
    
        let check = check_version("0.1.0", &server.url()).await;
        assert!(matches!(check.state, CheckState::Ok));
        assert!(check.detail.contains("403"));
    }

    Assert both the Ok state and contains("403") — a state-only check would still pass if a regression dropped the status into the JSON-parse path instead.

The retarget itself is sound and the two added tests are load-bearing, so this is the only blocker. The is_newer numeric-only parse (pre-release / 4-part tags) is pre-existing and unchanged here, out of scope for this PR.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I found issues that need to be addressed before this is ready.

Findings

  • [P2] Remove the extra blank line at EOF
    crates/gl/src/doctor.rs:478
    The added terminal blank line makes cargo fmt --all -- --check fail; the repository's fmt + clippy workflow runs that command as a required formatting gate. The current head therefore cannot pass CI until this line is removed.

cargo fmt --all -- --check fails on the extra terminal blank line, and the
fmt + clippy workflow runs that check as a required gate.
@euxaristia

Copy link
Copy Markdown
Author

Pushed a fixup addressing jatmn's finding: removed the trailing blank line at EOF in doctor.rs. cargo fmt --all -- --check now passes clean, and all 10 doctor tests still pass.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@beardthelion
beardthelion dismissed their stale review July 15, 2026 20:21

Dismissing my stale CHANGES_REQUESTED — it was on 67d52be, before the contributor added the non-2xx test and removed the EOF blank line. Re-reviewed the current head; approving separately.

@beardthelion beardthelion left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Both blockers are closed. test_check_version_http_error is load-bearing: I removed the if !resp.status().is_success() block and it goes red (panic at the 403-detail assertion) while the other 9 doctor tests stay green, then restored to 10/10. That pins the exact non-2xx branch the fixup was written for. The EOF blank line is gone and fmt + clippy is green.

The rest still holds from my last pass: the two URL tests remain load-bearing (reverting the retarget turns both red), and the retarget itself matches the canonical release source (install.sh and install.ps1 both default GITLAWB_RELEASE_REPO to Gitlawb/node). I traced the full response-class matrix on the current head, offline / 3xx / 4xx / 5xx / 2xx-non-JSON / 2xx-without-tag / 2xx-newer / 2xx-up-to-date, and every branch returns a truthful detail string with the status guard correctly ahead of the JSON parse. The injected base URL is test-only; the sole production caller passes the const. LGTM.

One non-blocking note for later, not this PR: now that the URL actually resolves, is_newer's numeric-only parse (splitn(3, '.')) starts seeing real tags, so a pre-release or 4-part tag (v1.2.3-rc1, v1.2.3.4) would compare imperfectly. It degrades gracefully (no panic), it's pre-existing, and it's out of scope here, worth a follow-up if release tags ever take that shape.

@kevincodex1 approved and ready to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crate:gl gl — the contributor CLI kind:bug Defect fix — wrong or unsafe behavior needs-tests Source changed without accompanying tests (advisory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gl doctor checks the wrong/stale release repo for version updates

3 participants