Releasing and contributing
The authoritative text is RELEASING.md in the repository; this page is the map. The repo's CLAUDE.md holds the development loop and conventions.
Branches and PRs
master is the only trunk, protected: no force pushes, required checks test, pint, require-semver-label. Work happens on branches and lands through PRs with conventional-commit titles, because titles become changelog lines. Every PR carries exactly one semver:major, semver:minor or semver:patch label (the Release Drafter autolabeler sets it from the title prefix; .github/workflows/semver-label.yml enforces it), optionally security and skip-changelog.
Docs label (since the documentation overhaul of October 2026): a PR labelled semver:minor or semver:major also carries docs:linked (with the evolve-docs PR URL in its body) or docs:none. .github/workflows/docs-label.yml enforces it; semver:patch PRs are exempt. The docs PR merges before the release is published.
CI
.github/workflows/ci.yml runs the suite (vendor/bin/phpunit, booted through the workbench provider) and pint --test on every PR and master push. The Release CI guard workflow checks that the tagged commit's CI run was green when a release is published and prepends a warning to the notes otherwise.
Releases
Merging updates a rolling draft release (Release Drafter, .github/release-drafter.yml for the categories); the next version follows from the labels merged since the last tag. Releasing is publishing the draft; the tag is created on publish, never by hand. Release candidates come from the Cut release candidate workflow (cut-rc.yml), numbered vX.Y.Z-rc.N, published as prereleases that only projects on an @RC constraint see. Consumers ride three constraint tiers: ^2.x stable, ^2.x@RC for test sites, a dev branch alias for development.
After publishing a stable release: .github/scripts/docs-release-entry.php <tag> <date> <notes> <releases.md> drafts the entry for getting-started/releases.md in evolve-docs (heading, date, badge, one bullet per PR by category, a TODO for the summary). Write the summary, condense the bullets, move any upgrade checklist to Upgrading within 2.x and link it, fold a patch release under its minor's "Patches" heading, then deploy the docs (deploy.sh in evolve-docs, with Diego's confirmation).
Development loop
composer update
vendor/bin/testbench workbench:build # assets, sqlite, migrate, seed (rerun to reset)
composer workbench:theme # frontend theme build (needs node)
vendor/bin/testbench serve # panel at /evolve, auto-login
vendor/bin/phpunit # or --testsuite Harness for the boot smoke test
vendor/bin/pint --dirtyworkbench:build exits 0 even when a seeder fails; read the output. Host-app config that real installs carry in published files is mirrored in workbench/app/Providers/WorkbenchServiceProvider.php; a feature that needs new host config is wired there too, or tests and the served workbench do not see it. See Workbench.
Conventions that bite
- Keep
theme/theme/and the moduleapp-publish/overlays in sync with component API changes; they publish into real projects and have gone stale before (2.5). - Every change to a view a project might have copied gets a
ViewOverrides::CHANGESentry. - Unreleased features are not documented on the docs site's master; the docs PR waits for the code to ship.
- Code style is Pint with
pint.json(Laravel preset, spaces around the concatenation dot).