fix(issues): resolve names to node IDs in createIssue/updateIssue - #27
Open
netztaucher wants to merge 1 commit into
Open
Conversation
createIssue and updateIssue pass human-readable names into GraphQL ID fields, so every call is rejected by the API: Could not resolve to a node with the global id of 'priority:medium' Three fields are affected in the same mutation input: repositoryId: this.repo // repo name, not a node ID assigneeIds: data.assignees // logins, not node IDs labelIds: data.labels // label names, not node IDs Because ToolSchemas gives `priority` and `type` zod defaults and IssueService appends them as `priority:<x>` / `type:<y>` labels, even a call that passes no labels at all carries two — so create_issue fails unconditionally, for every repository. Adds three resolvers to BaseGitHubRepository, alongside the existing resolveIssueNodeId(): - resolveRepositoryNodeId() — cached, a repository's node ID is stable - resolveLabelIds() — not cached, labels change at runtime - resolveAssigneeIds() — not cached, collaborators change at runtime Names that do not exist are skipped with a warning rather than created: creating them would silently alter the repository's label taxonomy as a side effect of writing an issue. This also makes the synthetic priority:/type: labels harmless when the repo does not define them. In update(), an omitted field stays undefined instead of resolving to an empty array — [] means "remove all", undefined means "leave unchanged". Adds regression tests asserting the mutation input. The existing suite mocked `graphql` wholesale and never checked its arguments, which is why this went unnoticed; the new tests fail on the current code with `repositoryId: "test-repo"`. Fixes kunwarVivek#26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #26.
createIssueandupdateIssuepass human-readable names into GraphQLIDfields, so the API rejects the mutation:Three fields in the same input are affected:
Since
ToolSchemasgivespriorityandtypezod.default()s andIssueServiceappends them aspriority:<x>/type:<y>labels, even a call that passes no labels carries two — socreate_issuefails unconditionally, for every repository, and no argument combination avoids it.What this changes
Three resolvers on
BaseGitHubRepository, next to the existingresolveIssueNodeId():resolveRepositoryNodeId()resolveLabelIds()resolveAssigneeIds()create()resolves all three in parallel;update()resolves the two it needs.Unknown names are skipped with a warning, not created. Creating them would silently alter a repository's label taxonomy as a side effect of writing an issue. This also makes the synthetic
priority:/type:labels harmless in repos that don't define them.update()keepsundefineddistinct from[]— an empty array means "remove all",undefinedmeans "leave unchanged", so an omitted field must not be resolved into[].Tests
Two regression tests asserting the mutation input. They fail on
main:The existing suite mocked
graphql: jest.fn()and never inspected its arguments, which is why this was invisible. The new tests route the mock by query name so the assertions can look at what actually reachescreateIssue.npm run buildis clean.Verified end-to-end
Built from this branch and driven over stdio against a real repository:
create_issue→Could not resolve to a node with the global id of '<repo>'backlog+docapplied, a deliberately bogus label skipped withSkipping labels that do not exist in <owner>/<repo>: …Deliberately left alone
The
priority:/type:label injection inIssueService.createIssue()(and itszoddefaults) still happens — with this fix it is merely skipped when the labels don't exist. It's a separate design question: those look like project-board field values rather than labels, and today they cannot be turned off (z.enumrejects""). Happy to follow up in a second PR whichever way you prefer — drop the injection, or remove the.default()s so it becomes opt-in.One related bug is also still open, same class:
data.labels || []returns the caller's array and is then mutated with.push. Left out to keep this diff focused.