Skip to main content

versioning

Component Versioning Strategy

This guide covers semantic versioning for GitLab CI/CD components and version management across 70+ projects.

Semantic Versioning

GitLab CI/CD Components must use semantic versioning (SemVer) when published to the catalog.

Version Format

MAJOR.MINOR.PATCH[-PRERELEASE][+BUILDMETA]

Examples:
1.0.0                   # Stable release
1.2.5                   # Patch update
2.0.0                   # Major version with breaking changes
3.1.0-beta.1            # Beta pre-release
3.1.0-rc.2              # Release candidate
1.4.3+20260108          # With build metadata

Version Components

MAJOR Version (X.0.0)

Increment when making incompatible API changes.

Breaking changes include:

  • Removing component inputs
  • Renaming component inputs
  • Changing input types (string † number)
  • Removing component jobs
  • Changing job behavior in backward-incompatible ways
  • Removing component entirely

Example:

# Version 1.x.x - Old spec: inputs: cluster_name: # Old name type: string # Version 2.0.0 - Breaking change spec: inputs: cluster: # Renamed (breaking!) type: string

MINOR Version (x.Y.0)

Increment when adding backward-compatible functionality.

Non-breaking additions include:

  • Adding new optional inputs (with defaults)
  • Adding new component jobs
  • Adding new features that don't affect existing behavior
  • Deprecating inputs (but keeping them functional)

Example:

# Version 1.0.0 spec: inputs: environment: type: string # Version 1.1.0 - New optional input spec: inputs: environment: type: string enable_monitoring: # New, optional, has default type: boolean default: false

PATCH Version (x.x.Z)

Increment when making backward-compatible bug fixes.

Patch updates include:

  • Bug fixes
  • Performance improvements
  • Documentation updates
  • Security patches (non-breaking)
  • Internal refactoring

Example:

# Version 1.0.0 - Bug: timeout too short deploy: script: - timeout 60 deploy.sh # Bug: 60s too short # Version 1.0.1 - Bug fix deploy: script: - timeout 300 deploy.sh # Fixed: 300s timeout

Pre-Release Versions

Used for testing before stable release:

1.0.0-alpha.1    # Early alpha
1.0.0-beta.1     # Feature-complete beta
1.0.0-rc.1       # Release candidate
1.0.0            # Stable release

Precedence:

1.0.0-alpha.1 < 1.0.0-beta.1 < 1.0.0-rc.1 < 1.0.0

Version References

component: gitlab.com/org/comp/deploy@1.2.3

Use when:

  • Production environments
  • Critical pipelines
  • Strict change control required

Pros: Predictable, no surprises Cons: Manual updates needed

Partial Version (Latest Patch)

component: gitlab.com/org/comp/deploy@~1.2

Selects the latest 1.2.x version (e.g., 1.2.0, 1.2.1, 1.2.2).

Use when:

  • Staging environments
  • Want automatic bug fixes
  • Trust component maintainers

Pros: Auto-receive patch updates Cons: Could introduce unintended behavior changes

Partial Version (Latest Minor)

component: gitlab.com/org/comp/deploy@~1

Selects the latest 1.x.x version (e.g., 1.0.0, 1.5.2, 1.9.8).

Use when:

  • Development environments
  • Want new features automatically
  • Experimental pipelines

Pros: Auto-receive features and bug fixes Cons: Higher risk of unexpected behavior

Latest Version

component: gitlab.com/org/comp/deploy@~latest

Selects the absolute latest version in the catalog.

Use when:

  • Local development only
  • Testing component updates
  • Temporary pipelines

Pros: Always cutting edge Cons: Extremely risky, can break anytime

** Never use ~latest in production!**

Commit SHA

component: gitlab.com/org/comp/deploy@e3262fdd0914fa823210cdb79a8c421e2cef79d8

Use when:

  • Testing unreleased component changes
  • Debugging specific commits
  • Pre-release validation

Pros: Exact commit reference Cons: Not discoverable in catalog, manual management

Version Strategy by Environment

Production Strategy

# .gitlab-ci.yml (production) # Pin to exact stable version deploy-production: include: - component: gitlab.com/org/comp/k8s-deploy@2.1.5 inputs: environment: production replicas: 10 rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Policy:

  • Exact version only
  • Update after thorough testing
  • Require approval for version changes
  • Document version change in MR

Staging Strategy

# .gitlab-ci.yml (staging) # Use latest patch version deploy-staging: include: - component: gitlab.com/org/comp/k8s-deploy@~2.1 inputs: environment: staging replicas: 3 rules: - if: $CI_COMMIT_BRANCH == "staging"

Policy:

  • Latest patch in minor version series
  • Automatically receive bug fixes
  • Test ground for production updates

Development Strategy

# .gitlab-ci.yml (development) # Use latest minor version deploy-dev: include: - component: gitlab.com/org/comp/k8s-deploy@~2 inputs: environment: development replicas: 1 rules: - if: $CI_MERGE_REQUEST_IID

Policy:

  • Latest minor version
  • Early exposure to new features
  • Catch issues before staging/production

Version Lifecycle

Stage 1: Development

Pre-release versions for testing:

# Alpha: Early testing git tag 2.0.0-alpha.1 git push origin 2.0.0-alpha.1 # Beta: Feature-complete, testing git tag 2.0.0-beta.1 git push origin 2.0.0-beta.1 # RC: Final testing before release git tag 2.0.0-rc.1 git push origin 2.0.0-rc.1

Testing projects use pre-release versions:

# test-project/.gitlab-ci.yml include: - component: gitlab.com/org/comp/deploy@2.0.0-beta.1

Stage 2: Stable Release

Release stable version:

git tag 2.0.0 git push origin 2.0.0

Announce to teams:

# Component v2.0.0 Released Stable release available. Ready for gradual rollout. **Breaking changes:** - Input `cluster_name` renamed to `cluster` **New features:** - Helm support - Auto-rollback on failure **Migration guide:** See docs/migration-v1-to-v2.md

Stage 3: Active Support

Patch versions for bug fixes:

# Bug fix git tag 2.0.1 git push origin 2.0.1 # Security patch git tag 2.0.2 git push origin 2.0.2 # Performance improvement git tag 2.0.3 git push origin 2.0.3

Projects using ~2.0 automatically receive patches.

Stage 4: Maintenance

Minor version released, previous enters maintenance:

# New minor version git tag 2.1.0 git push origin 2.1.0

Version 2.0.x enters maintenance mode:

  • Security patches only
  • Critical bug fixes only
  • No new features

Stage 5: Deprecated

Announce deprecation with migration deadline:

# Version 2.0.x Deprecation Notice **Deprecated:** 2.0.x series **Replacement:** 2.1.x or 3.0.x **End of Support:** 2026-06-01 (90 days) **Support Status:** Security patches only Please migrate to 2.1.x or 3.0.x before EOL.

Stage 6: End of Life (EOL)

Version no longer supported:

# Version 2.0.x End of Life **EOL Date:** 2026-06-01 **Status:** No support, no patches **Action Required:** Migrate to 2.1.x or 3.0.x immediately Projects still using 2.0.x: - [ ] legacy-project-1 - [ ] legacy-project-2

Remove from catalog (optional):

# Yank version if security risk glab release delete 2.0.5 --repo org/gitlab_components

Version Support Policy

Support Tiers

VersionStatusSupport LevelDuration
CurrentActiveFull supportUntil next minor
PreviousMaintenanceSecurity + Critical6 months
OlderDeprecatedSecurity only3 months
EOLUnsupportedNoneN/A

Example Timeline

2025-12-01: v2.0.0 released (Current)
2026-03-01: v2.1.0 released
            - v2.1.0 becomes Current
            - v2.0.x enters Maintenance (security + critical bugs)

2026-06-01: v2.2.0 released
            - v2.2.0 becomes Current
            - v2.1.x enters Maintenance
            - v2.0.x enters Deprecated (security only)

2026-09-01: v2.0.x EOL
            - v2.0.x no longer supported
            - All projects must be on v2.1.x or v2.2.x

Version Change Management

CHANGELOG.md

Maintain comprehensive changelog:

# Changelog All notable changes to gitlab_components documented here. Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html) ## [Unreleased] ### Added - New terraform component for infrastructure deployment ## [2.1.0] - 2026-03-01 ### Added - Helm deployment component - Auto-rollback feature in k8s-deploy - Monitoring integration for all deploy components ### Changed - Improved error messages in docker-build - Performance: 30% faster Docker builds ### Deprecated - `cluster_name` input (use `cluster` instead) ### Fixed - Bug: k8s-deploy timeout too short - Bug: docker-build failed with multi-stage Dockerfiles ### Security - Updated base images to address CVE-2026-12345 ## [2.0.0] - 2025-12-01 ### Added - Complete rewrite with semantic versioning - Typed inputs with validation - Published to CI/CD Catalog ### Changed - **BREAKING**: All components now require semantic version references - **BREAKING**: Renamed `cluster_name` to `cluster` ### Removed - **BREAKING**: Removed deprecated v1 components ## [1.9.5] - 2025-11-15 ### Fixed - Final bug fixes before v2.0.0 [Unreleased]: https://gitlab.com/org/comp/compare/2.1.0...HEAD [2.1.0]: https://gitlab.com/org/comp/compare/2.0.0...2.1.0 [2.0.0]: https://gitlab.com/org/comp/compare/1.9.5...2.0.0 [1.9.5]: https://gitlab.com/org/comp/releases/1.9.5

Migration Guides

Provide detailed migration docs:

# Migration Guide: v1.x to v2.0 ## Overview Version 2.0 introduces breaking changes. This guide helps migrate. ## Breaking Changes ### 1. Component References **Before (v1.x):** ```yaml include: - project: org/components ref: main file: templates/deploy.yml

After (v2.0):

include: - component: gitlab.com/org/components/deploy@2.0.0

2. Input Names

Before (v1.x):

variables: CLUSTER_NAME: production NAMESPACE_NAME: app

After (v2.0):

include: - component: gitlab.com/org/components/k8s-deploy@2.0.0 inputs: cluster: production # Renamed from cluster_name namespace: app # Renamed from namespace_name

3. Removed Components

The following components were removed:

  • legacy-deploy † Use k8s-deploy instead
  • old-build † Use docker-build instead

Step-by-Step Migration

Step 1: Update Component References

Replace project includes with component syntax.

Step 2: Rename Inputs

Update all renamed inputs per table above.

Step 3: Test in Development

Test updated pipeline in development environment.

Step 4: Deploy to Staging

After dev validation, deploy to staging.

Step 5: Deploy to Production

After staging validation, deploy to production.

Need Help?


## Automated Version Management

### Semantic Release Integration

```yaml
# .gitlab-ci.yml
release:
  stage: release
  image: node:20
  script:
    # semantic-release automatically:
    # - Analyzes commits
    # - Determines version bump
    # - Generates changelog
    # - Creates git tag
    # - Publishes release
    - npx semantic-release
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
// .releaserc.json { "branches": ["main"], "plugins": [ ["@semantic-release/commit-analyzer", { "preset": "conventionalcommits", "releaseRules": [ {"type": "feat", "release": "minor"}, {"type": "fix", "release": "patch"}, {"type": "perf", "release": "patch"}, {"type": "docs", "release": false}, {"breaking": true, "release": "major"} ] }], "@semantic-release/release-notes-generator", "@semantic-release/changelog", "@semantic-release/gitlab" ] }

Conventional Commits

Use conventional commits to auto-determine version bumps:

# Patch version (1.0.0 † 1.0.1) git commit -m "fix: correct timeout in k8s-deploy" # Minor version (1.0.1 † 1.1.0) git commit -m "feat: add Helm deployment component" # Major version (1.1.0 † 2.0.0) git commit -m "feat!: rename cluster_name to cluster BREAKING CHANGE: Input cluster_name renamed to cluster"

Version Bump Calculator

// calculate-version-bump.ts import { parseCommits } from './git-utils'; interface VersionBump { current: string; next: string; type: 'major' | 'minor' | 'patch'; commits: string[]; } function calculateVersionBump( currentVersion: string, commitsSinceLastRelease: string[] ): VersionBump { const commits = parseCommits(commitsSinceLastRelease); // Check for breaking changes if (commits.some(c => c.breaking)) { return { current: currentVersion, next: bumpMajor(currentVersion), type: 'major', commits: commits.filter(c => c.breaking).map(c => c.message) }; } // Check for features if (commits.some(c => c.type === 'feat')) { return { current: currentVersion, next: bumpMinor(currentVersion), type: 'minor', commits: commits.filter(c => c.type === 'feat').map(c => c.message) }; } // Default to patch return { current: currentVersion, next: bumpPatch(currentVersion), type: 'patch', commits: commits.filter(c => c.type === 'fix').map(c => c.message) }; }

Version Compliance

Enforcement Policies

Policy 1: Production must use exact versions

# GitLab CI/CD compliance check check-production-versions: stage: validate script: - | if [ "$CI_ENVIRONMENT_NAME" = "production" ]; then # Fail if using ~latest or partial versions if grep -E 'component:.*@~' .gitlab-ci.yml; then echo "ERROR: Production must use exact versions" exit 1 fi fi

Policy 2: No deprecated versions

check-deprecated-versions: stage: validate script: - | # Fail if using deprecated version if grep 'component:.*@1\.' .gitlab-ci.yml; then echo "ERROR: Version 1.x is deprecated (EOL: 2026-01-01)" echo "Please upgrade to 2.x" exit 1 fi

Version Audit Report

// audit-component-versions.ts interface VersionAudit { project: string; components: ComponentUsage[]; compliance: { production_exact_version: boolean; no_deprecated_versions: boolean; latest_available: string; current_version: string; needs_update: boolean; }; } async function auditProject(project: string): Promise<VersionAudit> { const ciConfig = await fetchCIConfig(project); const components = extractComponents(ciConfig); return { project, components, compliance: { production_exact_version: checkExactVersions(components), no_deprecated_versions: checkNoDeprecated(components), latest_available: await fetchLatestVersion(), current_version: components[0].version, needs_update: compareVersions(components[0].version, latestVersion) < 0 } }; } // Generate report for all 70 projects const audits = await Promise.all( projects.map(p => auditProject(p)) ); // Alert on non-compliance const nonCompliant = audits.filter(a => !a.compliance.no_deprecated_versions); if (nonCompliant.length > 0) { await sendAlert(`${nonCompliant.length} projects using deprecated versions`); }

Best Practices

DO:

  1. Use semantic versioning - Required for GitLab catalog
  2. Pin production versions - Exact versions only
  3. Automate version bumps - Use semantic-release
  4. Maintain changelog - Document all changes
  5. Provide migration guides - Help users upgrade
  6. Support multiple versions - Maintain 2-3 versions
  7. Communicate changes - Announce releases clearly
  8. Test before release - Use beta/RC versions
  9. Follow conventions - Conventional commits
  10. Deprecate gracefully - Give 90 days notice

DON'T:

  1. Don't use ~latest in production - Too risky
  2. Don't break compatibility without major bump - Follow semver
  3. Don't skip versions - 1.0.0 † 3.0.0 confuses users
  4. Don't reuse tags - Never delete and recreate tags
  5. Don't force updates - Let projects upgrade at their pace
  6. Don't forget documentation - Always update README
  7. Don't rush releases - Test thoroughly
  8. Don't ignore feedback - Listen to beta testers
  9. Don't support too many versions - Maintenance burden
  10. Don't surprise users - Communicate breaking changes early

Next Steps

  • Governance: Change approval and management processes
  • Patterns: Common component patterns and use cases
  • Testing: Component testing strategies

References