This guide is for maintainers who are releasing a new version of Ava CMS.
Versioning
Ava CMS uses Semantic Versioning: MAJOR.MINOR.PATCH.
Important: Ava CMS’s release checks currently require a strict numeric SemVer of the form:
^\d+\.\d+\.\d+$
So versions like 1.0.0-beta.1 will fail release tests today.
Examples:
1.0.0= Initial stable release1.0.1= Patch release with bug fixes1.1.0= Minor release with new features2.0.0= Major release with breaking changes
How to Release
- Update Version: Change
AVA_VERSIONinbootstrap.php. - Install dependencies (if needed): Ensure
vendor/exists andvendor/autoload.phpis present. - Lint: Run
./ava lint. - Test: Run
./ava test. - Release Tests: Run
./ava test --release. - Tag: Create a git tag (recommended format:
v1.0.0). - Push: Push the tag to GitHub.
- Release: Create a GitHub Release from that tag.
That’s it. Ava CMS’s updater checks GitHub Releases and compares the installed version (from AVA_VERSION) to the latest release tag.
Release Tests
The --release flag runs additional tests that verify the project is ready for public release:
./ava test --release
What it checks:
These checks are implemented in core/tests/Release/ReleaseChecksTest.php.
Note: these checks are intentionally opinionated. They validate the defaults of the Ava CMS distribution / starter install (safe config defaults, placeholder URLs/tokens, empty media directory, etc.). If you run them inside a real customised site (for example, a production docs site), you should expect them to fail unless you reset that site back to the starter defaults.
Security & Git
.gitignoreshould includeapp/config/users.php(or ausers.phpentry).gitignoreshould include.env.gitignoreshould includestorage/cache(or/storage/cache/)
Default Configuration Expectations
The release suite expects a “fresh install / safe defaults” configuration in app/config/ava.php:
debug.enabledisfalsethemeisdefaultadmin.enabledisfalseadmin.pathis/adminadmin.themeiscyancli.themeiscyan
And default site identity values:
site.nameisMy Ava CMS Sitesite.base_urlcontainslocalhostsite.timezoneisUTCsite.localeisen_GB
Security placeholder expectation:
security.preview_tokenshould be a placeholder value containingyour-preview-token(or be empty)
Version Checks
AVA_VERSIONmust match strictMAJOR.MINOR.PATCHAVA_VERSIONshould be higher than the latest GitHub release
The “higher than GitHub” check requires the curl extension and network access. If curl is missing (or GitHub cannot be reached), the test is skipped.
Project Structure
- Default theme directory exists:
app/themes/default/ - Default theme has bootstrap file:
app/themes/default/theme.php - Example content exists:
content/pages/index.md app/config/users.phpshould ideally be absent; if it exists, it must be gitignoredpublic/media/should be empty (except.gitkeep)
Documentation
README.mdmust existLICENSEmust exist
Dependencies
composer.jsonmust exist and be valid JSON (and contain anamefield)vendor/must existvendor/autoload.phpmust exist
Changelog Format
Include a changelog in the release notes following this format:
## What's New
- ✨ New feature description
- 🔧 Improvement description
- 🐛 Fixed issue description
## Breaking Changes
- ⚠️ Description of breaking change and migration steps
## New Bundled Plugins
- `plugin-name` — Brief description (not activated by default)
What's Included in Releases
GitHub’s release zipball includes the repository contents.
When a user runs ./ava update:apply, Ava CMS should not blindly overwrite their entire site. Instead, it downloads the zipball and synchronises a specific set of paths (see core/Updater.php).
Testing the Update Flow
Before releasing, test the update mechanism:
- Create a test installation
- Set it to an older version in
bootstrap.php - Create a test release on GitHub
- Run
./ava update:check --force - Run
./ava update:apply - Verify files were updated correctly
- Verify user files were preserved
Hotfix Releases
For urgent bug fixes:
- Increment PATCH:
1.0.0→1.0.1 - Follow the normal release process
- Note in changelog that it's a hotfix
Pre-release / Beta
Pre-release versions are not supported by the current release tests (they require strict MAJOR.MINOR.PATCH).
The updater itself uses PHP’s version_compare() for comparisons, but if you want release tests to pass, stick to strict numeric SemVer.
Repository Settings
Ensure the GitHub repository has:
- Releases enabled
- Public visibility (for API access without auth)
- Tags following the
v{VERSION}format
Troubleshooting
Users can't fetch updates
- Ensure releases are published (not draft)
- Ensure repository is public
- Check GitHub API status
Version comparison issues
The updater uses PHP’s version_compare() and strips a leading v from Git tags.
Numeric SemVer examples that compare as expected:
1.0.0<1.0.1✓1.0.9<1.0.10✓1.9.9<2.0.0✓
Release tests failing locally
- If
./ava test --releasefails becauseLICENSEis missing, add aLICENSEfile (the release suite requires it). - If the “higher than GitHub” check is skipped, install/enable the
curlextension so the suite can verify you’re not re-releasing an old version.