# [Engineering] Understanding Semantic Versioning
:::info
:bulb: Semantic Versioning (often abbreviated as SemVer) is a versioning system that uses a three-part version number to communicate changes in software.
:::
## :question: What is Semantic Versioning
Semantic Versioning (SemVer) is a widely adopted convention for versioning software. It provides a clear and consistent way to communicate the nature of changes in releases through version numbers.
SemVer uses a three-part version number: MAJOR.MINOR.PATCH. Each part conveys specific information about the release.
## :question: Why Semantic Versioning
* Consistent versioning helps developers understand the potential impact of upgrading to a new version of a dependency. It reduces conflicts and improves dependency management.
* Tools like `npm`, `pip`, and `cargo` use it to decide which versions are compatible.
* and more . . .
## :bulb: Versioning
### Overview of MAJOR.MINOR.PATCH format
**MAJOR**: Incremented when there are incompatible API changes. This means code using the previous version's API may break.
**MINOR**: Incremented when backward-compatible functionality is added. Existing code using the API should still work.
**PATCH**: Incremented when backward-compatible bug fixes are made. The API and functionality remain the same.
**Ex: 1.0.0**
**Pre-Release Versions:**
Release Candidate:
`vMAJOR.MINOR.PATCH-rc.X`
Use when your release is stable and feature-completeyou still want to catch any remaining issues before the stable release.
It's a step closer to the final release and should have minimal changes between the rc and stable versions.
## :feet: Steps
To apply semantic versioning to for example a package you have follow these steps:
### 1- Add new tag
* Create a new tag which points to your latest changes and push it to github, you can do this locally or from github release page.
```
git tag -a v1.0.0 -m "Version 1.0.0"
```
```
git push origin v1.0.0
```
for pre-release tags use Release Candidate format:
`vMAJOR.MINOR.PATCH-rc.X`
:::info
:bulb:Tags are snapshots, not live pointers.
:::
you can see commit your tags points to using:
```
git show-ref --tags
```
for specific tag:
```
git show v1.0.0
```
### 2- Publish Release
* Go to github releases page and draft a new release

* Choose your tag or add new one and make sure to set release title same as version you added, then set as latest release and publish the release

* For Development enviroment use the RC format and set as pre-release

### 3- Update your requirements.txt file in needed Microservices or Lambdas
* open a PR to targeted env and use the suitable release version, for example for dev env open PR using the pre-release version and merge it.

:::info
:bulb:
You don't have to update the version in the MS (master source) because the latest pre-release version is seen as the same as the released version, but it's a good practice to update it.
:::
* for stable releases once all of your changes are confirmed and you added stable tag version and release it open PR to master env and use the stable release.
```
git+ssh://git@github.com/HarriLLC/BreakEngine.git@v1.1.0
```
:::danger
make sure to not delete a release which is already used in MS or Lambda requirements file. as if so this will cause software releases failures.
:::
## :question: How to Deal With Multiple Features and Frequent Changes
we mentioned the very straigth forward case of adding a new change(feature or bug fix) and add a tag with suitable version and release, but what if we have multiple features on development branches what could we do?
* Team Collaboration
* Prioritize changes
* Each change to have its own seperate branch
* Those Changes that will be tested togehter to be merged to common branch taken basically from master.
* Add a tag from this branch and a release for it.
* Open PR for specific env on MSs or Lambdas that usee suitable pre-release version then merge.
* Changes shouldn't stay long on development enviroments. we need to keep updated and push as soon as we could to avoid having features conflicts and versioning confusion.
### ✍️ Lets describe this step by step with the following ex:
how to apply manual semantic versioning to lets say `FinancialModel` package where we have:
* Multi-environment setup
* 5 dependent microservices
* many features in development
* Uncertain release order of features
lets say we have those 3 features in development `(es-feature, minor-feature, ot-feature)`
Currently, `(es-feature, minor-feature, ot-feature)` are merged to dev
`es-feature` and `minor-feature` are merged into stage and beta
### 🧩 Current Feature and Env Status:
| Feature | Status | Environments Merged Into |
| --------------- | --------- | ------------------------ |
| `es-feature` | Completed | `dev`, `stage`, `beta` |
| `minor-feature` | Completed | `dev`, `stage`, `beta` |
| `ot-feature` | In Dev | `dev` only |
### :footprints: Step-by-Step Versioning Per Environment
#### 🔨 dev Environment
You are testing 3 features (including one not ready for stage/prod).
What to do:
* After merging `es-feature`, `minor-feature`, and `ot-feature` into dev:
```
git checkout dev
git tag v1.0.0-dev.1
git push origin v1.0.0-dev.1
```
in `requirements.txt` of microservices in dev env:
```
git+ssh://git@github.com/HarriLLC/FinancialModel.git@v1.0.0-dev.1
```
#### 🔨 stage Environment (UAT)
In stage, only `es-feature` and `minor-feature` are merged, `ot-feature` is NOT there.
What to do:
After merging those 2 features:
```
git checkout stage
git tag v1.0.0-uat.1
git push origin v1.0.0-uat.1
```
In `requirements.txt` of microservices in stage env:
```
git+ssh://git@github.com/HarriLLC/FinancialModel.git@v1.0.0-uat.1
```
#### 🚨 What if es-feature is Ready for Prod First?
If only `es-feature` is approved and `minor-feature` is delayed:
1- Create a new branch from the last commit where only `es-feature` was merged.
2- Tag it:
```
git tag v1.0.0-rc.1
git push origin v1.0.0-rc.1
```
3- When approved to go prod:
```
git tag v1.0.0
git push origin v1.0.0
```
4- Then in `requirements.txt` of microservices in stage env:
```
git+ssh://git@github.com/HarriLLC/FinancialModel.git@v1.0.0
```
#### ✅ Versioning Timeline Example
| Tag | Environment | Features Included | Purpose |
| -------------- | ----------- | ----------------- | --------------------------- |
| `v1.0.0-dev.1` | `dev` | es, minor, ot | Dev testing snapshot |
| `v1.0.0-uat.1` | `stage` | es, minor | UAT testing |
| `v1.0.0-rc.1` | `beta` | es | Release candidate (only es) |
| `v1.0.0` | `master` | es | Final prod release |
| `v1.1.0-rc.1` | `beta` | es + minor | Next release |
| `v1.1.0` | `master` | es + minor | Later prod release |
#### :question: Now what to do when you want to add a new feature?
suppose we have a new feature `break-feature` which will break/change behavior in all microservices not backward compatabile change:
**What You Should Do?**
1. Merge break-feature into dev
now you have those on dev
```
dev = es + minor + ot + break-feature
```
2. Tag the new dev version as the start of v2.x
```
git checkout dev
git tag v2.0.0-dev.1
git push origin v2.0.0-dev.1
```
3. Update requirements.txt in all 5 microservices (in their dev branches):
```
git+ssh://git@github.com/HarriLLC/FinancialModel.git@v2.0.0-dev.1
```
When ready:
Merge to stage, tag:
```
git tag v2.0.0-uat.1
git push origin v2.0.0-uat.1
```
Merge to beta, tag:
```
git tag v2.0.0-rc.1
git push origin v2.0.0-rc.1
```
Then finally:
```
git tag v2.0.0
git push origin v2.0.0
```
And update all microservices’ prod `requirements.txt` to:
```
git+ssh://git@github.com/HarriLLC/FinancialModel.git@v2.0.0
```
### ✅ Conclusion:
For our current situation:
* Tag dev as `vx.x.x-dev.x` for dev env versions including all dev features.
* Tag stage as `vx.x.x-uat.x` for stage env versions including all stage features.
* Later, choose which feature(s) to promote to beta and tag as `vx.x.x-rc.x`
* Merge targeted features branch to master and the final production tag goes to master as `vx.x.x`
* Update `requirements.txt` file for affected MSs for each env.
## :bulb: Team-Friendly Practices
to make things organized more we can add `CHANGELOG.md` file and keep it updated, this is a documentation file used in software projects to track all notable changes made over time — such as new features, bug fixes, breaking changes, and version updates.
ex:
```
# Changelog
All notable changes to this package will be documented in this file.
This project uses [Semantic Versioning](https://semver.org/).
---
## [v2.2.0] – 2025-09-15
### Added
- `ot-feature`: Added overtime cost calculation module.
### Changed
- Improved logging in financial methods.
---
## [v2.1.0] – 2025-08-20
### Added
- `minor-feature`: Introduced minor break calculations
---
## [v2.0.0] – 2025-08-01
### ⚠️ Breaking Changes
- Introduced `break-feature`: Update break financials calculations across all consumers (required changes in all 5 microservices).
- Removed deprecated `BreakForecastModel` class.
### Added
- Update Role APIs
- Improved internal mapping for user financials info.
---
## [Unreleased]
### Planned
- `forecast-feature`: Predictive model for calculations.
- `fww-refactor`: Refactor FWW model
---
## Notes
- `v1.0.0` was **intended but never released** due to early breaking change introduction.
- First production version is `v2.0.0`.
- All versions follow manual semantic versioning and are released via Git tags (e.g. `v2.1.0-rc.1`, `v2.1.0-uat.1`, etc.)
```