Repository navigation
fix(projects): send the server's allowlisted Projects query again - #79
Merged
Merged
Conversation
#57 trimmed projects.gql, and JuliaHub answers only allowlisted GraphQL documents, so since v0.4.3 every `jh project list` gets "query is not allowed". Restore the allowlisted text (JuliaHub's graphqlsrvr/external-queries/juliasim-projects.gql); its $limit, $offset, $orderBy and $filter already carry #57's paging and server-side filter. The e2e suite skipped on "not allowed", which hid this on both nightly installs. A disallowed query is a CLI defect, so it now fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
krynju
marked this pull request as ready for review
November 2, 2026 11:05
Review round 1: - JuliaSim's allowlisted document selects `resources`, which costs the server ~1.2 s per row: an admin's 20-row page took 24 s and a 100-row page hit the 60 s gateway timeout on nightly. The web UI's Projects document is allowlisted too and answers a 100-row page in 0.5 s, so send that one. - `jh clone` kept its own hand-pasted copy of the query and sent it with only ownerId (no limit, no filter). It now goes through fetchProjectsPage with a server-side owner/name filter, and the copy and its HTTP client are gone. - e2e: one disallowedQuery helper; backendGap no longer turns a disallowed document into a skip either. Docs updated. - Unit tests pin projects.gql's normalized text and cover the lookup filter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2: - The web UI's Projects document is allowlisted only from JuliaHub 26.4 (checked with graphqlsrvr's allowlist Lookup against release-26.3/26.4/ 26.5 and master). Send it first and, when a server answers "query is not allowed", JuliaSim's document, which every release allowlists. Any other error does not fall back. - clone: an exact case-insensitive match wins; otherwise a single server-side ILIKE match is used (Postgres and Go fold non-ASCII case differently). One getUserInfo per clone instead of two. - ownerUsernameFilter is shared by `project list --user` and clone. - The hash test is renamed to what it is, a change detector for both documents; the fallback order and pickProject have unit tests. - e2e docs say the package GraphQL fallback isn't allowlisted, so those tests fail if REST is down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l back on validation-failed Review round 3: - JuliaSim's document costs ~1.2 s per row, so a 100-row page in one request runs past the 30 s client timeout. The fallback now fetches the same page in ten 10-row requests (about 12 s each for an admin on nightly-sized data) and stops at a short chunk. - A pre-26.4 server running without an allowlist (dev mode) accepts the web UI document and then fails on its 26.4-only fields with validation-failed; fall back then too. - e2e: the `jh package` GraphQL fallback is allowlisted up to 26.3 and not from 26.4, so a failed REST call there ends in "query is not allowed". skipIfPackageFallbackDisallowed skips that known dead fallback by name in the package and package-search tests; README corrected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…im's Every JuliaHub release from 25.7 allowlists exactly one of two versions of the web UI's Projects document: the current one (26.4 on) or the one without `editing_mode` / `requires_publish_request` (25.7–26.3). Checked with graphqlsrvr's allowlist Lookup against every release branch's metadata. Neither selects JuliaSim's `resources` (~1 s per row), so the fallback is as fast as the first try and the 10-row chunking goes away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…xact clone matches
- When both Projects documents fail, report both errors, not only the
fallback's "query is not allowed".
- GraphQL errors print as before ("GraphQL errors: [{message}]"), without
the extension code.
- pickProject prefers an exact owner/name match over a case-insensitive one.
- TestPackageSearchVerbose skips on the dead package GraphQL fallback like
the other package tests.
- Fallback tests check which documents were sent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s, drop the lone-row clone pick - documentRejected matches "query is not allowed" or a `validation-failed` "field ... not found in type", not every validation error, so other errors on 26.4+ are reported as they are instead of after a doomed fallback. - pickProject no longer accepts a single row that matches neither exactly nor case-insensitively; such a row is not the requested project. - skipIfPackageUnsupported replaces the copy-pasted skip pair in the package and search tests, and runVerbose uses it for `search packages` too. - e2e/README says the suite targets JuliaHub 25.10+, where jh's Groups and Users documents are allowlisted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…project fields - pickProject returns an error naming the candidates when several projects match case-insensitively and none exactly, instead of cloning the newest. - documentRejected matches only "not found in type: 'projects'", so a filter validation error (projects_bool_exp) is reported once, without a fallback. - runVerbose calls skipIfUnsupported once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`jh clone` on main sent JuliaSim's Projects document, which 6.7 and 6.8 allowlist and neither web UI document is on. The lookup now tries the web UI documents and then JuliaSim's, with the owner/name filter and a 10-row limit, so its `resources` cost stays at a row or two. Project listings never use it. - One fetchProjectsWith walks a document list; listDocuments and lookupDocuments define the order. Every rejection is reported. - "query is not allowed" is matched case-insensitively as a substring. - TestCloneNotFound runs the clone lookup against the live server. - runVerboseSkipping takes the skip helper instead of matching argv. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…error
- pickProject: an exactly typed project name wins whatever the owner's case
(names are unique per owner); usernames always compare case-insensitively.
- When several Projects documents fail, each error names its document.
- TestCloneNotFound requires pickProject's own "not found" message, so a
server validation error ("... not found in type ...") can't pass it.
- graphQLExecutor replaces two copies of the transport closure.
- CLAUDE.md lists the new embedded documents and the request count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- When every document is rejected, the error says so before listing them, instead of only stacking "query is not allowed" errors. - lookupDocuments is a plain literal; fetchProjectsWith keeps only the first error and the messages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pankgeorg
approved these changes
Nov 3, 2026
pankgeorg
left a comment
Member
There was a problem hiding this comment.
Can we add an integration test as part of the JuliaHub release tests?
Member
Author
we have jh running as part of nightly, that's how i caught it |
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.
jh project listhas failed on every JuliaHub instance since v0.4.3:Why
JuliaHub answers only allowlisted GraphQL documents. Before #57 the CLI sent JuliaSim's allowlisted Projects document. #57 added paging and a server-side filter, and along the way trimmed fields from
projects.gql. The trimmed text matches no allowlisted document, so every instance rejects it. Hasura did the same before graphqlsrvr replaced it.#57 trimmed the fields for a good reason: JuliaSim's document selects
resources, which is expensive. It's still expensive on graphqlsrvr. Timed as admin on nightly.juliahub.dev (61k projects):juliasim-projects.gql)frontend/src/components/Projects/queries/projects.gql)So the CLI now sends the web UI's Projects document for listings. Only two versions of it exist on release branches from 6.9 on, and each of those releases allowlists exactly one.
jh clonelooks up a single owner/name, so it can afford JuliaSim's document as a last resort: that reaches 6.7 and 6.8, wherejh cloneworked before this PR. Checked with graphqlsrvr's allowlistLookupagainst each release's metadata:projects.gql(26.4+ web UI)projects_pre264.gql(6.9–26.3 web UI)projects_juliasim.gql(clone only)The CLI sends
projects.gqland, when a server rejects it,projects_pre264.gql. "Rejects" meansquery is not allowed, or avalidation-failed"field ... not found in type: 'projects'" from a pre-26.4 server running without an allowlist, whose schema lacks the 26.4 fields. Any other error is returned as it is. If every document is rejected, all the errors are reported. Neither web UI version selectsresources, so a listing's fallback is as fast as the first try. Listings never use JuliaSim's document. On 6.7/6.8jh project liststays unsupported, as it was before this PR. The clone lookup sends JuliaSim's document only after both web UI documents are rejected. It sends it with the owner/name filter and a 10-row limit, which keeps theresourcescost to a row or two.What changed
projects.gqlandprojects_pre264.gqlare the two versions of the web UI's Projects document (listDocuments).lookupDocumentsaddsprojects_juliasim.gql, which has the same text asgraphqlsrvr/external-queries/juliasim-projects.gql. OnefetchProjectsWithtries a list in order. Thego:embedcomment andCLAUDE.mdsay the files must stay the server's text, and why listings never use JuliaSim's.jh clone owner/namehad its own hand-pasted copy of the query, sent with onlyownerId: no limit and no filter. graphqlsrvr caps that at 1000 rows, so on a big install the target could be missing from the page. It now goes throughlookupDocumentswith a server-side owner/name filter (projectLookupFilter, literal and case-insensitive, sharingownerUsernameFilterwithproject list --user). An exact match wins, then the only case-insensitive one. Several case-variant matches without an exact one are reported as ambiguous, and a row that matches neither is not picked. The copy, its separate HTTP client and a secondgetUserInforound trip are gone.skipIfUnsupportedandbackendGaptreated "not allowed" as a backend gap and skipped. That's whyTestProjectListandTestProjectListByUserskipped on both nightly installs instead of failing. A disallowed document is a CLI defect, so a singledisallowedQueryhelper now makes it fail in both.TestCloneNotFoundruns the clone lookup against the live server and expects "not found". The README and the package test header say so, and that the suite targets JuliaHub 25.10+, where the allowlist carries the CLI's current Groups and Users documents.TestProjectsDocumentsUnchangedpins all three documents' normalized text and rejectsresourcesin the listing documents. It is a change detector only, because this repo can't see the server's allowlist.TestFetchProjectsPage*tests cover the fallback: the 26.4+ document first; fall back onquery is not allowedor a missing project field only (not on filter validation errors); which documents were sent; and that both errors are kept when neither is accepted.TestLookupProjects*cover the clone lookup's JuliaSim fallback and its 10-row limit.TestPickProjectandTestProjectLookupFiltercover choosing the row.Evidence
graphqlsrvr/internal/allowlistLookupon master and every release from 6.7 (table above). v0.4.3's text matches nothing anywhere.projects_pre264.gqlis byte-identical torelease-26.3's web UI file.go vet ./...,go test ./...andgo test -tags e2e -c ./e2epass.Not in this PR
package_search.gql/package_search_count.gqlare allowlisted up to 26.3 but not from 26.4. Package search uses REST first, so only the GraphQL fallback is dead on newer servers. The e2e package andsearch packagestests skip that case by name (skipIfPackageUnsupported) instead of failing, and the README says so.jh-projects.gqltographqlsrvr/external-queries/, with the same text asprojects.gql. That keeps the 26.4+ document allowlisted when the web UI's file changes, the wayjh-users.gqlandjh-groups.gqlalready work.🤖 Generated with Claude Code