Semantic versioning
Semantic versioning
1) What is SemVer and why is it needed
SemVer sets predictable rules for assigning versions to artifacts (libraries, APIs, services, schemas) so that consumers understand what to expect from the update:- MAJOR - breaking changes.
- MINOR is a new API-compatible feature.
- PATCH - reversible defect fixes.
The goal: to agree on the stability of contracts and reduce the cost of upgrades.
2) Version format
Base format:- `MAJOR. MINOR. PATCH[-PRERELEASE][+BUILD]`
`1. 4. 7 'is a stable release.
`1. 5. 0-rc. 2 '- pre-release (release candidate No. 2).
`2. 0. 0+linux. arm64 '- build metadata (do not affect version comparison).
1. First, 'MAJOR' is compared, then 'MINOR', then 'PATCH'.
2. Pre-releases are smaller than the corresponding stable version: '1. 2. 0-rc. 1 < 1. 2. 0`.
3. Build metadata ('+...') does not affect the order: '1. 2. 0+001 == 1. 2. 0`.
3) What counts as breaking change
Breaking change - any change requiring consumer action:- Delete/rename/change signature of public methods/endpoints.
- Change the input/output format (JSON scheme, types).
- Modify error contracts (codes/structures).
- Change side-effects/SLAs (for example, strict limits or new required fields).
Not breaking (if implemented correctly): adding optional fields, expanding enum with new values (if the client ignores them), new endpoints, new flags with defaults that do not affect current calls.
4) Pre-releases and channel strategies
Pre-releases allow you to test without breaking SemVer promises:- Tags: 'alpha', 'beta', 'rc'. Example: '2. 3. 0-beta. 3`.
- Channels: nightly → alpha → beta → rc → stable.
- Policy: pre-releases should not fall as transitive dependencies for default production assemblies.
5) Version ranges and constraint accuracy
Real ecosystems use range expressions:5. 1 Node/npm (default SemVer)
`^1. 4. 2` ≈ `>=1. 4. 2 <2. 0. 0 '(allows MINOR/PATCH, fixes MAJOR).
`~1. 4. 2` ≈ `>=1. 4. 2 <1. 5. 0 '(allows PATCH within MINOR).
`1. 4. x 'is any patch in 1. 4.
Exact pin: '1. 4. 2`.
5. 2 Python (PEP 440, pip)
`~=1. 4. 2` ≈ `>=1. 4. 2,==1. 4.`.
`>=1. 4,<2. 0 '- explicit boundaries.
5. 3 Maven/Gradle (Java)
`[1. 4,2. 0) '- inclusive/exclusive.
Strict kicking is recommended for food-critical artifacts.
5. 4 Go modules
Always complete 'vMAJOR' tags. MINOR. PATCH ';' v2 + 'requires module suffix '/v2'.
Recommendation: for applications - exact pins (reproducible builds). For libraries - caret ranges (facilitate updates without breakage).
6) CHANGELOG и Conventional Commits
Structured change log improves transparency.
Conventional Commits:
feat(payments): add PIX refund endpoint fix(api): correct 400 → 422 on invalid payload perf(cache): reduce p99 by 20%
refactor(core): extract rule engine docs: update API usage examples chore(deps): bump lodash to 4. 17. 21 feat!: remove legacy webhook v1 (BREAKING CHANGE:...)
Типы: `feat`, `fix`, `perf`, `docs`, `refactor`, `chore` и т. д.
An exclamation point or'BREAKING CHANGE'block declares a MAJOR.
CHANGELOG is generated from the history of commits (release-notes by bots).
7) Versioning policy for API
Public APIs: strict SemVer; breaking → MAJOR.
HTTP/REST: versioning by URL/header: '/v1/... ', '/v2/...' or 'Accept: application/vnd. org. service. v2+json`.
JSON schemas: minor extensions - new optional fields; major - delete/change mandatory.
gRPC/Protobuf: add new fields with new numbers; Do not reuse field numbers deleting the deprecate →, not breaking existing ones.
8) Data and migration schemes
Database migrations are synchronized with app @ 1 versions. 8. 0 'requires'schema @ 1. 8. x`.
For breaking schema changes - phases: expand (add), migrate, contract (delete). Upgrade to MAJOR only when you delete the old contract.
Support double write/read for the duration of the migration.
9) Monorepos and microservices
Multi-package: each package has its own 'MAJOR. MINOR. PATCH`; common root release cycle for meta artifacts only.
Vary strategies:- Independent versions (Lerna/Changesets) - increases isolation.
- Lock-step - easier communication, but more false MAJORS.
- For microservices, fix contracts (OpenAPI/Protobuf) with a separate version: 'contract @ 2. 1. 0 ', the service follows it.
10) Automation of releases in CI/CD
Automatic calculation of the version based on Conventional Commits:- `fix` → `PATCH`, `feat` → `MINOR`, `!`/`BREAKING` → `MAJOR`.
yaml
Pseudo-workflow steps:
- run: npx semantic-release
- run: git tag v$NEW_VERSION && git push --tags
- run: cosign sign ghcr. io/org/app:v$NEW_VERSION
CHANGELOG generation, publishing release notes, updating dependencies in GitOps repo, checking that 'main' always points to the last stable tag.
11) Deprivation policy
Announcement: mark functionality as deprecated in MINOR release, give EOL term (e.g. 90 days).
Observability: Log the use of legacy endpoints with user/tenant context.
Deletion: in the following MAJOR. Document the migration path.
12) Examples and templates
12. 1 Regular SemVer validation expression
regex
^(0 [1-9]\d)\.(0 [1-9]\d)\.(0 [1-9]\d)(?--([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)))? (?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)))?$
12. 2 Examples of comparisons
`1. 2. 3` < `1. 10. 0 '(MINOR comparison).
`2. 0. 0-rc. 1` < `2. 0. 0`.
`1. 2. 3+build. 5` == `1. 2. 3`.
12. 3 Dependency policy (YAML example)
yaml policy:
libraries:
default_range: "^MAJOR. MINOR. PATCH"
pin_security_critical: true services:
pin_exact: true allow_prerelease_in_nonprod: true api_contract:
require_same_minor: true forbid_major_mismatch: true
13) Anti-patterns
Using 'latest '/floating tags in the prod.
MAJOR enhancement without real breakdowns ("marketing versions").
Hidden breaking changes under the guise of 'PATCH'.
Pre-releases in transitive dependencies of production applications.
Change the artifact without a new tag (mutable versions).
Inconsistent code versions and database schemas.
14) Implementation checklist (0-45 days)
0-10 days
Accept SemVer as a mandatory standard, approve the breaking criteria.
Include Conventional Commits and a PR template with a'BREAKING CHANGE'field.
11-25 days
Connect semantic-release/changesets, CHANGELOG autogeneration.
Configure the signing and publishing of artifacts against the vX tag. Y.Z`.
26-45 days
Enter the deprecation policy and telemetry for legacy API usage.
Synchronize contract versions (OpenAPI/Proto) and services.
Prohibit 'latest' and mutable tags at the policy level (OPA/CI regulations).
15) Maturity metrics
% of artifacts published by SemVer tag only.
Average migration time between MINOR versions.
Number of incidents due to hidden breaking changes.
Coverage of Conventional Commits in repositories (> 95%).
Proportion of dependencies without floating ranges in the product (> 90%).
16) When SemVer isn't needed
Internal fast prototypes without external consumers (dated versioning is suitable).
Data/models with experimental features (better Model/Schema Versioning with compatibility at the converter level).
Content packages without a stable public API.
17) Conclusion
SemVer is a trust contract between manufacturer and consumer. Clearly define what breaks compatibility, automate release type recognition and artifact publishing, maintain a transparent CHANGELOG, and comply with deprivation policies. Then the updates will become routine, predictable and secure - and the infrastructure and APIs will develop without shocks to the business.