Handle GitHub comment node encoding fragility - #121
Conversation
Reviewer's GuideAdds a robust fallback for resolving GitHub review comment threads by first attempting the existing GraphQL lookup and then falling back to the REST API if the base64 node encoding changes, accompanied by helper functions and updated documentation. Sequence diagram for robust GitHub comment thread resolutionsequenceDiagram
participant Client
participant GraphQL API
participant REST API
Client->>GraphQL API: Query thread using base64 node id
alt GraphQL lookup succeeds
GraphQL API-->>Client: Return thread id
else GraphQL lookup fails
Client->>REST API: Fetch comment node_id
REST API-->>Client: Return node_id
Client->>GraphQL API: Query thread using REST node_id
GraphQL API-->>Client: Return thread id
end
Class diagram for new and updated comment resolution helpersclassDiagram
class GraphQLClient {
+run_query(query: &str, variables: Value) : Result<Value, Error>
}
class RepoInfo {
+owner: String
+name: String
}
class VkError {
+RequestContext
+BadResponse
}
class CommentRef {
+comment_id: u64
+thread_id: Option<String>
}
class resolve_comment {
+resolve_comment(token: &str, reference: &CommentRef, reply: Option<&str>) : Result<(), VkError>
}
class thread_id_from_lookup {
+thread_id_from_lookup(lookup: &Value) : Option<&str>
}
class fetch_comment_node_id {
+fetch_comment_node_id(token: &str, repo: &RepoInfo, comment_id: u64) : Result<String, VkError>
}
resolve_comment --> GraphQLClient
resolve_comment --> thread_id_from_lookup
resolve_comment --> fetch_comment_node_id
fetch_comment_node_id --> RepoInfo
fetch_comment_node_id --> VkError
thread_id_from_lookup --> VkError
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. Summary by CodeRabbit
WalkthroughSummarise the resolve flow change: query GraphQL for a thread using a synthesised comment node ID; if that lookup fails and the feature flag Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User CLI
participant R as resolve_comment
participant GQL as GitHub GraphQL
participant REST as GitHub REST
U->>R: Resolve PR review comment
R->>GQL: Query thread by node id (base64 "PullRequestReviewComment:<id>")
alt Thread id returned
GQL-->>R: threadId
else Not found / GraphQL lookup empty/error
note right of R #FFDDAA: Feature gated fallback\n`unstable-rest-resolve` only
R->>REST: GET /repos/{owner}/{repo}/pulls/comments/{id}
REST-->>R: comment.node_id
R->>GQL: Re-query thread by comment.node_id
GQL-->>R: threadId
end
R->>GQL: Mutation RESOLVE_THREAD_MUTATION(threadId, optional message)
GQL-->>R: resolve response
R-->>U: Completed
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Pre-merge checks (3 passed)✅ Passed checks (3 passed)
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used📓 Path-based instructions (3)**/*.rs📄 CodeRabbit inference engine (AGENTS.md)
Files:
⚙️ CodeRabbit configuration file
Files:
docs/**/*.md📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.md📄 CodeRabbit inference engine (AGENTS.md)
Files:
⚙️ CodeRabbit configuration file
Files:
🧬 Code graph analysis (2)tests/resolve.rs (1)
src/resolve.rs (1)
🔇 Additional comments (6)
✨ Finishing touches
🧪 Generate unit tests
Comment |
|
@coderabbitai Have the following now been resolved?
|
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/resolve.rs (1)
168-171: Stabilise the public function signature across features.Avoid feature-dependent parameter lists on
resolve_comment; it complicates downstream usage and breaks API compatibility when the feature is toggled.Apply this diff:
-pub async fn resolve_comment( - token: &str, - reference: CommentRef<'_>, - #[cfg(feature = "unstable-rest-resolve")] message: Option<String>, -) -> Result<(), VkError> { +pub async fn resolve_comment( + token: &str, + reference: CommentRef<'_>, + message: Option<String>, +) -> Result<(), VkError> {And add a no-op binding when the feature is disabled:
@@ let comment_id = reference.comment_id; - #[cfg(feature = "unstable-rest-resolve")] + #[cfg(feature = "unstable-rest-resolve")] let (repo, pull_number) = (reference.repo, reference.pull_number); + #[cfg(not(feature = "unstable-rest-resolve"))] + let _ = message;
♻️ Duplicate comments (1)
docs/vk-design.md (1)
42-44: Spelling now conforms to en-GB-oxendict (-ize).‘synthesizing’ with -ize is correct. No further action.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
docs/vk-design.md(1 hunks)src/resolve.rs(4 hunks)tests/resolve.rs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")
- Use en-GB-oxendict (-ize / -our) spelling and grammar
- Headings must not be wrapped.
- Documents must start with a level 1 heading
- Headings must correctly increase or decrease by no more than one level at a time
- Use GitHub-flavoured Markdown style for footnotes and endnotes.
- Numbered footnotes must be numbered by order of appearance in the document.
Files:
docs/vk-design.md
**/*.rs
⚙️ CodeRabbit configuration file
**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.
Adhere to single responsibility and CQRS
Place function attributes after doc comments.
Do not use
returnin single-line functions.Move conditionals with >2 branches into a predicate function.
Avoid
unsafeunless absolutely necessary.Every module must begin with a
//!doc comment that explains the module's purpose and utility.Comments and docs must follow en-GB-oxendict (-ize / -our) spelling and grammar
Lints must not be silenced except as a last resort.
#[allow]is forbidden.- Only narrowly scoped
#[expect(lint, reason = "...")]is allowed.- No lint groups, no blanket or file-wide suppression.
- Include
FIXME:with link if a fix is expected.Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
Use
rstestfixtures for shared setup and to avoid repetition between tests.Replace duplicated tests with
#[rstest(...)]parameterised cases.Prefer
mockallfor mocks/stubs.Prefer
.expect()over.unwrap()Ensure that any API or behavioural changes are reflected in the documentation in
docs/Ensure that any completed roadmap steps are recorded in the appropriate roadmap in
docs/Files must not exceed 400 lines in length
- Large modules must be decomposed
- Long match statements or dispatch tables should be decomposed by domain and collocated with targets
- Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
- For testing of functionality depending upon environment variables, dependency injection and the
mockablecrate are the preferred option.- If mockable cannot be used, env mutations in tests ...
Files:
src/resolve.rstests/resolve.rs
🔍 Remote MCP Ref
Concise additional context for reviewing PR #121
-
docs/vk-design.md — Documents the new thread-id lookup approach: build/query the comment node (base64 "PullRequestReviewComment:"), and if that fails fall back to fetching the comment's node_id via REST (when feature enabled). Notes the REST path posts a reply before resolving and that GITHUB_TOKEN / abort-on-no-token behavior is unchanged.
-
src/resolve.rs — Key code changes:
- Adds thread_id_from_lookup helper and a fetch_comment_node_id REST function (GET /repos/{owner}/{repo}/pulls/comments/{id}) guarded by #[cfg(feature = "unstable-rest-resolve")]. The REST fetch checks resp.status().is_success() and returns explicit VkError on non-2xx.
- resolve_comment first attempts the GraphQL lookup; on missing/failing thread id it logs warn! and, if the feature is enabled, falls back to REST to obtain node_id then retries GraphQL.
- Conditional imports (log::warn, reqwest, etc.) are feature-gated.
- Public signature impact: resolve_comment gains an extra parameter message: Option behind the unstable-rest-resolve feature — i.e., the function's exported signature differs depending on the feature flag.
-
tests/resolve.rs — Adds async test resolve_falls_back_to_rest (gated by unstable-rest-resolve) that runs a MITM server and asserts the request sequence and behavior: POST /graphql (empty), GET /repos/o/r/pulls/comments/1 (REST node_id), POST /graphql (thread id), POST /graphql (resolve).
-
Cargo.toml — Defines the feature unstable-rest-resolve (empty feature).
Suggested review focus
- API compatibility: confirm the conditional change to resolve_comment's public signature is acceptable (crate consumers / semver implications).
- Feature gating: verify reqwest/log and the REST code are fully behind #[cfg(feature = "...")] and that building without the feature does not pull in reqwest.
- Tests & CI: ensure the new test is exercised in CI (or runs under the feature) and that docs match implemented behavior.
🔇 Additional comments (5)
tests/resolve.rs (1)
140-148: Validate expected fallback sequence.The asserted call order correctly demonstrates GraphQL → REST → GraphQL → GraphQL. Good coverage.
src/resolve.rs (4)
11-12: Gate logging import correctly.Feature-gate
log::warnto avoid pulling the dependency when the feature is disabled. Good.
203-210: Document node-id synthesis inline and keep it minimal.Lookup construction and initial query are correct and succinct. Good.
211-237: Log REST fallback entry points.Warnings on both error and “missing thread id” paths meet the observability requirement. Good.
238-245: Return structured error when REST is disabled.Non-feature path properly errors on missing thread id. Good.
Summary
Testing
make fmtmake lintmake testmake markdownlintmake nixiehttps://chatgpt.com/codex/tasks/task_e_68c06493d49c83228169762681f7aaa2
Summary by Sourcery
Improve robustness of pull request review thread resolution by falling back to GitHub’s REST API when GraphQL node encoding changes
Enhancements:
Documentation: