Skip to content
Draft
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
96 changes: 96 additions & 0 deletions .github/workflows/cli-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,99 @@ jobs:
done
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Its own job, after the GitHub release, so the release never waits on
# npm and a failed publish can be re-run alone.
npm:
name: Publish to npm
needs: releaseandpublish
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
persist-credentials: false

- name: ⎔ Setup bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0

- name: 📥 Download deps
run: bash "$GITHUB_WORKSPACE/.github/scripts/bun-install.sh"
working-directory: cli

# Packing builds the bundle (prepack). A prerelease goes to the
# alpha dist-tag and a release to latest. npm gives a package's
# first version latest whatever its tag, and latest can't be
# removed, so until a stable release exists latest follows the
# newest prerelease instead of staying on the first one. What
# latest is gets read before publishing, and a failed read stops
# the step: it never counts as "no stable release yet". The step
# checks the registry's dist-tags before it calls it done.
- name: 📦 Publish to npm
working-directory: cli
run: |
if [ -z "${NPM_CONFIG_TOKEN:-}" ]; then
echo "::error::The NPM_TOKEN repository secret is not set"
exit 1
fi
VERSION="$GITHUB_REF_NAME"
TAGS_URL="https://registry.npmjs.org/-/package/allthings/dist-tags"
# The dist-tags as JSON, {} if the package doesn't exist
# (404); any other answer is retried, then fails.
tags() {
local out code
for _ in 1 2 3 4 5 6; do
if out=$(curl -sS -w '\n%{http_code}' "$TAGS_URL"); then
code="${out##*$'\n'}"
case "$code" in
200) printf '%s\n' "${out%$'\n'*}"; return 0 ;;
404) echo '{}'; return 0 ;;
esac
fi
sleep 10
done
echo "::error::Could not read npm dist-tags" >&2
return 1
}
# Its own assignment, so a failed read stops the step.
BEFORE=$(tags)
LATEST=$(jq -r '.latest // ""' <<<"$BEFORE")
if [[ "$VERSION" == *-* ]]; then
bun publish --access public --tag alpha
WANT_ALPHA="$VERSION"
if [[ -z "$LATEST" || "$LATEST" == *-* ]]; then
# Retried: the new version may not be visible yet.
for _ in 1 2 3 4 5 6; do
if curl -fsS -X PUT "$TAGS_URL/latest" \
-H "authorization: Bearer $NPM_CONFIG_TOKEN" \
-H "content-type: application/json" \
--data "\"$VERSION\"" > /dev/null; then
break
fi
sleep 10
done
WANT_LATEST="$VERSION"
else
WANT_LATEST="$LATEST"
fi
else
bun publish --access public --tag latest
WANT_LATEST="$VERSION"
WANT_ALPHA=""
fi
# The registry may take a moment to show a new version.
for _ in 1 2 3 4 5 6; do
TAGS=$(tags)
if [[ "$(jq -r '.latest // ""' <<<"$TAGS")" == "$WANT_LATEST" ]] &&
[[ -z "$WANT_ALPHA" || "$(jq -r '.alpha // ""' <<<"$TAGS")" == "$WANT_ALPHA" ]]; then
echo "npm dist-tags: $TAGS"
exit 0
fi
sleep 10
done
echo "::error::npm dist-tags are $TAGS, not latest=$WANT_LATEST${WANT_ALPHA:+ alpha=$WANT_ALPHA}"
exit 1
env:
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
15 changes: 15 additions & 0 deletions .github/workflows/cli.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,18 @@ jobs:
# The old name still runs, with its note on stderr.
ln -s allthings atw
./atw --version 2>&1 >/dev/null | grep -q "atw is now allthings"

# What npm would get: the packed bundle, installed and run as bunx runs it.
- name: 📦 Pack for npm and run it with bunx
working-directory: cli
run: |
pack="$RUNNER_TEMP/pack"
bun pm pack --destination "$pack"
try="$RUNNER_TEMP/try"
mkdir -p "$try"
cd "$try"
echo '{"name":"try","private":true}' > package.json
bun add "$pack"/allthings-*.tgz
bunx allthings --version
bunx allthings --help
bunx atw --version 2>&1 >/dev/null | grep -q "atw is now allthings"
10 changes: 9 additions & 1 deletion cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ That installs the latest stable release in `~/.allthings/bin`. `allthings` 2 is
curl -fsSL https://allthingsweb-dev.github.io/allthingsweb/install.bash | ALLTHINGS_VERSION=2.0.0-alpha.2 bash
```

It is also on npm as `allthings`, for Bun. Prereleases carry the `alpha` dist-tag:

```sh
bunx allthings@alpha events
```

## Use

```sh
Expand Down Expand Up @@ -41,4 +47,6 @@ bun run src/index.ts events

`src/config.ts` holds the site it talks to, `siteOrigin`. It stays on allthingsweb.dev until allthings.dev serves the new site: until then allthings.dev only redirects, and a redirect drops an MCP POST. It flips with the domain move (`infra/docs/r2-migration.md`, Phase 4).

Releases are GitHub releases, cut by pushing a tag that matches `version` in `package.json` (`.github/workflows/cli-release.yaml`). A hyphenated tag (`2.0.0-alpha.2`) is a prerelease, and the installer skips it unless asked. Nothing is published to npm: the package is private.
Releases are GitHub releases, cut by pushing an annotated tag that matches `version` in `package.json` (`.github/workflows/cli-release.yaml`). A hyphenated tag (`2.0.0-alpha.2`) is a prerelease, and the installer skips it unless asked.

The same workflow then publishes the package to npm with `bun publish`, after the binaries. `bun run build` (which packing runs) bundles `src/index.ts` and `src/atw.ts` for Bun into `dist/`, and the package ships only that, with zod inside. A prerelease gets the `alpha` dist-tag, a release `latest`. npm gives a package's first version `latest` whatever its tag, and `latest` can't be removed, so until there is a stable release `latest` follows the newest prerelease. The step then checks the registry's dist-tags. Publishing uses the `NPM_TOKEN` repository secret.
4 changes: 1 addition & 3 deletions cli/bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 27 additions & 7 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,44 @@
"name": "allthings",
"version": "2.0.0-alpha.2",
"description": "all things from your terminal and your agents: the evenings, who is on stage and how to get in.",
"keywords": [
"allthings",
"events",
"meetups",
"san francisco",
"mcp",
"cli"
],
"homepage": "https://allthings.dev",
"repository": {
"type": "git",
"url": "git+https://github.com/allthingsweb-dev/allthingsweb.git",
"directory": "cli"
},
"bugs": "https://github.com/allthingsweb-dev/allthingsweb/issues",
"type": "module",
"private": true,
"bin": {
"allthings": "./src/index.ts",
"atw": "./src/atw.ts"
"allthings": "./dist/index.js",
"atw": "./dist/atw.js"
},
"files": [
"dist"
],
"engines": {
"bun": ">=1.3"
},
"scripts": {
"build": "rm -rf dist && bun build src/index.ts src/atw.ts --target=bun --minify --splitting --outdir dist",
"prepack": "bun run build",
"fmt": "prettier --write .",
"check": "prettier --check .",
"typecheck": "tsc --noEmit",
"test": "bun test"
},
"dependencies": {
"zod": "^4.6.5"
},
"devDependencies": {
"@types/bun": "^1.4.2",
"prettier": "^3.6.2",
"typescript": "7.0.2"
"typescript": "7.0.2",
"zod": "^4.6.5"
}
}
11 changes: 8 additions & 3 deletions cli/tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,16 @@ describe("config", () => {
}
});

test("the package installs allthings, with atw as its alias", () => {
test("the package installs allthings, with atw as its alias, from its bundle", () => {
expect(packageJson.name).toBe("allthings");
expect(packageJson.bin).toEqual({
allthings: "./src/index.ts",
atw: "./src/atw.ts",
allthings: "./dist/index.js",
atw: "./dist/atw.js",
});
// npm gets the bundle alone, which needs nothing installed beside it.
expect(packageJson.files).toEqual(["dist"]);
expect(packageJson).not.toHaveProperty("dependencies");
// bun publish refuses a private package.
expect(packageJson).not.toHaveProperty("private");
});
});
Loading