Releases

How erxes/erxes versions are tagged, how Docker images and frontend bundles are published, and how to read a release as a self-hoster. For upgrading a deployment, see Upgrades.

Who cuts a release

Maintainers create releases from the shared integration branches; contributors never update release metadata. Pull requests are squash-merged and release notes are generated, not hand-written. The release itself is driven by release-it:

  • pnpm release runs release-it (declared as a dev dependency, ^17.0.0).
  • .release-it.json disables npm publishing, commits with the message release ${version} (visible in history as release 3.1.9), creates a git tag named ${version} matching the 3.* pattern, and publishes a GitHub release named v${version}.
  • @release-it/conventional-changelog with the Angular preset rewrites CHANGELOG.md from conventional commit messages, which is why feat(scope): and fix(scope): matter. See Contribute to codebase.

The changelog

Each CHANGELOG.md entry links the compare range, groups commits under ### Bug Fixes and ### Features, and keeps issue and commit links. The 3.1.9 entry looks like this:

## [3.1.9](https://github.com/erxes/erxes/compare/3.1.8...3.1.9) (2026-09-17)

### Features

* **core:** add "Basic information" system fields to Settings → Properties (c8b7214)
* **core:** add member email activity log (#9350) (b65966c)
* **frontline:** use "Visible to create" for convert properties on every kind (f93184b)

What CI publishes

Per-area workflows under .github/workflows/ run builds on pull requests and publish artifacts only on pushes to main or version tags:

Workflow filesArtifactTags
ci-api-*.yml (gateway, core-api, 11 plugin APIs)Docker image erxes/erxes-next-<service> (erxes-next-gateway, erxes-next-core-api, erxes-next-sales_api, …)latest and YYYYMMDD-<short-sha> on main pushes (core-api also publishes from debug/core)
ci-core-ui.ymlerxes/erxes-next-uilatest, branch, short SHA, and semver tags via docker/metadata-action
ci-service-*.yml, ci-saas-migrations.ymlerxes/erxes-next-logs, erxes/erxes-next-automations, erxes/erxes-next-migrationslatest and date-SHA
ci-apps-*.ymlerxes/frontline-widgets, erxes/posclient-front, erxes/help-centerlatest (help-center and frontline-widgets also get date-SHA or metadata tags)
ci-ui-*.yml (plugin remotes)No image; the Rspack Module Federation build is synced to Cloudflare R2 at s3://erxes-next/<folder>/<name>_ui/Folder is latest on main, or the tag name on a version tag

The release workflow

Pushing a tag matching [0-9]* (or running the workflow manually with a version input) triggers release.yml. For each of the 19 images in its matrix (the gateway, core-api, all plugin APIs, logs, automations, erxes-next-ui, frontline-widgets, posclient-front, and help-center), it runs:

docker buildx imagetools create -t "<image>:<version>" "<image>:latest"

So a version tag does not rebuild anything; it promotes whatever :latest was current on Docker Hub at that moment. sentry-release.yml runs on the same tag and creates a Sentry release erxes-<version> on sentry.erxes.io, attaches commits, uploads source maps from frontend/core-ui/dist and frontend/plugins/*/dist, and marks a deployment.

Reading a release as a self-hoster

  • Pin erxes/erxes-next-<service>:3.1.9-style tags rather than latest. The version tag is a copy of the :latest build that was current at release time, so the tag and latest can diverge immediately afterward.
  • A product version does not prove every image has a matching tag; check the set you deploy with docker buildx imagetools inspect erxes/erxes-next-core-api:3.1.9 (or docker manifest inspect).
  • Read CHANGELOG.md for the fixes and features between your current version and the target, then check Database Migrations before following Upgrades.
  • Frontend plugin code is served from the versioned R2 folder, not from an image; a release updates both the images and the erxes-next/<version>/ bundle prefix.
Was this helpful?