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
22 changes: 12 additions & 10 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# Changesets
<!-- Content type: How-to -->

Release flow (single-branch, adapted from anchorage's two-branch setup):
# Release packages with Changesets

1. Every PR that changes a published package (`@understudy/protocol`,
`@understudy/connector`) adds a changeset: `pnpm changeset`.
2. On push to `master`, `.github/workflows/release.yml` either opens/updates
the standing "Version Packages" PR (when changesets are pending) or
publishes any package whose version is not yet on npm (when none are).
3. Merging the Version Packages PR is the release trigger.
Understudy versions published packages on `dev` and publishes them from `master`.

The apps (`apps/backend`, `apps/extension`) are `private: true` and never
publish. Docs: https://github.com/changesets/changesets
1. Target feature and fix pull requests at `dev`. Add a changeset with `pnpm changeset` when a pull request changes `@understudy/protocol` or `@understudy/connector`.
2. Merge the pull request into `dev`. `.github/workflows/version.yml` opens or updates `changeset-release/dev` with version bumps, changelog entries, and consumed changesets.
3. Review and merge the `Version Packages` pull request into `dev`.
4. Verify the versioned `dev` commit, then immediately open and merge a promotion pull request from `dev` to `master`.
5. `.github/workflows/release.yml` publishes unpublished public package versions with npm provenance, tags them, and creates GitHub releases.

If another changeset reaches `dev` before promotion, merge the regenerated `Version Packages` pull request and update the promotion. The release workflow rejects pending changesets on `master`.

Do not merge `master` back into `dev`. The apps in `apps/backend` and `apps/extension` are private and never publish. Read the [Changesets documentation](https://github.com/changesets/changesets) for CLI details.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "master",
"baseBranch": "dev",
"updateInternalDependencies": "patch",
"ignore": [],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ name: CI

on:
push:
branches: [master]
branches: [master, dev]
pull_request:
branches: [master, dev]

concurrency:
group: ci-${{ github.ref }}
Expand Down
33 changes: 20 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
name: Release

# Single-branch changesets flow (adapted from anchorage's two-branch
# version.yml + release.yml — understudy has no dev/main split, so one
# workflow does both halves). On every push to master the changesets action
# either:
# (a) opens/updates the standing "Version Packages" PR when changesets are
# pending (version bumps + CHANGELOG entries + changeset deletion), or
# (b) publishes any public package whose package.json version is not yet on
# npm, creates git tags, and creates GitHub releases.
# A push with nothing pending and nothing unpublished is a clean no-op.
# Publish the versions promoted from dev by a dev-to-master release PR.
# version.yml owns version bumps and changelogs on dev, so this workflow never
# opens pull requests or commits to master. It publishes public package
# versions that are not yet on npm, creates git tags, and creates GitHub
# releases. A push with nothing unpublished is a clean no-op.
#
# A pending changeset on master means dev changed after its Version Packages
# PR merged but before promotion. Publishing that tree would attach the new
# change to a version and changelog that did not include it, so fail before
# installing or publishing anything.
#
# Requires the NPM_TOKEN repo secret: an npm automation token with publish
# rights on the @understudy scope (the org must exist on npm first). Without
Expand All @@ -24,7 +25,6 @@ concurrency: release-${{ github.ref }}

permissions:
contents: write
pull-requests: write
id-token: write

jobs:
Expand All @@ -49,6 +49,15 @@ jobs:
cache: pnpm
registry-url: https://registry.npmjs.org

- name: Refuse pending changesets (freeze-window tripwire)
run: |
PENDING=$(find .changeset -maxdepth 1 -name '*.md' ! -name 'README.md')
if [ -n "$PENDING" ]; then
echo "::error::Unversioned changesets reached master. Merge the regenerated 'Version Packages' PR into dev, then re-cut the release PR (dev -> master)."
echo "$PENDING"
exit 1
fi

- name: Install (frozen lockfile)
run: pnpm install --frozen-lockfile

Expand All @@ -57,12 +66,10 @@ jobs:
- name: Build publishable packages
run: pnpm --filter "./packages/*" build

- name: Version PR or publish
- name: Publish unpublished versions to npm
uses: changesets/action@v1
with:
publish: pnpm changeset publish
title: 'release: version packages'
commit: 'release: version packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Version

# Version packages on dev before promotion to master. Pending changesets cause
# the action to open or update changeset-release/dev. With no pending
# changesets, the workflow is a clean no-op.
#
# Merge the Version Packages PR into dev, verify that commit, then promote dev
# to master. The release workflow rejects a promotion that still contains a
# pending changeset.

on:
push:
branches: [dev]

concurrency: version-${{ github.ref }}

permissions:
contents: write
pull-requests: write

jobs:
version:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# v5/v6 majors run on the node24 action runtime (changesets/action@v1
# already does); the v4 majors ran on node20, which GitHub now flags
# with a deprecation annotation.
- uses: actions/checkout@v5
with:
# Changesets reads history to compute what changed.
fetch-depth: 0

# Reads the pnpm version from package.json "packageManager".
- uses: pnpm/action-setup@v6

- uses: actions/setup-node@v5
with:
node-version: 22
cache: pnpm

- name: Install (frozen lockfile)
run: pnpm install --frozen-lockfile

# No publish input: versioning happens on dev, while master publishes.
- name: Open or update the Version Packages PR (base dev)
uses: changesets/action@v1
with:
title: 'release: version packages'
commit: 'release: version packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Read [`docs/technical-plan.md`](docs/technical-plan.md) for the architecture, sa
| `apps/extension` | WXT and React extension with attended and two-tab unattended hosting |
| `apps/cdp-spike` | Historical Manifest V3 CDP capability harness |

`@understudy/protocol@0.7.0` and `@understudy/connector@0.5.0` are prepared in this repository. A local build does not publish them.
`@understudy/protocol@0.8.0` and `@understudy/connector@0.5.1` are the current published versions. A local build does not publish them.

## Understand the isolation boundary

Expand Down Expand Up @@ -62,13 +62,21 @@ Load `apps/extension/.output/chrome-mv3/` through `chrome://extensions`. Follow

## Release published packages

Changesets and GitHub Actions manage releases from `master`. A pull request that changes a published package adds a changeset with:
Use `dev` as the integration branch and `master` as the default release branch. Target feature and fix pull requests at `dev`. Add a changeset when a pull request changes a published package:

```bash
pnpm changeset
```

The release workflow opens or updates the **Version Packages** pull request. Merging that pull request publishes approved versions with npm provenance. `NPM_TOKEN` needs publish access to the `@understudy` scope.
The Version workflow opens or updates the `Version Packages` pull request against `dev`. Release an approved version in this order:

1. Merge `Version Packages` into `dev`.
2. Verify the versioned `dev` commit.
3. Open and merge a promotion pull request from `dev` to `master`.

The Release workflow publishes the promoted versions with npm provenance. It rejects `master` commits that contain pending changesets. If another changeset reaches `dev` before promotion, merge the regenerated `Version Packages` pull request and update the promotion.

Do not merge `master` back into `dev`. `NPM_TOKEN` needs publish access to the `@understudy` scope.

Backend deployment remains a separate Wrangler operation. Keep `UNATTENDED_ENABLED_TENANTS=[]` until the canary extension passes the production acceptance suite.

Expand Down