Version Management¶
Complete guide to managing versions in CCGO projects using semantic versioning, git tags, and automated version injection.
Overview¶
CCGO provides comprehensive version management features:
- Semantic Versioning - Follow SemVer 2.0.0 specifications
- Automated Tagging - Create git tags from CCGO.toml version
- Version Injection - Automatically inject version info into builds
- Multi-Platform Support - Consistent versioning across all platforms
- Build Metadata - Include git commit SHA, build timestamp in binaries
- Release Management - Simplify release workflows
Version Format¶
Semantic Versioning¶
CCGO follows Semantic Versioning 2.0.0:
Components:
- MAJOR: Incompatible API changes
- MINOR: New backward-compatible functionality
- PATCH: Backward-compatible bug fixes
- PRERELEASE: Optional pre-release identifier (alpha, beta, rc)
- BUILDMETADATA: Optional build metadata (commit SHA, timestamp)
Examples:
1.0.0 # Stable release
1.2.3 # Patch update
2.0.0-alpha.1 # Pre-release
1.5.0+20240115 # With build metadata
2.1.0-rc.2+g8f3a # Pre-release with git hash
Configuration¶
CCGO.toml¶
[package]
name = "mylib"
version = "1.2.3" # SemVer format
authors = ["Your Name <you@example.com>"]
[version]
# Version injection settings
inject_build_metadata = true # Include git SHA and timestamp
inject_to_code = true # Generate version header files
prerelease_suffix = "beta" # Optional: alpha, beta, rc
# Platform-specific version overrides (optional)
[version.android]
version_code = 10203 # Android integer version (auto-calculated if not set)
[version.ios]
build_number = "123" # iOS build number (defaults to PATCH)
[version.windows]
file_version = "1.2.3.0" # Windows 4-part version
Version Auto-Calculation¶
CCGO automatically calculates platform-specific version numbers:
Android version_code:
iOS build number:
Windows file version:
Creating Version Tags¶
Using ccgo tag¶
# Create tag from CCGO.toml version
ccgo tag
# Create tag with custom version
ccgo tag v2.0.0
# Create tag with message
ccgo tag --message "Release version 2.0.0 with new features"
# Create annotated tag
ccgo tag --annotate
# Push tag to remote
ccgo tag --push
Tag Format¶
Manual Tagging¶
# Create lightweight tag
git tag v1.0.0
# Create annotated tag
git tag -a v1.0.0 -m "Release 1.0.0"
# Push tag to remote
git push origin v1.0.0
# Push all tags
git push --tags
Version Injection¶
Build-Time Injection¶
CCGO automatically injects version information during builds:
# Version info injected into all builds
ccgo build android
# Disable version injection
ccgo build android --no-version-inject
Generated Version Header¶
C++ Header (include/<project>/version.h):
#pragma once
#define MYLIB_VERSION "1.2.3"
#define MYLIB_VERSION_MAJOR 1
#define MYLIB_VERSION_MINOR 2
#define MYLIB_VERSION_PATCH 3
#define MYLIB_GIT_SHA "8f3a2b1c"
#define MYLIB_GIT_BRANCH "main"
#define MYLIB_BUILD_TIMESTAMP "2024-01-15T10:30:00Z"
#define MYLIB_BUILD_TYPE "Release"
// Platform-specific
#ifdef __ANDROID__
#define MYLIB_VERSION_CODE 10203
#elif defined(__APPLE__)
#define MYLIB_BUNDLE_VERSION "123"
#elif defined(_WIN32)
#define MYLIB_FILE_VERSION "1.2.3.0"
#endif
namespace mylib {
const char* get_version();
const char* get_git_sha();
const char* get_build_timestamp();
}
Implementation:
// src/version.cpp (auto-generated)
#include "mylib/version.h"
namespace mylib {
const char* get_version() {
return MYLIB_VERSION;
}
const char* get_git_sha() {
return MYLIB_GIT_SHA;
}
const char* get_build_timestamp() {
return MYLIB_BUILD_TIMESTAMP;
}
}
Using Version in Code¶
#include "mylib/version.h"
#include <iostream>
void print_version() {
std::cout << "MyLib version: " << mylib::get_version() << "\n";
std::cout << "Git SHA: " << mylib::get_git_sha() << "\n";
std::cout << "Built: " << mylib::get_build_timestamp() << "\n";
}
Platform-Specific Versioning¶
Android¶
Version Code and Version Name:
[package]
version = "1.2.3"
[version.android]
version_code = 10203 # Integer for Play Store
version_name = "1.2.3" # Display name (defaults to package.version)
Gradle Integration:
// Generated in build.gradle.kts
android {
defaultConfig {
versionCode = 10203
versionName = "1.2.3"
}
}
iOS¶
Bundle Version:
[package]
version = "1.2.3"
[version.ios]
bundle_short_version = "1.2.3" # CFBundleShortVersionString
build_number = "123" # CFBundleVersion
Info.plist:
<key>CFBundleShortVersionString</key>
<string>1.2.3</string>
<key>CFBundleVersion</key>
<string>123</string>
OpenHarmony¶
HAR Version:
module.json5:
Windows¶
File Version:
[package]
version = "1.2.3"
[version.windows]
file_version = "1.2.3.0" # Four-part version
product_version = "1.2" # Display version
company_name = "Your Company"
copyright = "Copyright © 2024"
Resource File (.rc):
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,3,0
PRODUCTVERSION 1,2,0,0
{
VALUE "FileVersion", "1.2.3.0"
VALUE "ProductVersion", "1.2"
VALUE "CompanyName", "Your Company"
VALUE "LegalCopyright", "Copyright © 2024"
}
Pre-Release Versions¶
Alpha Releases¶
Beta Releases¶
Release Candidates¶
Promotion to Stable¶
# Promote RC to stable
# 1. Update CCGO.toml
version = "2.0.0" # Remove -rc.1
# 2. Create stable tag
ccgo tag v2.0.0 --message "Stable release 2.0.0"
Build Metadata¶
Git Information¶
CCGO automatically includes: - Commit SHA: Current git commit hash - Branch: Current git branch name - Tag: Closest git tag (if any) - Dirty: Whether working directory has uncommitted changes
Timestamp¶
Build Type¶
Custom Metadata¶
Version Queries¶
Check Current Version¶
# Show version from CCGO.toml
ccgo --version
# Show detailed version info
ccgo version --detailed
# Output:
# CCGO version: 3.0.10
# Project: mylib
# Version: 1.2.3
# Git SHA: 8f3a2b1c
# Git branch: main
# Modified: no
Runtime Version Query¶
// In your application
#include "mylib/mylib.h"
const char* version = mylib::get_version();
printf("Library version: %s\n", version);
Versioning Workflows¶
Development Workflow¶
# 1. Start new feature
git checkout -b feature/new-api
# CCGO.toml: version = "1.2.0"
# 2. Develop and test
ccgo build --all
ccgo test
# 3. Merge to main
git checkout main
git merge feature/new-api
# 4. Bump version
# Update CCGO.toml: version = "1.3.0"
# 5. Create tag
ccgo tag v1.3.0 --message "Add new API"
# 6. Push
git push origin main --tags
Release Workflow¶
# 1. Create release branch
git checkout -b release/2.0
# CCGO.toml: version = "2.0.0-rc.1"
# 2. Test release candidate
ccgo build --all
ccgo test --all
# 3. Fix bugs if needed
# ... bug fixes ...
# 4. Promote to stable
# Update CCGO.toml: version = "2.0.0"
ccgo tag v2.0.0 --message "Release 2.0.0"
# 5. Merge back to main
git checkout main
git merge release/2.0
# 6. Push
git push origin main --tags
Hotfix Workflow¶
# 1. Create hotfix branch from tag
git checkout -b hotfix/1.2.4 v1.2.3
# CCGO.toml: version = "1.2.4"
# 2. Fix critical bug
# ... fix ...
# 3. Test
ccgo build --all
ccgo test
# 4. Create tag
ccgo tag v1.2.4 --message "Hotfix: critical bug"
# 5. Merge to main and release branch
git checkout main
git cherry-pick hotfix/1.2.4
git checkout release/1.2
git cherry-pick hotfix/1.2.4
# 6. Push
git push origin main release/1.2 --tags
Changelog Integration¶
Automatic Changelog Generation¶
# Generate changelog from git tags
ccgo changelog
# Output to file
ccgo changelog --output CHANGELOG.md
# Between specific versions
ccgo changelog --from v1.0.0 --to v2.0.0
Changelog Format¶
# Changelog
## [2.0.0] - 2024-01-15
### Added
- New authentication API
- Support for OAuth 2.0
### Changed
- Updated dependency versions
- Improved error handling
### Fixed
- Memory leak in network module
- Crash on invalid input
### Breaking Changes
- Removed deprecated APIs
- Changed function signatures
## [1.2.3] - 2024-01-01
### Fixed
- Critical security vulnerability
Version Constraints¶
Dependency Versions¶
[dependencies]
openssl = { version = "^1.1.0" } # Compatible with 1.1.x
boost = { version = "~1.80.0" } # Compatible with 1.80.x
zlib = { version = "1.2.11" } # Exact version
# Version ranges
protobuf = { version = ">=3.0.0, <4.0.0" }
Operators:
- ^: Compatible with (same major version)
- ~: Approximately compatible (same minor version)
- >=, <=, >, <: Comparison operators
- ,: AND operator
Platform-Specific Constraints¶
[dependencies.android]
androidx-core = { version = "1.12.0" }
[dependencies.ios]
alamofire = { version = "~5.8.0" }
Best Practices¶
1. Version Numbering¶
- Start at 1.0.0 for first stable release
- 0.y.z for initial development (unstable API)
- Increment MAJOR for breaking changes
- Increment MINOR for new features
- Increment PATCH for bug fixes
2. Tag Management¶
# Always use annotated tags for releases
git tag -a v1.0.0 -m "Release 1.0.0"
# Lightweight tags for internal use only
git tag build-123
# Push tags explicitly
git push origin v1.0.0
3. Version in Commit Messages¶
# Good commit messages
git commit -m "chore: bump version to 1.2.3"
git commit -m "release: v2.0.0"
git commit -m "hotfix: v1.2.4 - fix critical bug"
4. Pre-Release Testing¶
# Test all platforms before release
ccgo build --all --release
ccgo test --all
# Verify version info
ccgo version --detailed
5. Documentation¶
- Update CHANGELOG.md before each release
- Document breaking changes clearly
- Maintain migration guides for major versions
CI/CD Integration¶
GitHub Actions¶
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Extract version
id: version
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Build all platforms
run: ccgo build --all --release
- name: Create GitHub Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ steps.version.outputs.version }}
draft: false
prerelease: false
GitLab CI¶
release:
stage: deploy
only:
- tags
script:
- ccgo build --all --release
- ccgo publish --all --registry official
artifacts:
paths:
- target/
Troubleshooting¶
Version Mismatch¶
Problem:
Solution:
Invalid Version Format¶
Problem:
Solution:
Tag Already Exists¶
Problem:
Solution:
# Delete old tag (if intentional)
git tag -d v1.0.0
git push origin :refs/tags/v1.0.0
# Create new tag
ccgo tag v1.0.0
Examples¶
Complete Versioning Setup¶
# CCGO.toml
[package]
name = "mylib"
version = "1.2.3"
authors = ["Your Name <you@example.com>"]
[version]
inject_build_metadata = true
inject_to_code = true
[version.android]
version_code = 10203
[version.ios]
build_number = "123"
[version.windows]
file_version = "1.2.3.0"
company_name = "Your Company"
copyright = "Copyright © 2024"