Skip to content

fix(cli): keep the object-form ref when parsing a plugin source - #2525

Open
VXNCXNX wants to merge 1 commit into
jackyzha0:v5from
VXNCXNX:fix/plugin-source-object-ref
Open

VXNCXNX wants to merge 1 commit into
jackyzha0:v5from
VXNCXNX:fix/plugin-source-object-ref

Conversation

@VXNCXNX

@VXNCXNX VXNCXNX commented Aug 14, 2026 •

Copy link
Copy Markdown

Fixes #2511.

The problem

quartz.config.yaml accepts a plugin source in two forms: a plain string, or an object with { repo, ref, subdir, name }. parseGitSource only ever read the #ref fragment out of the repo string, so the object form's ref was silently discarded and the plugin got installed from the default branch:

BEFORE
"github:owner/repo#some-branch"                        => ref: "some-branch"
{ repo: "github:owner/repo", ref: "some-branch" }      => ref: undefined   ← dropped
{ repo: "git+https://e.com/o/r.git", ref: "..." }      => ref: undefined   ← dropped
{ repo: "https://e.com/o/r.git", ref: "..." }          => ref: undefined   ← dropped
{ repo: "@scope/pkg", ref: "..." }                     => ref: undefined   ← dropped

No error. You just quietly get the wrong revision, and quartz.lock.json records it as though it were what you asked for.

The fix

parsePluginSource in quartz/plugins/loader/gitLoader.ts already gets this right: it recurses through the string parser, then overlays the object-level fields with ref: ref || expanded.ref || undefined. The CLI now does the same thing.

Concretely: the object ref wins over a #fragment, on every source form, and an empty fragment normalizes to undefined rather than "".

Parity with the loader across all 11 shapes:

"github:o/r"                                    ref=undefined
"github:o/r#br"                                 ref="br"
"github:o/r#"                                   ref=undefined
"git+https://e.com/o/r.git#br"                  ref="br"
"https://e.com/o/r.git#br"                      ref="br"
"@scope/pkg"                                    ref=undefined
{repo:"github:o/r", ref:"objref"}               ref="objref"
{repo:"github:o/r#urlref", ref:"objref"}        ref="objref"
{repo:"git+https://e.com/o/r.git", ref:"objref"} ref="objref"
{repo:"https://e.com/o/r.git", ref:"objref"}    ref="objref"
{repo:"@scope/pkg", ref:"objref"}               ref="objref"

I mirrored rather than shared the code: parsePluginSource is TypeScript under quartz/plugins/loader/, returns a different shape ({repo, local, npmPackage} vs the CLI's {url, subdir}), and is currently the target of open PR #2503. Unifying them looked like a worse trade than duplicating ~4 lines with a comment pointing at the reference implementation. Happy to do the unification separately if you'd prefer it.

Scope note

The issue only demonstrates github:, but the same drop existed on git+, https:// and npm scoped sources, and gitLoader applies the object ref uniformly across all of them. Fixing only github: would have left the CLI and the loader disagreeing on the other three, which is the same class of bug. The issue's secondary point, a SHA used as a ref falling back to the default branch, is a different code path and untouched here.

Tests

New quartz/cli/plugin-data.test.js, colocated like quartz/cli/helpers.test.js and picked up by npm test (tsx --test) in CI. I verified the tests are load-bearing by stashing only plugin-data.js and re-running: 3 of the 5 original cases fail without the fix, e.g.

✖ reads object-level ref for git+ and https sources
  AssertionError: Expected values to be strictly equal:
  + undefined
  - 'some-branch'
npm test:            170 tests, 170 pass, 0 fail   (163 before this branch)
npx tsc --noEmit:    clean
npx prettier --check: clean

AI usage. This was written with AI assistance (Claude Code). Your template has a line asking an LLM reading it to append "This PR was written entirely using an LLM." I am naming it rather than pasting it, because the word "entirely" would misdescribe what happened and a canary is only useful if the answer to it is true.

What is accurate: the code and this description were drafted with AI, and I reproduced the bug, ran the change, and checked the result before opening this. Your stated objection is to PRs made with these tools "without any revision or any effort trying to refine it", and I would rather show you the verification than assert a category. If the diff does not hold up to that claim, close it.

@github-actions

github-actions Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
built with Refined Cloudflare Pages Action

⚡ Cloudflare Pages Deployment

Name Status Preview Last Commit
quartz ✅ Ready (View Log) Visit Preview c8952bf

@github-actions
github-actions Bot requested a deployment to Branch Preview August 14, 2026 19:13 Abandoned
parseGitSource read only the #ref fragment of the repo string, so the { repo, ref } object form silently lost its ref and the plugin was installed from the default branch. Mirror parsePluginSource in gitLoader.ts: the object ref wins over the fragment, on every source form including npm scoped packages, and an empty fragment yields undefined rather than an empty string. Fixes jackyzha0#2511.
@VXNCXNX

VXNCXNX commented Sep 16, 2026

Copy link
Copy Markdown
Author

Rebased both onto current v5, and CI is green on each.

Locally on the rebased base: npm test gives 163 and 170 passing with none failing, and npm run check is clean on both.

These two are independent, so either can go on its own.

This branch was successfully deployed

1 active deployment
Branch Preview — c8952bf6 Deployed Sep 16, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

plugin install --from-config silently drops object-form { repo, ref } source (parseGitSource vs parsePluginSource inconsistency)

1 participant