β Versioning β
This page explains how versioning currently works in Flowcontrol across Maven, the running applications, Docker images, and the Portainer-based deployment flow.
π’ Version format β
Flowcontrol currently uses a four-part application version such as 3.4.6.4.
That means the implementation is SemVer-inspired, but not strict three-part SemVer. In practice, the repository currently uses:
MAJOR.MINOR.PATCH.REVISION
The first three segments should follow the usual SemVer meaning:
MAJOR: breaking or structural changesMINOR: backward-compatible featuresPATCH: backward-compatible fixes
The fourth segment is part of the current release version used in Maven, environment configuration, and published images. Even if the team treats the first three parts semantically, the deployed version in this repository is still the full four-part value.
π Source of truth β
The primary source of truth for the release version is the root Maven version in pom.xml.
The root POM uses:
<version>${revision}</version>and the current revision is stored in:
<revision>3.4.6.4</revision>This matters because the protected branch publish workflow resolves project.version from Maven when publishing GHCR images. In other words:
- the release version used for image publication comes from the root Maven version
- the release version does not come from GitHub vars
π§© Where the version is used β
β Backend services β
Each Java service exposes an application version from:
app:
version: ${APP_VERSION:latest}That means:
- if
APP_VERSIONis provided, the running service uses that value - if
APP_VERSIONis missing, the fallback islatest
π₯οΈ Client β
The client uses VITE_APP_APP_VERSION.
Current behavior:
- in local development,
client/vite.config.tscopies the root.envvalue fromAPP_VERSIONintoVITE_APP_APP_VERSION - in production-style builds, the config uses the placeholder
-APP_VERSION- client/src/utils/useAppVersion.tsfalls back toclient/package.jsononly if the placeholder was not replaced
Because of that fallback, client/package.json is not the release source of truth. It is only a fallback value for the UI if the expected runtime/build replacement did not happen.
π³ Application version vs image tag β
These two things are related, but they are not the same:
APP_VERSION: the version shown or exposed by the running application- image tag: the container tag used to pull and run a specific build
This distinction is important in the current setup.
π¨ Local development compose β
The development compose files use APP_VERSION directly as the image tag for the Java services.
Examples:
${EUREKA_IMAGE}:${APP_VERSION}${GATEWAY_IMAGE}:${APP_VERSION}${ARTICLE_IMAGE}:${APP_VERSION}
So in local compose-based development, the application version and image tag are usually the same value.
β Portainer / deployment compose β
The main deployment compose file separates these concerns:
- service images use
${IMAGE_TAG} - the runtime application version is still passed in as
${APP_VERSION}
Examples:
image: ${ARTICLE_IMAGE}:${IMAGE_TAG}APP_VERSION: ${APP_VERSION}
This means:
- the deployed container tag is selected through
IMAGE_TAG - the version shown inside the application is controlled by
APP_VERSION - in staging, those values are consumed by the Portainer auto-deploy setup
- in production, those values are updated manually in Portainer during the rollout
For a clean release, those values should describe the same rollout, but they are configured separately in the deployment stack.
For the deployment stack model and where those values are supplied, see Deployment.
π·οΈ Published image tags β
The protected branch publish workflow builds and publishes images based on the Maven project version.
π§ͺ staging β
After an approved PR is merged into staging, each published image receives:
stagingstaging-<short-sha><version>-staging<version>-staging-<short-sha>
π master β
After an approved PR is merged into master, each published image receives:
<version>
That <version> value is the Maven project version from the root POM.
π¦ Release checklist β
When preparing a new release version, update the version in the places that actually matter today:
- Update the root
pom.xml<revision>value. - Update
.envAPP_VERSIONif local development and local compose runs should reflect the same version. - Make sure the deployment stack uses the intended
APP_VERSIONandIMAGE_TAG. - Merge through the normal protected-branch flow so GitHub Actions publishes the correct GHCR tags.
- For staging, verify that Portainer auto-deployed the intended staging tag.
- For production, manually update
APP_VERSIONandIMAGE_TAGin Portainer and trigger the stack update. - Verify that the running stack shows the expected application version after rollout.
β οΈ Important notes β
- The old documentation said the version should be changed in GitHub vars first. That is no longer the primary source of truth for release versioning in this repository.
- The client
package.jsonversion is not the release version used by CI/CD. - The per-service
app.version: ${APP_VERSION:latest}fallback should not be treated as release configuration. It is only a runtime default. - If you change the Maven version but forget to align
APP_VERSIONin the deployment environment, the image tag and the version shown inside the app can drift apart. - In the current production process, GitHub publishes the versioned images, but Portainer does not roll production forward automatically. Someone still needs to set
APP_VERSIONandIMAGE_TAGand trigger the update manually.
β Recommended rule β
To keep releases understandable, treat the root Maven revision as the canonical release number and keep these aligned for every release:
- root
pom.xml<revision> - deployment
APP_VERSION - deployment
IMAGE_TAGtarget
If those three stay aligned, the published image tags, the deployed stack, and the version shown in the UI and backend services remain consistent.