Skip to content

ci: changeset-driven Package Release workflow - #901

Open
cloudwebrtc wants to merge 16 commits into
mainfrom
chore/add-changeset-support-for-merge-pr
Open

cloudwebrtc wants to merge 16 commits into
mainfrom
chore/add-changeset-support-for-merge-pr

Conversation

@cloudwebrtc

@cloudwebrtc cloudwebrtc commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

ci: changeset-driven Package Release workflow

  • Rename the publish workflow to Package Release (package-release.yml)
  • Each push to main (merged PRs, including from forks) applies the pending
    .changeset/*.md files and opens or updates a single release PR
    (release/changesets-<base>) with the version bumps and release notes
  • Supported bump types: patch, minor, major, patch-rc, minor-rc,
    major-rc, next-rc, promote; packages: livekit-rtc, livekit-api,
    livekit-protocol
  • Add .github/changesets.py: parses changesets, resolves the bump per package
    (largest wins), validates all of them before writing any file, then bumps
    version.py and removes the changesets it used
  • Release notes list each entry with its own bump type, PR and author
    (`minor` Add a room helper (#123 by @user))
  • Merging the release PR publishes every package whose version.py it changed
    (more than one per release is possible) and tags each one; only release PRs
    opened by the bump job (same repo, github-actions[bot]) can trigger this
  • Each package gets a GitHub Release with its notes. The release is created as
    a draft and made public only after that package's PyPI upload succeeds
  • Only RC releases are allowed from non-main branches; those are started with
    a manual workflow run
  • Add a Changeset workflow that validates changesets on every PR commit
  • Add a Changeset Reminder workflow that comments once with a format guide
    when a PR has no changeset, and removes the comment once one is added. It
    skips renovate/* PRs and PRs that only touch dependency files (*.lock,
    package.json, pnpm-lock.yaml, root pyproject.toml)
  • Add .changeset/README.md documenting the format and release flow

devin-ai-integration[bot]

This comment was marked as resolved.

cloudwebrtc and others added 2 commits October 26, 2026 12:22
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
After tagging, create a GitHub Release per released package using its
section of the release PR body (generated from the consumed changesets).
RC versions are marked as pre-releases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

cloudwebrtc and others added 6 commits October 26, 2026 12:42
Look up the commit that added each changeset and the PR it belongs to,
and append "(#123 by @user)" to its release-notes entry (short SHA when
there is no PR). The bump job now fetches full history and passes
GH_TOKEN so the lookup works in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Create releases with --draft in the tag job, and make each one public in
its package's publish job right after the PyPI upload. A failed build or
upload now leaves only a draft, never a public release for a version
that is not on PyPI. Publish jobs now depend on tag and get
contents: write for gh release edit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pull_request events from forks get a read-only token even after merge,
so the bump job could not push the release branch or open the release
PR. Trigger it on push to main (plus workflow_dispatch) instead; release
PR detection and publishing stay on pull_request: closed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
detect trusted any merged PR whose branch started with release/. Also
require a release/changesets-* branch from this repository, opened by
github-actions[bot], so a hand-made release PR cannot trigger a publish.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a Changeset workflow that runs `changesets.py --check` on each PR
push. It checks the PR merge result with the same rules the release
uses (format, package names, bump types, conflicts, rc-only on non-main
branches) without changing any file. Rename check() to validate() to
free the name for the new flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a remind job (pull_request_target, no checkout of PR code) that
comments once with a short format guide when a PR has no .changeset
file, and deletes that comment once a changeset is added. Bot PRs and
release PRs are skipped. The validate job now runs on pull_request only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudwebrtc cloudwebrtc changed the title chore: Add .changeset support for package-release. ci: changeset-driven Package Release workflow Oct 26, 2026
- Skip both the `validate` and `remind` jobs for PRs from `renovate/*` branches
  (dependency and security updates)
- Don't post the missing-changeset reminder when a PR only changes dependency
  files: `*.lock` (e.g. `uv.lock`, `Cargo.lock`), `package.json` or
  `pnpm-lock.yaml`, in any directory

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
devin-ai-integration[bot]

This comment was marked as resolved.

cloudwebrtc and others added 6 commits October 26, 2026 13:48
With validate and remind in one workflow triggered by both pull_request
and pull_request_target, every PR got a second, skipped "Validate
changesets" check, which could satisfy a required status check even when
validation failed. The reminder now lives in changeset-reminder.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The root pyproject.toml is the unpublished workspace config (dev tooling
and security constraint floors), so a PR touching only it and uv.lock
needs no changeset. Package pyproject.toml files still get the reminder
since they declare published runtime dependencies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Documents the changeset format and release flow, and keeps the
.changeset/ directory in git once every pending changeset has been
consumed by a release (the scripts and workflows ignore README.md).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This PR only changes CI and release tooling, so it shouldn't release any
package. .changeset/README.md now keeps the directory in git.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Prefix every release-notes entry with the bump type its changeset asked
for, e.g. "- `minor` Add a shared room helper (#15 by @user)". The type
is per package, since one changeset can bump packages differently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cloudwebrtc

Copy link
Copy Markdown
Contributor Author

Fork test: Package Release pipeline

Ran the full flow end to end on cloudwebrtc/python-sdks, with the PyPI upload stubbed (one package set to succeed, one to fail) and docs jobs disabled. Nothing was uploaded to PyPI.

Result: 16/16 scenarios passed. 3 issues were found; all are fixed on this branch.

Area Verified
PR checks Missing changeset → reminder posted, then removed once one is added (#2); invalid type fails with an annotation (#3); renovate/* and lockfile-only PRs skipped (#4, #5)
Release PR One release PR, updated in place as rtc / api / protocol PRs merge (#14); largest bump wins; api's livekit-protocol>= follows; entries show type + credit, e.g. `minor` … (#15 by @cloudwebrtc)
Publishing Tags created; GitHub Release goes public only after a successful upload, and stays a draft when the upload fails; no new release PR after a release merges
Security Hand-made release/changesets-* PR bumping version.py → nothing published (#6)
RC Manual run on a non-main branch: minor-rc → rc1, next-rc → rc2 (pre-releases), promote → stable; stable bump on non-main rejected

Fixed during testing

  • The reminder moved to its own workflow, so "Validate changesets" no longer gets a skipped duplicate that could satisfy a required check (1431e29)
  • Added .changeset/README.md, so the directory stays in git once every changeset has been used up (ed9e38d)
  • Trimmed blank lines around GitHub Release notes (6769d4c)

Not covered: contributor fork PRs, real PyPI / Trusted Publisher, the rtc wheel build (no arm64 runner on the fork), branch protection.

Before merging

  • Update PyPI Trusted Publisher (livekit, livekit-api, livekit-protocol) from publish.yml to package-release.yml
  • Make "Validate changesets" and "Release gate" required checks on main
  • Confirm Actions are allowed to create pull requests

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant