Skip to content

Versioning POS Next

Mostafa Kadry edited this page Sep 8, 2026 · 1 revision

How versions work in this app, what a bump means, and exactly what to change.

Read this one before your first release, then use the quickstart. Where the release steps here differ from VERSION_CONTROL.md, follow this doc. it adds the verification steps that catch the silent failure described below.


1. What a version is, and why we need one

A version is a promise about compatibility, not a changelog entry and not a marketing number. It answers one question for whoever installs the app:

If I upgrade, will my setup still work?

POS Next is not a website that everyone loads fresh. It is a Frappe app that runs on many customer sites, each on its own upgrade schedule, each with its own data. Without a reliable version:

  • Support cannot ask "which version are you on?" and get a meaningful answer.
  • You cannot say "that bug was fixed in 1.14.2" and have anyone act on it.
  • A site cannot be pinned to a known-good release (bench get-app --branch v1.17.0).
  • You cannot tell whether an upgrade needs a maintenance window and a migration, or whether it is safe on a Tuesday afternoon.
  • Rollback becomes guesswork.

The version is also load-bearing inside the app: pos_next/utils.py exposes get_app_version(), and the frontend build writes a separate version.json used for cache busting so a stale service worker does not keep serving old assets.


2. Semantic Versioning

This project follows Semantic Versioning 2.0.0. as stated at the top of CHANGELOG.md.

  MAJOR . MINOR . PATCH
    2   .   4   .   1
Part Bump when Upgrade means
PATCH Backwards-compatible bug fix Safe. Just upgrade.
MINOR Backwards-compatible new feature Safe. New things appear, nothing breaks.
MAJOR Breaking change Read the notes. Plan it. Something you rely on changed or disappeared.

The rule in one line: increment the leftmost part that applies, and reset the parts to its right to zero.

1.16.3  +  bug fix        ->  1.16.4
1.16.3  +  new feature    ->  1.17.0     (patch resets to 0)
1.16.3  +  breaking       ->  2.0.0      (minor and patch reset to 0)

"Why 1.2 → 1.3 and not 1.2 → 2.0?"

Because the size of the change is irrelevant. Only compatibility matters.

A three-month feature that adds a whole new screen is still a MINOR bump if nothing existing breaks. A one-line rename of a whitelisted API argument is a MAJOR bump, because every caller of that argument now fails.

Ask: "Can a customer upgrade without changing anything on their side?" Yes → MINOR. No → MAJOR.

What is not breaking

  • Adding a new whitelisted endpoint.
  • Adding an optional argument with a default.
  • Adding a DocType field.
  • Fixing a bug so behaviour finally matches documented intent.
  • Internal refactors, UI redesigns, performance work.

Pre-1.0 and pre-release

Under SemVer, 0.y.z means anything may change at any time. POS Next is past 1.0, so that no longer applies. the compatibility promise is real now.

For release candidates, use a pre-release suffix: 2.1.0-rc.1. These sort before the final release and are valid in both SemVer and PEP 440.


3. Files to change

Three places carry the version, and all three must move together.

# File Field Who reads it
1 pos_next/__init__.py __version__ = "X.Y.Z" Canonical. flit builds the Python package from it (pyproject.toml sets dynamic = ["version"]); bench version and get_app_version() report it
2 POS/package.json "version": "X.Y.Z" The Vue frontend build
3 Git tag vX.Y.Z GitHub releases, bench get-app --branch, rollback, support

Plus CHANGELOG.md, which follows Keep a Changelog: move [Unreleased] entries under a new [X.Y.Z] - YYYY-MM-DD heading.

pos_next/public/pos/version.json is generated by yarn build. Never edit it, never hand-write it into a commit — it is a build timestamp for cache busting, not a release version.

Why the git tag must match

The tag is the only one of the three that is addressable from outside the repository. The other two are just strings inside files.

  • bench get-app https://github.com/BrainWise-DEV/POSNext --branch v1.17.0 installs a customer site at an exact, reproducible commit. That only works if the tag exists and points where you think.
  • GitHub Releases are built from tags. No tag, no release page, no notes.
  • git diff v1.16.0..v1.17.0 is how you answer "what actually shipped?" during an incident.
  • Rollback is git checkout v1.16.0. If the tag is missing or points at the wrong commit, there is nothing to roll back to.

If the tag says v2.0.0 but __init__.py says 1.17.0, every one of those breaks. A customer reports a bug on "2.0.0", you check out v2.0.0, and the running site reports 1.17.0. You are now debugging blind. That is the situation the repo is in today.


6. Standards referenced

Standard Use
Semantic Versioning 2.0.0 The MAJOR.MINOR.PATCH contract
Keep a Changelog 1.1.0 CHANGELOG.md format
Conventional Commits 1.0.0 chore(release): commit messages
PEP 440 Python version strings (what flit validates)
npm semver package.json version field
Git tagging Annotated tags and why to prefer them

Quick reference

PATCH  x.y.Z   bug fix, safe to upgrade
MINOR  x.Y.0   new feature, nothing breaks
MAJOR  X.0.0   something broke: API, doctype, mandatory migration,
               minimum dependency, or the meaning of a stored value

Change together:  pos_next/__init__.py
                  POS/package.json
                  git tag vX.Y.Z
                  CHANGELOG.md

Never edit:       pos_next/public/pos/version.json   (generated by yarn build)