release-process
Skill166 starsChanged 5 days agoApache-2.0View on GitHub
End-to-end release runbook for playwright-rust — version bump, supply-chain refresh, per-crate CHANGELOGs, tag-prefix routing for the three workspace crates, the safer push-then-tag workflow that waits for CI before publishing, and the post-release follow-ups.
- Commits and pushes
14 other projects use a version of this.
Adopted by
Most recently taken up by
- niksavis/handilytheir own version, first seen Nov 8, 2026
- github/squadtheir own version, first seen Nov 8, 2026
- niksavis/basiclytheir own version, first seen Nov 7, 2026
- google/capsemtheir own version, first seen Oct 30, 2026
- microsoft/github-vteam-industry-demostheir own version, first seen Oct 25, 2026
- theultimate-dev/skillstheir own version, first seen Oct 11, 2026
Other versions14 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 14
- fossasia/visdom★ 10ksame name
- github/gh-aw★ 5.6ksame name
- github/squad★ 3.4ksame name
- pluk-inc/markdown-preview★ 2.8ksame name
- pluk-inc/md-preview.app★ 2.8ksame name
- GoogleCloudPlatform/cloud-foundation-fabric★ 2.1ksame name
- lichtblick-suite/lichtblick★ 1.2ksame name
- google/capsem★ 179same name
- Azure/apiops-cli★ 32same name
- lizTheDeveloper/shipping-skills★ 8same name
4 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- doctest-conventionsSkill
- driver-bumpSkill
- supply-chainSkill
- playwright-rs-usageSkill
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 6 are distinctive, and 3 are very specific to this project.
0
Common
Most of the 14 edited versions we read keep these.
6
Distinctive
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 78
Tests are green on
main: before starting - Very specific: line 94
Add a fresh empty ## [Unreleased] heading above
- Very specific: line 95
Update the compare-link footer: add [X.Y.Z]: <compare/prevtag...thistag> and repoint [Unreleased] at the new tag.
- Very specific: line 188
When a playwright-rs release also requires bumping a sibling crate (e.g.
- Distinctive: line 210
If a sibling's version is unchanged this cycle, just skip its tag.
- Distinctive: line 212
If CI fails on main after the version-bump commit:
- Distinctive: line 214
Don't tag. Land a follow-up commit fixing the failure (or revert).
- Distinctive: line 286
Update tracking issues: if this release closes any
- Distinctive: line 291
Announce: if applicable (depends on release significance)
“Common” is measured: kept by at least 6 in 10 of the 14 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Release Process
This skill captures the procedural steps for shipping a playwright-rust release, for in-context reference when walking through one manually or guiding the user.
Pre-flight, before touching any version string
The checklist below assumes these already pass; run them first so a failure lands here rather than halfway through a bump. All are read-only against the tree as it stands.
cargo nextest run --workspace --all-features # what release.yml runs
cargo nextest run --workspace --run-ignored ignored-only # engine-specific stress set
cargo test --doc --workspace --all-features
cargo xtask verify-changelog-links # [Unreleased] and the link footer agree
cargo xtask verify-driver-version # every pinned reference matches build.rs
cargo xtask verify-agent-docs # skill compiles and names every feature
cargo xtask verify-site-snippets
cargo xtask sync-protocol-spec --check # vendored spec is the pinned driver's
cargo xtask verify-protocol-methods # every method the crate sends is in that spec
cargo vet && scripts/deny-lockfiles.sh && cargo auditcargo audit fetches the RustSec database over git, which the Claude Code
sandbox blocks; a "couldn't fetch advisory database" there is the sandbox,
not an advisory. CI's Security & Quality job on the same commit is the
authoritative run in that case.
Then check the cross-crate couplings that a bump makes bite. Step 4 below lists the dependency lines that move together; confirm each is at the version about to be superseded before editing any of them, so a line that was already stale does not get mistaken for one this bump changed.
Workspace layout — three independently-versioned crates
Three publishable crates, each with its own CHANGELOG and tag prefix:
| Crate | Path | CHANGELOG | Tag prefix |
playwright-rs | crates/playwright/ | crates/playwright/CHANGELOG.md | vX.Y.Z |
playwright-rs-macros | crates/playwright-rs-macros/ | crates/playwright-rs-macros/CHANGELOG.md | macros-vX.Y.Z |
playwright-rs-trace | crates/playwright-rs-trace/ | crates/playwright-rs-trace/CHANGELOG.md | trace-vX.Y.Z |
The top-level CHANGELOG.md is an index file, not a changelog —
release notes are generated per-crate from each crate's own CHANGELOG.
The xtask workspace member is publish = false and has no CHANGELOG;
its workflow is documented in crates/xtask/.
Versioning
0.x.y— pre-1.0, API may change (current stage)1.0.0— stable API, ready for production- Patch (
x.y.Z) — bug fixes, security advisories, no API changes - Minor (
x.Y.0) — additive features, deprecations, no breaking changes permitted in 1.x but acceptable in 0.x - Major (
X.0.0) — breaking changes (post-1.0)
Security advisories against transitive deps always warrant a patch release, even if functional behavior is unchanged. See the supply-chain skill.
Pre-release checklist
Steps below assume you're releasing playwright-rs (the main crate).
For the macros or trace crate, swap the paths and tag prefix per the
table above; the workflow is otherwise identical.
- Tests are green on
mainbefore starting - Decide the version (
X.Y.Z) — independent of the other crates - Bump the version in the relevant
Cargo.toml:- For
playwright-rs: workspaceversionin the top-levelCargo.toml - For
playwright-rs-macros:versionincrates/playwright-rs-macros/Cargo.toml - For
playwright-rs-trace:versionincrates/playwright-rs-trace/Cargo.toml
- For
- If a sibling crate's version changed too, update the dep line in
crates/playwright/Cargo.toml:playwright-rs-macros = { version = "...", path = "..." }for the macros bumpplaywright-rs-trace = { version = "...", path = "..." }for the trace bump — two lines carry it, the optional dependency behind thetracefeature and the dev-dependency the tracing integration test uses, and both need the new version. Cargo does not fall back to crates.io for a path dependency whose version requirement fails, so a stale line breaks every workspace command until it is updatedxtask'splaywright-rs = { path = "...", version = "..." }if the main crate version changes (cargo-deny's no-wildcard rule)
- Run
cargo vet. A version bump needs no change insupply-chain/, since our own crates areaudit-as-crates-io = false(see the supply-chain skill) - Update the relevant CHANGELOG (
crates/<crate>/CHANGELOG.md):- Rename
## [Unreleased]to## [X.Y.Z] - YYYY-MM-DD - Add a fresh empty
## [Unreleased]heading above - Update the compare-link footer: add
[X.Y.Z]: <compare/prevtag...thistag>and repoint[Unreleased]at the new tag. This step was skipped on three consecutive releases, leaving those headings rendering as literal[0.14.0]text, so it is now enforced bycargo xtask verify-changelog-links(pre-commit; run it directly if you want to check before committing).
- Rename
- Sync README.md to the release — applies to
playwright-rsonly. The repo'sREADME.mddescribes the latest published release, notmain's in-progress state. A pointer line under the Status: header directs readers atcrates/playwright/CHANGELOG.md[Unreleased]for anything not yet on crates.io. At release time, fold in everything the[Unreleased]CHANGELOG has been previewing — feature flags table, install/CI snippets, Testing & Debugging additions, etc. Also bump the install snippet's pinned"0.X"(line 136 area) if this is a minor or major bump. If this release carries a driver bump, update the README badge only: install snippets are version-free by design (they go through theinstall-browsersexample /install_browsers), so verify none regressed to a pinnednpx playwright@X.Y.Z. - Sync the landing site's release-facing constants — applies to
playwright-rsonly, and these are not covered bycargo xtask verify-driver-version(that guard deliberately anchors only onPLAYWRIGHT_DEV, since the released values legitimately lagmainbetween releases). Easy to miss, and both are rendered on the published/vX.Y.Zsnapshot:crates/site/src/components/hero.rs—PLAYWRIGHT_RELEASEDmust become the driver version this release bundles (i.e. matchPLAYWRIGHT_DEVat release time).crates/site/snippets/install.toml— the crates.io pin ("0.X"and its0.X.ycomment). Also dropunreleased=truefrom anyFeatureCardincrates/site/src/components/features.rswhose feature ships in this release (unreleased cards render only on the dev build, so they would be missing from the release snapshot), and prune the matching assertions incrates/site-e2e/tests/landing_page.rs.
- Verify locally:
cargo nextest run --workspacecargo clippy --workspace --all-targets --all-features -- -D warningscargo test --doc --workspacecargo audit && scripts/deny-lockfiles.sh && cargo vet- Dry-run the publish:
cargo publish --dry-run -p <crate>— catches packaging issues (missing files, license check, README path) before the irreversible realcargo publish. Pass--allow-dirtyif you're verifying mid-edit. Coordinated first-publish caveat: when a release pushes a not-yet-published sibling crate (e.g. v0.13.0's first publish ofplaywright-rs-macros), the main crate's dry-run fails withno matching package named '<sibling>' found ... required by package 'playwright-rs'because cargo resolves all deps against the crates.io index. Dry-run the sibling crates in dependency order (-p playwright-rs-macros→-p playwright-rs-trace→-p playwright-rs); the main crate's dry-run only completes after the siblings are actually published. For pre-release verification,cargo package --list -p playwright-rs --allow-dirtyconfirms the tarball contents without index lookups.
The safer push-then-tag workflow
A pushed git tag triggers release.yml which publishes to crates.io.
Crates.io publishing is irreversible — you cannot unpublish, only
yank. Always validate on CI before tagging.
Single-crate release (the common case)
# 1. Commit the version-bump changes for the chosen crate
git add Cargo.toml Cargo.lock crates/<crate>/Cargo.toml \
crates/<crate>/CHANGELOG.md \
supply-chain/imports.lock supply-chain/config.toml
# (also stage README.md if you bumped the main crate's minor version)
git commit -m "Bump <crate> to <prefix>vX.Y.Z"
# 2. Push the COMMIT first (no tag yet)
git push origin main
# 3. Watch CI — Test on linux/mac/windows + Security & Quality
gh run watch # or check the Actions tab in GitHub
# 4. Only after ALL required checks are green, create and push the tag.
# release.yml's supply-chain-gates job enforces part of this: publishing
# fails unless the tagged commit is on main and vet, deny and audit
# passed on it. The job runs after the test matrix, so Security &
# Quality has normally finished by then; if it had not, re-run the
# failed jobs once it has.
# Tag prefix maps to crate (see workspace table at top of file):
# v0.13.0 → playwright-rs
# macros-v0.1.1 → playwright-rs-macros
# trace-v0.1.1 → playwright-rs-trace
git tag -a <prefix>vX.Y.Z -m "Release <crate> <prefix>vX.Y.Z — <one-line summary>"
git push origin <prefix>vX.Y.ZCoordinated release (multiple crates bumped together)
When a playwright-rs release also requires bumping a sibling crate
(e.g. v0.13.0 wants a fresh playwright-rs-macros 0.2.0), publish the
sibling first so the dep is available on crates.io when the main
crate's cargo publish runs:
# Single commit bumps all relevant Cargo.toml + CHANGELOG files.
git push origin main
gh run watch # CI must be green
# Push tags in dependency order. Wait ~30s between tags so the
# crates.io index propagates before the next publish runs.
git tag -a macros-vA.B.C -m "Release playwright-rs-macros vA.B.C"
git push origin macros-vA.B.C
sleep 30 # crates.io index propagation
git tag -a trace-vD.E.F -m "Release playwright-rs-trace vD.E.F"
git push origin trace-vD.E.F
sleep 30
git tag -a vX.Y.Z -m "Release playwright-rs vX.Y.Z"
git push origin vX.Y.ZIf a sibling's version is unchanged this cycle, just skip its tag.
If CI fails on main after the version-bump commit:
- Don't tag. Land a follow-up commit fixing the failure (or revert).
- A failed
mainis recoverable; a published bad version is not.
What release.yml does on tag push
The workflow handles all three tag prefixes (v*, macros-v*,
trace-v*) with one routed pipeline:
- Runs the test suite on linux/macOS/windows as a final pre-publish gate (always, regardless of tag prefix).
- Resolves the tag —
Resolve crate, changelog, and version from tagstep parses${GITHUB_REF#refs/tags/}and routes:macros-v*→playwright-rs-macros+crates/playwright-rs-macros/CHANGELOG.mdtrace-v*→playwright-rs-trace+crates/playwright-rs-trace/CHANGELOG.mdv*→playwright-rs+crates/playwright/CHANGELOG.md
- Generates release notes from the resolved CHANGELOG via
parse-changelog <CHANGELOG> <VERSION>— the per-crate CHANGELOG is the single source of truth for release notes; no manual paste needed. - Creates the GitHub Release with
name = "<crate> <version>"and the body from the parsed CHANGELOG section. - Publishes to crates.io — exactly one publish step fires per
tag, gated by
startsWith(github.ref_name, '<prefix>'). Failure aborts the workflow (nocontinue-on-error); the release tag stays in place but the publish didn't happen, so re-running with the same tag after fixing the issue is safe.
The workflow is library-only: no binary artifacts are built, archived, or attested. If a CLI is ever shipped, add a separate binary-release pipeline rather than bolting onto this workflow.
Post-release
- Verify the GitHub Release at
https://github.com/padamson/playwright-rust/releases/tag/<prefix>vX.Y.Z - Verify crates.io has the new version. The JSON API often refuses
this with a data-access-policy error; the sparse index answers reliably:
curl -s https://index.crates.io/pl/ay/playwright-rs | tail -1 Publish the versioned site snapshot — applies to
playwright-rsonly, and nothing triggers this automatically:gh workflow run pages.yml --ref vX.Y.Z -f version=X.Y.Z--ref vX.Y.Zis load-bearing: the workflow builds/v<version>/from current source at that ref, so dispatching frommainwould publishmain's content under the release's URL. A tag push does not firepages.yml(itson.pushfilters to branches), so skipping this leavesversions.jsonadvertising the previous release aslatestand omits the new version from the dropdown. This was missed for 0.15.1 and again for 0.16.0, which is why it is now a numbered step rather than a comment in the workflow header.Verify after:
curl -s https://playwright-rust.dev/versions.json- First-time publish bookkeeping — if this was the first crates.io
release of a workspace crate, confirm
supply-chain/config.tomlhas[policy.<crate>] audit-as-crates-io = false. Without itcargo vetfails every push once the crate is on crates.io. It belongs in the commit that adds the crate: vet accepts afalsepolicy before the first publish (it wastruethat it rejected). - Flip the release-state doc — one follow-up commit,
[skip ci], for a minor release that closed driver surface:docs/implementation-plans/v1.0-gap-analysis.md, the version's section heading and the Coverage Summary paragraph. A patch release that changes no coverage needs nothing here.docs/roadmap.mdcarries no per-release status by design and is never touched at release time. The gap analysis claims a release exists, so it must not ride the version-bump commit: that lands onmainbefore CI and before the tag, and a failed publish would leavemainadvertising a release nobody can install. Keep it in the "cut, awaiting tag" phrasing until the publish is verified in steps 1-2, then flip it in one commit. - Update tracking issues if this release closes any
- Reconcile the parked backlog. Anything this release shipped that was parked as a refactor, a deferred follow-up or a measured item gets its body deleted and a ledger row added where it was parked, in this session. Left to a later audit, shipped work keeps reading as open.
- Announce if applicable (depends on release significance)
Common pitfalls
- Hand-editing
supply-chain/imports.lock— never; it is generated bycargo vet(see supply-chain skill) - Tagging before CI — a single failing platform is enough to make a release un-rerunnable
- Forgetting the
[Unreleased]reset in the per-crate CHANGELOG — leaves the next session's CHANGELOG additions homeless - Editing the top-level
CHANGELOG.md— it's an index, not a changelog. Per-crate CHANGELOGs are the source of truth; if you tried adding a release entry to the index it won't appear in the generated GitHub release notes. - Skipping the README version bump on minor releases of
playwright-rs— the install snippet's pinned"0.X"controls what new users see in the README on GitHub before the version on crates.io is current - Coordinated release without sleep between tags — crates.io index
propagation takes ~10–30s;
cargo publish -p playwright-rswill fail to resolve a freshly-publishedplaywright-rs-macrosif the tags are pushed back-to-back without a wait - Pushing the wrong prefix —
vX.Y.Zalways meansplaywright-rs;macros-vX.Y.Zis the macros crate;trace-vX.Y.Zis the trace crate. Therelease.yml"Resolve crate, changelog, and version from tag" step rejects unknown prefixes
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

