# [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 ![image](https://hackmd.io/_uploads/r16-4oEwgl.png) * 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 ![image](https://hackmd.io/_uploads/rJK2EiNwgl.png) * For Development enviroment use the RC format and set as pre-release ![image](https://hackmd.io/_uploads/HJXvroNPgl.png) ### 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. ![image](https://hackmd.io/_uploads/HkRaIh4wlg.png) :::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.) ```