Skip to content

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 ​

bash
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 --dirty

workbench: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 module app-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::CHANGES entry.
  • 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).