Skip to content

fix: plugin install --from-config doesn't detect a changed pinned source - #2512

Open
tyrcho wants to merge 1 commit into
jackyzha0:v5from
tyrcho:fix/reinstall-changed-plugin-source
Open

tyrcho wants to merge 1 commit into
jackyzha0:v5from
tyrcho:fix/reinstall-changed-plugin-source

Conversation

@tyrcho

@tyrcho tyrcho commented Jul 30, 2026

Copy link
Copy Markdown

Fixes

plugin install --from-config silently keeps a stale plugin when its pinned source changes

Goal

Bumping a plugin's pinned source in quartz.config.yaml (e.g. switching a fork branch, or repointing at a different fork/ref) should always be picked up the next time npx quartz plugin install --from-config runs, whether that's a fresh checkout or a reused .quartz/plugins/ directory (a persistent CI cache, or a local dev machine that already had the old version installed).

Problem

handlePluginInstallUnified()'s "is this plugin already installed" check only verified that quartz.lock.json had an entry for the plugin's name and that its directory existed on disk — it never compared that entry's recorded source against the plugin's current source in quartz.config.yaml. So whenever the old directory and lockfile record were still present, the plugin was treated as up to date and never re-cloned, regardless of what the config now said.

This is easy to miss with the tool's own default workflow (delete .quartz/ or start from a fresh checkout, so there's no stale state to miss in the first place), but it bites as soon as .quartz/plugins/ is reused across runs — most notably a CI cache keyed on something coarser than every individual plugin's source, or repeated local runs of plugin install --from-config after editing the config.

It's also worse than a silent no-op: the existing-directory fast path re-stamps the lockfile's source field to the new value while leaving commit pointing at whatever was actually still checked out — producing a lockfile entry that claims to be on the new ref while actually still serving the old one.

Implementation

  • quartz/cli/plugin-git-handlers.js: extracted the comparison into a small pure pluginSourceChanged(priorEntry, currentSource) helper, used in both:

    • the "is this plugin missing" filter that decides what needs installing, and
    • the existing-directory fast path, which now removes the stale directory and falls through to a normal (re)install instead of just re-stamping the lockfile.

    An unrelated pre-existing directory with no prior lockfile record at all (e.g. first-ever install onto an already-populated .quartz/plugins/) is left alone, matching the previous behavior for that case.

  • quartz/cli/plugin-git-handlers.test.js (new): covers pluginSourceChanged — no prior record, unchanged source, changed ref, changed repo.

Verified: npm test (167 tests passing) and npm run check (tsc --noEmit + prettier --check) both clean.

handlePluginInstallUnified()'s "already installed" check only verified
that quartz.lock.json had an entry for the plugin's name and that its
directory existed — it never compared the entry's recorded `source`
against the plugin's current source in quartz.config.yaml. So bumping
a plugin's pinned ref (e.g. switching a fork branch, or repointing at
a different fork) was silently ignored whenever the old directory and
lockfile record were still present: the plugin was treated as
up to date and never re-cloned.

This mattered most whenever `.quartz/plugins/` gets reused across
runs instead of rebuilt from scratch — a persistent CI cache, or a
local dev machine re-running `plugin install --from-config` after
editing quartz.config.yaml — since a fresh checkout has no stale
state to miss in the first place. Worse, the existing-directory fast
path re-stamped the lockfile's `source` field to the new value while
leaving `commit` pointing at whatever was actually checked out,
producing a lockfile entry that claimed to be on the new ref while
still serving the old one.

Fixed by extracting the comparison into `pluginSourceChanged()` and
using it in both the "is this missing" filter and the existing-
directory handling: a source mismatch now removes the stale directory
and lets the normal clone path reinstall it, while an unrelated
pre-existing directory (no prior lockfile record at all) is left
alone as before.

Verified: added quartz/cli/plugin-git-handlers.test.js covering the
new helper, `npm test` (167 tests passing) and `npm run check`
(tsc + prettier) both clean.
@github-actions

github-actions Bot commented Jul 30, 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 f933fed

This branch was successfully deployed

1 active deployment
Branch Preview — f933fedc Deployed Jul 30, 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.

1 participant