Skip to main content
Last Updated: 2025-10-14 Current Version: 2.4.0 This document defines the version pinning strategy for Docker images and deployment configurations to ensure production-grade, reproducible deployments.

Executive Summary

Policy: 🔴 NEVER use :latest tags in production deployments Rationale:
  • ✅ Reproducible deployments across environments
  • ✅ Easy rollback to any previous version
  • ✅ Clear version history and audit trail
  • ✅ No surprise breaking changes
  • ✅ Compliance with production best practices

Version Pinning Rules

Production (Mandatory)

All production deployments MUST use explicit version tags following semantic versioning:
## ✅ CORRECT
image: mcp-server-langgraph:2.4.0
image: mcp-server-langgraph:v2.4.0
image: gcr.io/project/app:2.4.0

## 🔴 NEVER DO THIS
image: mcp-server-langgraph:latest
image: mcp-server-langgraph  # defaults to latest
Staging environments SHOULD use explicit version tags with environment prefix:
## ✅ PREFERRED
newTag: staging-2.4.0

## ⚠️ ACCEPTABLE (for pre-release testing)
newTag: staging-rc1
newTag: staging-beta

## 🔴 AVOID
newTag: staging-latest

Development (Flexible)

Development environments MAY use latest tags for rapid iteration:
## ✅ ACCEPTABLE for local dev
newTag: dev-latest
newTag: dev-${GIT_SHA}

## ✅ BETTER (traceable)
newTag: dev-2.4.0-${GIT_SHA}

Current Version Matrix

Application Version: 2.4.0

ComponentVersion SourceCurrent Value
Projectpyproject.toml2.4.0
Helm ChartChart.yaml2.4.0
App VersionChart.yaml (appVersion)2.4.0

Deployment Configurations

FileTagStatusEnvironment
Kubernetes
deployments/kubernetes/base/deployment.yaml2.4.0✅ PinnedBase
Helm
deployments/helm/mcp-server-langgraph/values.yaml2.4.0✅ PinnedDefault
deployments/helm/mcp-server-langgraph/Chart.yaml2.4.0✅ PinnedVersion
Kustomize
deployments/kustomize/base/kustomization.yaml2.4.0✅ PinnedBase
deployments/kustomize/overlays/dev/kustomization.yamldev-latest⚠️ LatestDevelopment
deployments/kustomize/overlays/staging/kustomization.yamlstaging-2.4.0✅ PinnedStaging
deployments/kustomize/overlays/production/kustomization.yamlv2.4.0✅ PinnedProduction
Cloud Run
deployments/cloudrun/service.yaml2.4.0✅ PinnedTemplate

Semantic Versioning

We follow Semantic Versioning 2.0.0:

MAJOR.MINOR.PATCH

2.4.0
│ │ └─ PATCH: Backwards compatible bug fixes
│ └─── MINOR: Backwards compatible new features
└───── MAJOR: Breaking changes

Version Bumping Rules

PATCH version (2.4.0 → 2.4.1):
  • Bug fixes
  • Security patches
  • Documentation updates
  • No API changes
MINOR version (2.4.0 → 2.5.0):
  • New features (backward compatible)
  • Deprecations (with migration path)
  • Performance improvements
  • Dependency updates (minor)
MAJOR version (2.4.0 → 3.0.0):
  • Breaking API changes
  • Removed deprecated features
  • Major architectural changes
  • Incompatible dependency updates

Version Update Process

1. Update Source of Truth


## Update pyproject.toml
[project]
version = "2.5.0"  # New version

## Commit version bump
git add pyproject.toml
git commit -m "chore: bump version to 2.5.0"

2. Update Deployment Configurations

Run the version sync script:

## Automated version sync (recommended)
./scripts/sync-versions.sh 2.5.0

## Or manual updates:
## - deployments/helm/mcp-server-langgraph/Chart.yaml (version and appVersion)
## - deployments/helm/mcp-server-langgraph/values.yaml (image.tag)
## - deployments/kubernetes/base/deployment.yaml
## - deployments/kustomize/base/kustomization.yaml
## - deployments/kustomize/overlays/staging/kustomization.yaml
## - deployments/kustomize/overlays/production/kustomization.yaml
## - deployments/cloudrun/service.yaml

3. Create Git Tag

## Create annotated tag
git tag -a v2.5.0 -m "Release version 2.5.0"

## Push tag to trigger release workflow
git push origin v2.5.0

4. CI/CD Automatic Tagging

Our CI/CD pipeline automatically creates:
## On git tag push (v2.5.0):
- mcp-server-langgraph:2.5.0
- mcp-server-langgraph:2.5
- mcp-server-langgraph:2
- mcp-server-langgraph:latest  # Convenience tag

## On main branch commit:
- mcp-server-langgraph:main-${GIT_SHA}
- mcp-server-langgraph:latest  # Updated

## On feature branch:
- mcp-server-langgraph:${BRANCH}-${GIT_SHA}
Note: The :latest tag is created automatically for convenience but MUST NOT be used in production deployments.

Image Tag Formats

## Semantic version (production)
mcp-server-langgraph:2.4.0
mcp-server-langgraph:v2.4.0

## Git SHA (development/staging)
mcp-server-langgraph:dev-a1b2c3d
mcp-server-langgraph:staging-a1b2c3d

## Combined (traceability)
mcp-server-langgraph:2.4.0-a1b2c3d
mcp-server-langgraph:v2.4.0-rc1

## Environment-specific
mcp-server-langgraph:staging-2.4.0
mcp-server-langgraph:prod-2.4.0

Anti-Patterns (DO NOT USE)

## ❌ No tag specified (defaults to :latest)
mcp-server-langgraph

## ❌ Latest tag
mcp-server-langgraph:latest
mcp-server-langgraph:stable
mcp-server-langgraph:production

## ❌ Mutable tags
mcp-server-langgraph:v2
mcp-server-langgraph:v2.4

Deployment Environment Strategies

Development

## kustomize/overlays/dev/kustomization.yaml
images:
  - name: mcp-server-langgraph
    newTag: dev-latest  # Or dev-${GIT_SHA}
Rationale: Rapid iteration, auto-deploy on commit

Staging

## kustomize/overlays/staging/kustomization.yaml
images:
  - name: mcp-server-langgraph
    newTag: staging-2.4.0  # Explicit version
Rationale: Testing specific versions before production

Production

## kustomize/overlays/production/kustomization.yaml
images:
  - name: mcp-server-langgraph
    newTag: v2.4.0  # Production version tag
Rationale: Absolute reproducibility, auditable deployments

Image Pull Policy

Always use IfNotPresent or Never with pinned tags:
## ✅ CORRECT (with pinned tag)
image: mcp-server-langgraph:2.4.0
imagePullPolicy: IfNotPresent

## ⚠️ REQUIRED (with latest tag)
image: mcp-server-langgraph:latest
imagePullPolicy: Always
Rationale:
  • IfNotPresent: Reduces registry pulls, faster deployments
  • Always: Required for mutable tags (latest) to get updates
  • Never: Local development only

Verification Checklist

Before deploying to production:
  • All image tags are explicit versions (no :latest)
  • Version matches pyproject.toml
  • Chart.yaml version and appVersion match
  • All Kustomize overlays updated
  • Git tag created and pushed
  • CI/CD built correct version
  • Staging tested with exact production tag
  • Rollback plan documented

Automated Verification

## Check for :latest tags in production configs
./scripts/check-latest-tags.sh

## Expected output:
## ✅ No :latest tags found in production configurations
## ✅ All versions consistent: 2.4.0

Rollback Procedures

Kustomize Rollback

## Update overlay to previous version
cd deployments/kustomize/overlays/production
vim kustomization.yaml  # Change newTag: v2.4.0 → v2.3.0

## Apply rollback
kubectl apply -k deployments/kustomize/overlays/production

## Verify rollback
kubectl rollout status deployment/prod-mcp-server-langgraph

Helm Rollback

## Rollback to previous release
helm rollback mcp-server-langgraph

## Or rollback to specific revision
helm rollback mcp-server-langgraph 3

## Or reinstall with previous version
helm upgrade mcp-server-langgraph ./deployments/helm/mcp-server-langgraph \
  --set image.tag=2.3.0 \
  --reuse-values

Kubernetes Native Rollback

## Rollback deployment to previous revision
kubectl rollout undo deployment/mcp-server-langgraph

## Rollback to specific revision
kubectl rollout undo deployment/mcp-server-langgraph --to-revision=5

## Check rollout history
kubectl rollout history deployment/mcp-server-langgraph

Version Drift Detection

Manual Check

## Check running version in Kubernetes
kubectl get deployment mcp-server-langgraph -o jsonpath='{.spec.template.spec.containers[0].image}'

## Expected: mcp-server-langgraph:2.4.0

## Check all deployments across namespaces
kubectl get deployments --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.spec.template.spec.containers[0].image}{"\n"}{end}' | grep mcp-server-langgraph

Automated Monitoring

## Prometheus alert for version drift
- alert: ImageVersionMismatch
  expr: kube_deployment_spec_replicas{deployment="mcp-server-langgraph"}
        unless on(deployment) kube_deployment_spec_template_image{image=~".*:2\\.4\\.0"}
  for: 5m
  annotations:
    summary: "Deployment using unexpected image version"

CI/CD Integration

GitHub Actions Example

## .github/workflows/deploy.yml
- name: Deploy to Production
  run: |
    # Extract version from git tag
    VERSION=${GITHUB_REF#refs/tags/v}

    # Validate version format
    if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      echo "Invalid version format: $VERSION"
      exit 1
    fi

    # Deploy with explicit version
    helm upgrade --install mcp-server-langgraph ./helm/mcp-server-langgraph \
      --namespace production \
      --set image.tag=$VERSION \
      --wait

Pre-commit Hook

## .git/hooks/pre-commit
#!/bin/bash
## Check for :latest tags in production paths

LATEST_TAGS=$(grep -r ":latest" deployments/ \
  --include="*.yaml" \
  --exclude-dir="overlays/dev" \
  | grep -v "^#" || true)

if [ -n "$LATEST_TAGS" ]; then
  echo "❌ ERROR: Found :latest tags in production configurations:"
  echo "$LATEST_TAGS"
  echo ""
  echo "Please pin to specific versions."
  exit 1
fi

echo "✅ No :latest tags found in production configurations"

Infrastructure Image Versions

External service images (OpenFGA, Keycloak, etc.) are also pinned:
ServiceImageVersionUpdated
OpenFGAopenfga/openfgav1.10.22025-10-14
Keycloakquay.io/keycloak/keycloak26.4.02025-10-14
PostgreSQLpostgres16-alpine2025-10-14
Redisredis7-alpineCurrent
OTEL Collectorotel/opentelemetry-collector-contrib0.137.02025-10-14
Jaegerjaegertracing/all-in-one1.74.02025-10-14
Prometheusprom/prometheusv3.2.12025-10-14
Grafanagrafana/grafana11.5.12025-10-14
See VERSION_COMPATIBILITY for detailed infrastructure version matrix.

Best Practices Summary

DO ✅

  • ✅ Use explicit semantic version tags (2.4.0)
  • ✅ Update all deployment configs when bumping version
  • ✅ Create git tags for releases
  • ✅ Test with production tags in staging
  • ✅ Document version changes in CHANGELOG.md
  • ✅ Use imagePullPolicy: IfNotPresent with pinned tags
  • ✅ Maintain version consistency across all files

DON’T ❌

  • ❌ Use :latest in production
  • ❌ Use mutable tags (stable, production, v2)
  • ❌ Skip version bumps in deployment configs
  • ❌ Deploy without version validation
  • ❌ Omit git tags for releases
  • ❌ Mix version formats (v2.4.0 vs 2.4.0)
  • ❌ Assume :latest is stable

Troubleshooting

Issue: “Image pull backoff”

## Check if version exists in registry
docker pull mcp-server-langgraph:2.4.0

## If not found, build and push
docker build -t mcp-server-langgraph:2.4.0 .
docker tag mcp-server-langgraph:2.4.0 gcr.io/PROJECT/mcp-server-langgraph:2.4.0
docker push gcr.io/PROJECT/mcp-server-langgraph:2.4.0

Issue: “Deployment using old version”

## Force new deployment
kubectl rollout restart deployment/mcp-server-langgraph

## Or update deployment
kubectl set image deployment/mcp-server-langgraph \
  mcp-server-langgraph=mcp-server-langgraph:2.4.0

Issue: “Version mismatch across environments”

## Audit all deployments
kubectl get deployments --all-namespaces -o wide | grep langgraph

## Sync all environments to same version
./scripts/sync-all-envs.sh 2.4.0


Version History

DateVersionChangeAuthor
2025-10-142.4.0Removed all :latest tags from production configsClaude Code
2025-10-132.2.0Initial version pinning policyTeam

Last Audit: 2025-10-14 Next Review: 2025-11-14 Status: ✅ All production deployments use pinned versions