diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 782d5d0..8ae2f97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,9 +27,11 @@ bb plugin dev plugins/thread-badges # rebuild + reload on every save npm run release -- thread-badges # this checkout -> the released tag ``` -`link all` and `release all` take every plugin at once. `npm run bb -- reload -` is a one-shot build and reload for when you are not leaving the watcher -running. +`release` follows the newest tag, so `bb plugin update` keeps tracking it, and +refuses — before removing anything — when the checkout's version has no tag +yet. `link all` and `release all` take every plugin at once. `npm run bb -- +reload ` is a one-shot build and reload for when you are not leaving the +watcher running. What removal does *not* touch is the plugin's data directory under `~/.bb/plugins//`, so recorded follow-ups and the stage catalog survive a @@ -100,8 +102,10 @@ Bump the version in the plugin's `package.json` in the same commit, and update its `PLUGIN_OVERVIEW.md` whenever `bb.description` or a surface changes — the store shows the two together and they must not disagree. -A README's install snippet needs no attention: it names `@semver:*`, which -resolves to the newest tag under that plugin's prefix. Do not put a version in -one. Every snippet that named a range went stale, and a caret range on a `0.x` -version goes stale on the very next release — `^0.1.0` cannot reach `0.2.0` at -all, so readers were installing a plugin two minor versions behind. +A README's install snippet needs no attention: it names the bare range `@*`, +which `--tag-prefix` resolves to the newest tag under that plugin's prefix. +Don't spell it `@semver:*` — bb rejects an explicit `semver:` spec alongside +`--tag-prefix`. Do not put a version in one either. Every snippet that named a +range went stale, and a caret range on a `0.x` version goes stale on the very +next release — `^0.1.0` cannot reach `0.2.0` at all, so readers were installing +a plugin two minor versions behind. diff --git a/README.md b/README.md index fd0a483..29ea35c 100644 --- a/README.md +++ b/README.md @@ -20,21 +20,21 @@ is installed, and Workflow Stages needs One at a time, by subdirectory: ```sh -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/follow-up --tag-prefix follow-up/ -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/thread-badges --tag-prefix thread-badges/ -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/top-tabs --tag-prefix top-tabs/ -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/workflow-stages --tag-prefix workflow-stages/ ``` -Each plugin is released under its own tag prefix, so `semver:*` resolves to the -newest release of that plugin alone and these lines never go stale. A caret +Each plugin is released under its own tag prefix, so the range `*` resolves to +the newest release of that plugin alone and these lines never go stale. A caret range would: on a `0.x` version `^0.1.0` cannot reach `0.2.0` at all, which is how this page came to offer a plugin two minor versions behind. `--plugin ` works instead of `--subdirectory` — the repository carries a diff --git a/plugins/follow-up/README.md b/plugins/follow-up/README.md index 2d5a219..b4f7a5b 100644 --- a/plugins/follow-up/README.md +++ b/plugins/follow-up/README.md @@ -12,12 +12,13 @@ nothing to run — no model to choose, no cooldown, no polling, no inflight lock ## Install ```sh -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/follow-up --tag-prefix follow-up/ ``` -`semver:*` resolves to the newest `follow-up/vX.Y.Z` tag, so this line stays -correct as the plugin releases and `bb plugin update` follows it. +With `--tag-prefix`, the range `*` resolves to the newest `follow-up/vX.Y.Z` +tag, so this line stays correct as the plugin releases and `bb plugin update` +follows it. ## What it does diff --git a/plugins/thread-badges/README.md b/plugins/thread-badges/README.md index d43967c..4cf3da0 100644 --- a/plugins/thread-badges/README.md +++ b/plugins/thread-badges/README.md @@ -14,12 +14,13 @@ knows nothing about what any badge means. ## Install ```sh -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/thread-badges --tag-prefix thread-badges/ ``` -`semver:*` resolves to the newest `thread-badges/vX.Y.Z` tag, so this line stays -correct as the plugin releases and `bb plugin update` follows it. +With `--tag-prefix`, the range `*` resolves to the newest `thread-badges/vX.Y.Z` +tag, so this line stays correct as the plugin releases and `bb plugin update` +follows it. ## What it does diff --git a/plugins/top-tabs/README.md b/plugins/top-tabs/README.md index 93329e9..ab6fc6b 100644 --- a/plugins/top-tabs/README.md +++ b/plugins/top-tabs/README.md @@ -16,7 +16,7 @@ open on that tab. ## Install ```sh -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/top-tabs --tag-prefix top-tabs/ ``` diff --git a/plugins/workflow-stages/README.md b/plugins/workflow-stages/README.md index 8616776..6ffd449 100644 --- a/plugins/workflow-stages/README.md +++ b/plugins/workflow-stages/README.md @@ -23,12 +23,13 @@ and selected under **Settings → Appearance → Sidebar**. Without it the stage have nowhere to draw. ```sh -bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@semver:*" \ +bb plugin install "git:https://github.com/matthewdias/bb-plugins.git@*" \ --subdirectory plugins/workflow-stages --tag-prefix workflow-stages/ ``` -`semver:*` resolves to the newest `workflow-stages/vX.Y.Z` tag, so this line stays -correct as the plugin releases and `bb plugin update` follows it. +With `--tag-prefix`, the range `*` resolves to the newest `workflow-stages/vX.Y.Z` +tag, so this line stays correct as the plugin releases and `bb plugin update` +follows it. Then pick **Workflow** in the sidebar's Groups menu. diff --git a/scripts/bb-dev.mjs b/scripts/bb-dev.mjs index 9380948..1dca60c 100644 --- a/scripts/bb-dev.mjs +++ b/scripts/bb-dev.mjs @@ -44,8 +44,8 @@ function plugin(slug) { dir, id, version: manifest.version, - range: `^${manifest.version}`, tagPrefix: `${id}/`, + tag: `${id}/v${manifest.version}`, subdir: `plugins/${slug}`, }; } @@ -70,16 +70,21 @@ function fail(message) { process.exit(1); } -/** The installed source line, or null when the plugin is not installed. */ -function currentSource(id) { +/** + * One line of `bb plugin source` — "requested" is what was asked for, "resolved" + * the tag and commit it landed on — or null when the plugin is not installed. + */ +function sourceLine(id, field) { try { const out = bb(["plugin", "source", id], { capture: true }); - return out.match(/^\s*requested:\s*(.+)$/m)?.[1]?.trim() ?? null; + return out.match(new RegExp(`^\\s*${field}:\\s*(.+)$`, "m"))?.[1]?.trim() ?? null; } catch { return null; } } +const currentSource = (id) => sourceLine(id, "requested"); + /** * Only the values that differ from their declared default are worth carrying * across a reinstall — a default that stays default needs no help, and writing @@ -128,18 +133,51 @@ function swap(p, source, label) { const link = (p) => swap(p, [`path:${REPO}`, "--plugin", p.id], "released tag -> this checkout"); -const release = (p) => +/** + * `@*` resolves to whatever the newest tag is, so a checkout whose bumped + * version was never tagged would quietly get the previous release. Refuse it + * here, before anything is removed — every plugin, so `release all` cannot stop + * halfway with some swapped. + */ +function assertTagged(ps) { + const missing = ps.filter((p) => { + const out = execFileSync( + "git", + ["ls-remote", "--tags", REMOTE, `refs/tags/${p.tag}`], + { encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] }, + ); + return out.trim() === ""; + }); + if (missing.length > 0) { + fail( + `Not tagged on ${REMOTE}: ${missing.map((p) => p.tag).join(", ")}.\n` + + "Push the tag first, or release from a checkout whose version is tagged. " + + "Nothing was changed.", + ); + } +} + +// A bare range, not a pinned `^X.Y.Z`: on a 0.x version a caret cannot reach +// the next minor, so `bb plugin update` would stop following the plugin. bb +// rejects `@semver:*` alongside --tag-prefix, which is why it is spelled `@*`. +function release(p) { swap( p, - [ - `git:${REMOTE}@${p.range}`, - "--subdirectory", - p.subdir, - "--tag-prefix", - p.tagPrefix, - ], - `this checkout -> ${p.tagPrefix}v${p.version}`, + [`git:${REMOTE}@*`, "--subdirectory", p.subdir, "--tag-prefix", p.tagPrefix], + `this checkout -> newest ${p.tagPrefix} tag`, ); + const resolved = sourceLine(p.id, "resolved"); + if (resolved === null) { + console.warn(" note: could not read which tag was installed"); + return; + } + console.log(` resolved: ${resolved}`); + // Not necessarily a newer one: `@*` skips pre-releases, so a checkout at + // 0.8.0-beta.1 gets the newest stable release, which is older. + if (!resolved.includes(`@${p.tag} `)) { + console.warn(` note: this checkout is ${p.tag}; a different tag was installed`); + } +} function reload(p) { const started = Date.now(); @@ -175,9 +213,12 @@ switch (command) { case "link": targets().forEach(link); break; - case "release": - targets().forEach(release); + case "release": { + const ps = targets(); + assertTagged(ps); + ps.forEach(release); break; + } case "reload": targets().forEach(reload); break;