Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
<slug>` 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 <slug>` 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/<id>/`, so recorded follow-ups and the stage catalog survive a
Expand Down Expand Up @@ -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.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <name>` works instead of `--subdirectory` — the repository carries a
Expand Down
7 changes: 4 additions & 3 deletions plugins/follow-up/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 4 additions & 3 deletions plugins/thread-badges/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion plugins/top-tabs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/
```

Expand Down
7 changes: 4 additions & 3 deletions plugins/workflow-stages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
71 changes: 56 additions & 15 deletions scripts/bb-dev.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
};
}
Expand All @@ -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
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
Loading