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
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: 1.3.14

- uses: dtolnay/rust-toolchain@stable

Expand All @@ -56,12 +56,14 @@ jobs:
# deleted from source; this is the last consumer to move off it.
- name: Headless browser host
id: qa
uses: pathscale/chuzz/.github/actions/headless-host@master
uses: pathscale/chuzz/.github/actions/headless-host@b0e4ce0d35fe96230c90d2a3ed55a64686abe370
with:
token: ${{ secrets.SIBLING_REPOS_TOKEN }}
chuzz-ref: b0e4ce0d35fe96230c90d2a3ed55a64686abe370
ps-qa-version: =0.7.3

- name: Install Dependencies
run: bun install
run: bun install --no-save

# `qa` only, for now: `src` carries 20 pre-existing findings that are not
# this change's to fix, and gating on them would block every PR. The
Expand Down
46 changes: 36 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: Release

# Fully automatic releases. Push to master, and if the commits since the last
# published version warrant a release, this bumps the version, publishes to npm
# and tags it. No version-bump PR, no manual step.
# Fully automatic releases. Successful CI on a master push starts this workflow;
# if the commits since the last published version warrant a release, it bumps
# the version, publishes to npm and tags it. No version-bump PR, no manual step.
#
# The version comes from conventional commits (scripts/next-version.ts):
# type! / BREAKING CHANGE -> major, feat -> minor, fix|perf|revert -> patch.
Expand All @@ -20,15 +20,19 @@ name: Release
# Without it the publish step fails closed rather than publishing unauthenticated.

on:
push:
branches: [master]
workflow_dispatch:
workflow_run:
workflows: [CI]
types: [completed]

permissions:
contents: read

jobs:
decide:
if: >-
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'master'
runs-on: ubicloud-standard-2
outputs:
mode: ${{ steps.decide.outputs.mode }}
Expand All @@ -37,10 +41,17 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # next-version.ts reads commit history
ref: ${{ github.event.workflow_run.head_sha }}

- name: Require the tested revision to remain master
run: |
git fetch origin master
test "$(git rev-parse HEAD)" = "${{ github.event.workflow_run.head_sha }}"
test "$(git rev-parse origin/master)" = "${{ github.event.workflow_run.head_sha }}"

- uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: 1.3.14

- name: Decide whether to release, and as what version
id: decide
Expand Down Expand Up @@ -71,10 +82,20 @@ jobs:
runs-on: ubicloud-standard-2
permissions:
contents: write # push the bump commit
outputs:
release_sha: ${{ steps.release-sha.outputs.value }}
env:
VERSION: ${{ needs.decide.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.workflow_run.head_sha }}

- name: Require the tested revision to remain master
run: |
git fetch origin master
test "$(git rev-parse HEAD)" = "$(git rev-parse origin/master)"

# Mirrors ci.yml — the build resolves this plugin from a sibling directory.
- name: Checkout rsbuild-plugin-ui-css-purge
Expand All @@ -88,7 +109,7 @@ jobs:

- uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: 1.3.14

- uses: actions/setup-node@v4
with:
Expand All @@ -108,7 +129,7 @@ jobs:
git push origin HEAD:master

- name: Install dependencies
run: bun install
run: bun install --no-save

- name: Contract check
run: bun run check
Expand Down Expand Up @@ -145,6 +166,10 @@ jobs:
mkdir -p release
npm pack --pack-destination release

- name: Record the release revision
id: release-sha
run: echo "value=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

- uses: actions/upload-artifact@v4
with:
name: npm-package
Expand Down Expand Up @@ -185,7 +210,7 @@ jobs:
# is not on npm. Tags had drifted badly before this — newest was v1.1.51
# while npm was on 1.2.11.
tag:
needs: [decide, publish]
needs: [decide, prepare, publish]
runs-on: ubicloud-standard-2
permissions:
contents: write
Expand All @@ -199,4 +224,5 @@ jobs:
gh release create "v$VERSION" \
--repo "$GITHUB_REPOSITORY" \
--title "v$VERSION" \
--target "${{ needs.prepare.outputs.release_sha }}" \
--generate-notes
31 changes: 15 additions & 16 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ natively, and Claude Code loads it through the `@AGENTS.md` import in
implementation files.** It is the frontend working agreement: SolidJS/`@pathscale/ui`
conventions, and a context-efficient workflow. Reading it first keeps
context small and avoids re-deriving patterns that already exist.
- **Releases are automatic — never run `npm publish` by hand.** Pushing to `master`
runs [`.github/workflows/release.yml`](.github/workflows/release.yml), which derives the
version from the conventional commits since the last release, bumps `package.json`,
publishes through npm Trusted Publishing (OIDC) and tags it. There is no `NPM_TOKEN` in
this repository, so a local publish cannot authenticate anyway, and a hand-written
- **Releases are automatic — never run `npm publish` by hand.** A successful CI run for
`master` starts [`.github/workflows/release.yml`](.github/workflows/release.yml) at the
exact revision CI tested. The workflow stops if `master` advances before release,
derives the version from conventional commits, bumps `package.json`, publishes through
npm Trusted Publishing (OIDC), and tags the published revision. There is no `NPM_TOKEN`
in this repository, so a local publish cannot authenticate anyway, and a hand-written
version bump only fights the workflow. Publishing is irreversible and a version can
never be reused, so if a release looks wrong, read the workflow run before touching
anything.
- **After a merge, confirm the fix actually published.** The automatic release has one
hole and it is easy to walk into: if the release job for the *previous* merge is still
running when yours lands, the new tag can end up pointing at your commit while npm
never receives it. `bun run scripts/next-version.ts` then reports "no releasable
commits", because the range it inspects is already empty. The symptom is a merged fix
that a consumer cannot install.
- **After a merge, confirm the fix actually published.** The release is gated by CI and
fails closed when another merge advances `master`. Confirm the npm version and tag both
point at the expected release revision:

So check, every time:

Expand All @@ -40,20 +38,21 @@ natively, and Claude Code loads it through the `@AGENTS.md` import in
git tag --points-at HEAD # a tag here with no npm release is the hole
```

If master is ahead of npm, push a one-line `chore(release): <next>` bump to `master`
to trigger the workflow. That is the one case where touching the version by hand is
correct, and it is a repair, not the normal path.
If master is ahead of npm, inspect the CI and Release runs. Fix or re-run the failed
workflow rather than manufacturing another version bump.
- **One open PR per repository. Add to it.** If a PR is already open here, push your
commits onto that branch instead of opening a second one. Two open PRs against the
same library mean two releases, two version bumps, and a consumer that has to wait for
both — and whichever lands second can hit the tag hole above.
- **`bun` is the package manager** — its lockfile is authoritative. Don't introduce a second one by running npm/yarn/pnpm here.
- **`bun` is the package manager. Do not add or generate lockfiles.** This fleet
intentionally resolves from `package.json`; remove a generated lockfile before
reviewing the change. Don't run npm/yarn/pnpm here.
- **Docs describe what is true now.** If you change behaviour, update the README and any affected doc in the same change.

## Build & run

```bash
bun install
bun install --no-save
bun run dev
bun run build
bun run lint
Expand Down
3 changes: 2 additions & 1 deletion tests/qa-harness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ cargo build --release --manifest-path ../chuzz/Cargo.toml --bin chuzz-headless \
QA_HOST=../chuzz/target/release/chuzz-headless bash tests/qa-harness/run-all.sh
```

`QA_PS_QA` does the same for a local ps-qa, version 0.7.1 or newer. The script
`QA_PS_QA` does the same for a local ps-qa. Release runs use the reviewed exact
version 0.7.3 so a driver update cannot silently change the result. The script
refuses stale bundles unless `QA_ALLOW_STALE=1` is explicitly set. Linux rendered
QA needs fontconfig development files and an installed font such as DejaVu;
the shared CI host action installs both. Release verification uses `QA_PROFILE=full`.
Expand Down
8 changes: 4 additions & 4 deletions tests/qa-harness/run-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ fi
# days stale, and all three passed the moment the current one ran.
#
# The driver and host use the shared control protocol from this release.
readonly PS_QA_FLOOR="0.7.1"
readonly PS_QA_VERSION="0.7.3"
ps_qa_version="$("$PS_QA" --version 2>/dev/null | awk '{ print $2 }')"
if [[ -z "$ps_qa_version" ]]; then
echo "$PS_QA does not report a version; it is too old to sweep with" >&2
exit 1
fi
if [[ "$(printf '%s\n%s\n' "$PS_QA_FLOOR" "$ps_qa_version" | sort -V | head -1)" != "$PS_QA_FLOOR" ]]; then
echo "ps-qa $ps_qa_version is older than the $PS_QA_FLOOR this harness needs." >&2
echo " cargo install ps-qa --version '^$PS_QA_FLOOR'" >&2
if [[ "$ps_qa_version" != "$PS_QA_VERSION" ]]; then
echo "ps-qa $ps_qa_version is not the reviewed $PS_QA_VERSION this harness requires." >&2
echo " cargo install ps-qa --version '=$PS_QA_VERSION'" >&2
echo " (or set QA_PS_QA to a build, which is what to do when changing the driver)" >&2
exit 1
fi
Expand Down
Loading