Version Constraints for Multi-Version Images

Overview

Version constraints prevent unwanted major or minor version updates for multi-version container images (e.g., python-3-11, nodejs-20). Constraints are defined in properties.yml and validated during make check by comparing VERSION files against defined patterns.

Adding Version Constraints

Edit the image’s properties.yml to add a version constraint:

---
main_package: python3.11
version_constraints: '3.11.*'  # Allow 3.11.X, block 3.12+ and 4.X

The constraint applies to all distros for the image:

---
main_package: dotnet-sdk-8.0
version_constraints: '8.*'  # Applies to rawhide, hummingbird, and any other distros

Constraint Patterns

Constraints use glob-style patterns:

  • 3.11.* - Match any 3.11.X version (recommended for version families)
  • 20.* - Match any 20.X version
  • 8.* - Match any 8.X version
  • 1.25.* - Match any 1.25.X version (for Go-style 3-part versions)

The pattern matches against the version from the VERSION file. For example, if the VERSION file contains 3.11.14, the constraint 3.11.* will match.

How Validation Works

  1. Lockfile Generation: When make all runs, lockfiles are generated with resolved package versions
  2. VERSION File Creation: generate_jinja2.py creates VERSION files from resolved package versions
  3. Constraint Checking: When make check runs, check_version_constraints.py validates VERSION files against constraints
  4. Failure: If a violation is detected, the build fails with a detailed error message
  5. Renovate Integration: Renovate MRs that violate constraints fail CI and are blocked from automerge

Handling Constraint Violations

When a build fails due to a version constraint violation, you have several options:

Option 1: Accept the new version (create new image)

If the new major/minor version is acceptable:

  1. Create a new image directory (e.g., images/python-3-14/)

  2. Copy properties and configuration from the old version

  3. Update the constraint in the new directory:

    version_constraints: '3.14.*'
    
  4. Update repository field to group versions together

  5. Consider adding latest tag to the new version if appropriate

Option 2: Block the version update (exclude package)

If the new version should be blocked entirely:

  1. Add the package to yum-repos/*.repo excludepkgs
  2. Follow the procedure in Excluding Packages from Images
  3. Renovate will skip the excluded version in future updates
  4. When the issue is resolved, remove the exclusion

Option 3: Update the constraint (allow version bump)

If the version bump is acceptable for the existing image:

  1. Update the constraint in properties.yml:

    version_constraints: '3.12.*'  # Allow 3.12.X now
    
  2. Consider if this changes the image’s purpose (major version change)

  3. Update image documentation and tags accordingly

  4. Consider renaming the image directory to reflect the new version

Examples

Python Multi-Version Images

# images/python-3-11/properties.yml
distros:
  - hummingbird
main_package: python3.11
repository: python
version_constraints: '3.11.*'
# images/python-3-13/properties.yml
distros:
  - hummingbird
main_package: python3.13
repository: python
version_constraints: '3.13.*'

Node.js Multi-Version Images

# images/nodejs-20/properties.yml
main_package: nodejs20
repository: nodejs
version_constraints: '20.*'
# images/nodejs-24/properties.yml
main_package: nodejs24
repository: nodejs
version_constraints: '24.*'

.NET SDK Multi-Version Images

# images/dotnet-sdk-8-0/properties.yml
main_package: dotnet-sdk-8.0
repository: dotnet-sdk
version_constraints: '8.*'

.NET Runtime Multi-Version Images

# images/dotnet-runtime-8-0/properties.yml
main_package: dotnet-runtime-8.0
repository: dotnet-runtime
version_constraints: '8.*'

ASP.NET Runtime Multi-Version Images

# images/aspnet-runtime-8-0/properties.yml
main_package: aspnetcore-runtime-8.0
repository: aspnet-runtime
version_constraints: '8.*'

OpenJDK Multi-Version Images

# images/openjdk-21/properties.yml
main_package: java-21-openjdk-headless
repository: openjdk
version_constraints: '21.*'

Go Multi-Version Images (3-part versions)

# images/go-1-25/properties.yml
main_package: golang1.25
repository: go
distros:
  - hummingbird
version_constraints: '1.25.*'  # Matches 1.25.0, 1.25.3, etc.

Troubleshooting

Constraint not working

  • Verify package name matches exactly (case-sensitive)
  • Ensure pattern syntax is correct (use * wildcard)
  • Run make all to regenerate VERSION files before make check

False positive violations

  • Check for typos in the constraint pattern
  • Verify the pattern matches the version format (e.g., 3.11.* not 3.11*)
  • Ensure you’re using glob patterns, not regex

Package renamed in repositories

If a package is renamed (e.g., python3.11python311):

  1. Update main_package field
  2. Update constraint with new package name (not needed - constraints check VERSION files)
  3. Regenerate lockfiles and VERSION files with make all

Implementation Details

The version constraint system consists of:

  1. properties.yml: Optional version_constraints field with a glob pattern string
  2. ci/check_version_constraints.py: Python script that validates VERSION files
  3. Makefile integration: Script runs as part of make check
  4. CI integration: Failures block merge, including Renovate automerge

The validation process:

  1. Reads properties.yml for each image
  2. If version_constraints defined, finds all VERSION files across all distros
  3. Applies the same constraint pattern to all distros for the image
  4. Compares VERSION file content against glob pattern using Python’s fnmatch
  5. Reports violations with file path, version, constraint, and properties file location
  6. Exits with error code 1 if any violations found

See Also