Package and Namespace Versioning Strategy for CIM Profile DTOs¶
Context and Problem Statement¶
We need to support simultaneous deployment of multiple IEC 61970 CIM profile versions (2.4.15 and 3.0.0) in our Web API while maintaining:
- Clear separation between versions
- NuGet package independence
- CI/CD-friendly versioning
- Discoverable DTO structures
- Endpoint version parity
How should we structure NuGet packages and namespaces to enable clean version isolation while supporting multiple active API endpoints?
Decision Drivers¶
- Need for parallel installation of multiple CIM versions
- Requirement for explicit version mapping between packages and API endpoints
- CI/CD pipeline compatibility for automated package generation
- Prevention of accidental cross-version DTO usage
- Client clarity in package dependencies
- Compliance with Semantic Versioning standards
Considered Options¶
- Separate NuGet Package per Full Version (GridLab.Gmss.Cgmes.3.0.0)
- Single Package with Versioned Namespaces (GridLab.Gmss.Cgmes)
Decision Outcome¶
Chosen option: "Separate NuGet Package per Full Version", because it provides:
- Absolute version isolation at package level
- Clear dependency tracking in consumer projects
- Simplified CI/CD pipeline implementation
- Direct correlation between API version and package version
- Safe deprecation path for older versions
Consequences¶
-
Good:
- Package version directly maps to API version (3.0.0 package ↔ /api/v3.0.0)
- No possibility of version conflict in dependencies
- Automated pipeline can generate packages without merge conflicts
- Enables differential updates between major/minor versions
-
Bad:
- Potential duplication of identical DTOs across packages
- Requires strict namespace versioning discipline
- Slightly increased storage requirements for NuGet repository
Confirmation¶
Implementation will be verified through:
- ArchUnit validation of namespace-version correlation
- Pipeline-generated package metadata checks
- API version integration tests
// ArchUnit rule example
Classes().That().ResideInNamespace(".*\.Dtos\.V\d+", true)
.Should().BePublic()
.Check();
Pros and Cons of the Options¶
Separate NuGet Package per Full Version¶
-
Good:
- 💡 Explicit
PackageReferenceversions in consumer projects - 🛡️ 100% version isolation in IL level
- 🔀 Enables side-by-side installation
- 📈 Clear version adoption metrics via NuGet stats
- 🔧 Simplifies hotfixes to specific versions
- 💡 Explicit
-
Neutral:
- Requires namespace versioning convention
-
Bad:
- Slightly more complex initial setup
Single Package with Versioned Namespaces¶
-
Good:
- Single package to manage
- Smaller artifact repository footprint
-
Bad:
- ❗ Risk of implicit version mixing
- 🔄 Requires full recompilation for version updates
- 🚫 Impossible to use multiple versions simultaneously
- 📉 Hard to track actual version usage
More Information¶
Version Mapping Table
| API Endpoint | NuGet Package | Namespace Suffix |
|---|---|---|
| /api/v2.4.15/ | GridLab.Gmss.Cgmes.2.4.15 | .Dtos.V2 |
| /api/v3.0.0/ | GridLab.Gmss.Cgmes.3.0.0 | .Dtos.V3 |
Semantic Versioning Reference