# Version Management

Nickel-based version management for infrastructure components, providers, and task services ensures consistent, reproducible deployments.

## Overview

Version management in Provisioning:
- Nickel schemas define version constraints
- Semantic versioning (semver) support
- Version locking for reproducibility
- Compatibility validation
- Update strategies

## Version Constraints

Define version requirements in Nickel:

```nickel
{
  task_services = [
    {
      name = "kubernetes",
      version = ">=1.28.0, <1.30.0",  # Range constraint
    },
    {
      name = "prometheus",
      version = "~2.45.0",  # Patch versions allowed
    },
    {
      name = "grafana",
      version = "^10.0.0",  # Minor versions allowed
    },
    {
      name = "nginx",
      version = "1.25.3",  # Exact version
    }
  ]
}
```

## Constraint Operators

| Operator | Meaning | Example | Matches |
| -------- | ------- | ------- | ------- |
| `=` | Exact version | `=1.28.0` | 1.28.0 only |
| `>=` | Greater or equal | `>=1.28.0` | 1.28.0, 1.29.0, 2.0.0 |
| `<=` | Less or equal | `<=1.30.0` | 1.28.0, 1.30.0 |
| `>` | Greater than | `>1.28.0` | 1.29.0, 2.0.0 |
| `<` | Less than | `<1.30.0` | 1.28.0, 1.29.0 |
| `~` | Patch updates | `~1.28.0` | 1.28.x |
| `^` | Minor updates | `^1.28.0` | 1.x.x |
| `,` | AND constraint | `>=1.28, <1.30` | 1.28.x, 1.29.x |

## Version Locking

Generate lock file for reproducible deployments:

```bash
# Generate lock file
provisioning version lock

# Creates versions.lock.ncl with exact versions
```

**versions.lock.ncl**:

```nickel
{
  task_services = {
    kubernetes = "1.28.3",
    prometheus = "2.45.2",
    grafana = "10.0.5",
    nginx = "1.25.3"
  },
  providers = {
    upcloud = "1.2.0",
    aws = "3.5.1"
  }
}
```

Use lock file:

```nickel
let locked = import "versions.lock.ncl" in
{
  task_services = [
    {name = "kubernetes", version = locked.task_services.kubernetes}
  ]
}
```

## Version Updates

### Check for Updates

```bash
# Check available updates
provisioning version check

# Show outdated components
provisioning version outdated
```

Output:

```plaintext
Component    Current  Latest   Update Available
kubernetes   1.28.0   1.29.2   Minor update
prometheus   2.45.0   2.47.0   Minor update
grafana      10.0.0   11.0.0   Major update (breaking)
```

### Update Strategies

**Conservative (patch only)**:

```nickel
{
  update_policy = 'conservative,  # Only patch updates
}
```

**Moderate (minor updates)**:

```nickel
{
  update_policy = 'moderate,  # Patch + minor updates
}
```

**Aggressive (all updates)**:

```nickel
{
  update_policy = 'aggressive,  # All updates including major
}
```

### Performing Updates

```bash
# Update all components (respecting constraints)
provisioning version update

# Update specific component
provisioning version update kubernetes

# Update to specific version
provisioning version update kubernetes --version 1.29.0

# Dry-run (show what would update)
provisioning version update --dry-run
```

## Compatibility Validation

Validate version compatibility:

```bash
# Check compatibility
provisioning version validate

# Check specific component
provisioning version validate kubernetes
```

Compatibility rules defined in schemas:

```nickel
{
  name = "grafana",
  version = "10.0.0",
  compatibility = {
    prometheus = ">=2.40.0",  # Requires Prometheus 2.40+
    kubernetes = ">=1.24.0"   # Requires Kubernetes 1.24+
  }
}
```

## Version Resolution

When multiple constraints conflict, resolution strategy:

1. **Exact version** - Highest priority
2. **Compatibility constraints** - From dependencies
3. **User constraints** - From configuration
4. **Latest compatible** - Within constraints

Example resolution:

```nickel
# Component A requires: kubernetes >=1.28.0
# Component B requires: kubernetes <1.30.0
# User specifies: kubernetes ^1.28.0

# Resolved: kubernetes 1.29.x (latest compatible)
```

## Pinning Versions

Pin critical components:

```nickel
{
  task_services = [
    {
      name = "kubernetes",
      version = "1.28.3",
      pinned = true  # Never auto-update
    }
  ]
}
```

## Version Rollback

Rollback to previous versions:

```bash
# Show version history
provisioning version history

# Rollback to previous version
provisioning version rollback kubernetes

# Rollback to specific version
provisioning version rollback kubernetes --version 1.28.0
```

## Best Practices

1. **Use version constraints** - Avoid `latest` tag
2. **Lock versions** - Generate and commit lock files
3. **Test updates** - Validate in non-production first
4. **Pin critical components** - Prevent unexpected updates
5. **Document compatibility** - Specify version requirements
6. **Monitor updates** - Track new releases
7. **Gradual rollout** - Update incrementally

## Version Metadata

Access version information programmatically:

```bash
# Show component versions
provisioning version list

# Export versions to JSON
provisioning version export --format json

# Compare versions
provisioning version compare <component> <version1> <version2>
```

## Integration with CI/CD

```yaml
# .gitlab-ci.yml example
deploy:
  script:
    - provisioning version lock --verify  # Verify lock file
    - provisioning version validate       # Check compatibility
    - provisioning deploy                 # Deploy with locked versions
```

## Troubleshooting

### Version Conflicts

```bash
# Show dependency tree
provisioning version tree

# Identify conflicting constraints
provisioning version conflicts
```

### Update Failures

```bash
# Check why update failed
provisioning version update kubernetes --verbose

# Force update (override constraints)
provisioning version update kubernetes --force --version 1.30.0
```

## References

- [Configuration System](configuration-system.md) - Version configuration
- [Schemas Reference](schemas-reference.md) - Version contracts
- [Task Services](task-services.md) - Service versions
