All notable changes to the Deployment Guard workflow will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
This is a complete architectural refactor of the Deployment Guard workflow to fix critical bugs that were present since v1.0.0. These bugs prevented proper validation and are now fixed without breaking changes.
-
Robust Version Comparison: Complete rewrite of anti-downgrade logic with proper handling of:
- Base version comparison (YY.MM.DD format)
- Rebuild number comparison (e.g.,
-2in25.12.08-2) - Hash comparison (e.g.,
_abc123in25.12.08_abc123) - Full support for all combinations:
25.12.08,25.12.08-2,25.12.08_abc,25.12.08-2_abc
-
Improved Registry Validation:
- Now tries Docker Hub first, then falls back to full image path for private registries
- Better error messages indicating which registry was checked
- Handles mirror registries more gracefully
-
Enhanced Error Reporting:
- State variables now accumulate ALL validation failures before exiting
- Detailed failure reasons shown for each failed image/file
- Clear indication of which validation step failed and why
-
State Management Architecture: Complete replacement of temporary files with bash arrays
- Before (v1.x): Used
/tmp/validation_failed.txt,/tmp/new_images.txt,/tmp/old_images.txt - After (v1.1.2): Uses bash arrays:
VALIDATION_FAILED,FAILED_IMAGES,NEW_IMAGES,OLD_IMAGES - Eliminates race conditions and file cleanup issues
- Deterministic execution with explicit state tracking
- Before (v1.x): Used
-
Error Handling: Added
set -euo pipefailto all bash scripts for strict error handling- Scripts now fail fast on any command error
- Undefined variables cause immediate failure
- Pipe failures are properly detected
-
Bug #1: Fixed rebuild number downgrade detection
- Issue: v1.x allowed downgrade from
25.12.08-2to25.12.08(no suffix) - Root Cause: Version comparison only compared base version (YY.MM.DD), ignored rebuild numbers
- Fix: Now extracts and compares rebuild numbers when base version is the same
- Example:
25.12.08-2→25.12.08is now correctly blocked as a downgrade - Example:
25.12.08→25.12.08-2is correctly allowed as an upgrade - Example:
25.12.08-2_abc→25.12.08-2_xyzis allowed (same version, different hash)
- Issue: v1.x allowed downgrade from
-
Bug #2: Fixed temporary file persistence issues
- Issue: v1.x had race conditions with
/tmp/validation_failed.txtfile - Root Cause: Multiple writes to same file in loops, manual cleanup required
- Fix: Eliminated ALL temporary files, using in-memory bash arrays
- Issue: v1.x had race conditions with
-
Bug #3: Fixed image existence validation fragility
- Issue: v1.x only checked Docker Hub canonical image, failed for private registries
- Root Cause: Assumed all images exist in Docker Hub
- Fix: Now tries Docker Hub first, then falls back to full image path with registry
-
Bug #4: Fixed silent failures in validation loops
- Issue: v1.x would continue loop even after validation failure, sometimes skipping images
- Root Cause: Lack of strict error handling (
set -euo pipefail) - Fix: Added strict error handling and explicit state tracking
-
Bug #5: Fixed version pattern validation edge cases
- Issue: v1.x regex allowed malformed tags to pass
- Root Cause: Regex didn't enforce proper format boundaries
- Fix: Improved regex validation with proper anchoring and format checks
- All bash scripts now use
set -euo pipefailfor strict error handling - Eliminated potential security issues from temporary file handling
- Better validation of all input parameters before processing
- Added comprehensive CHANGELOG documenting all fixes
- Improved inline comments explaining complex version comparison logic
- Added examples of supported version formats in code comments
- Fixed immutable tag support in image validation
- Improved hash extraction for commit hashes in tags
- Added support for immutable tags with commit hashes
- Added
testing_force_non_bypassparameter for testing validation logic
- Organization-based bypass for trusted members
- File allowlist validation
- Image-only change validation
- Image format and repository validation
- Version pattern validation
- Basic anti-downgrade protection
- Image existence verification in registry
v1.1.2 is a hotfix release that fixes critical bugs without changing the API or default behavior. All workflows using v1.1.1 can safely upgrade to v1.1.2 without any changes.
- Rebuild Downgrade Protection: Now correctly blocks downgrades like
25.12.08-2→25.12.08 - Private Registry Support: Image existence checks now work with private registries
- Deterministic Execution: No more temporary file race conditions
- Complete Error Reporting: All validation failures are reported, not just the first one
Simply update the version tag in your workflow:
# Before (v1.1.1 - buggy)
uses: dotCMS/ai-workflows/.github/workflows/deployment-guard.yml@v1.1.1
# After (v1.1.2 - fixed)
uses: dotCMS/ai-workflows/.github/workflows/deployment-guard.yml@v1.1.2No configuration changes needed! All parameters remain the same.
Severity: High Impact: Allowed downgrades that should be blocked
Scenario:
# Before: 25.12.08-2_abc123 (rebuild 2)
# After: 25.12.08_xyz789 (no rebuild = rebuild 0)v1.1.1 Behavior: ✅ Allowed (incorrectly)
- Extracted base version:
25.12.08==25.12.08→ Same version, allowed - Did NOT compare rebuild numbers
v1.1.2 Behavior: ❌ Blocked (correctly)
- Extracted base version:
25.12.08==25.12.08 - Extracted rebuild:
2>0→ Downgrade detected, blocked
Technical Details:
# v1.1.1 logic (BROKEN)
OLD_VERSION_NO_HASH="${OLD_TAG%%_*}" # 25.12.08-2
NEW_VERSION_NO_HASH="${TAG%%_*}" # 25.12.08
OLD_VERSION="${OLD_VERSION_NO_HASH%%-*}" # 25.12.08
NEW_VERSION="${NEW_VERSION_NO_HASH%%-*}" # 25.12.08
# Only compared: 25.12.08 == 25.12.08 → ✅ PASS (BUG!)
# v1.1.2 logic (FIXED)
OLD_BASE_VERSION=$(echo "$OLD_TAG" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') # 25.12.08
NEW_BASE_VERSION=$(echo "$TAG" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') # 25.12.08
# Compare base: 25.12.08 == 25.12.08
# Extract rebuilds: OLD=2, NEW=0
# Compare rebuild: 2 > 0 → ❌ BLOCKED (CORRECT!)Severity: Medium Impact: Non-deterministic failures, potential missed validations
Scenario: Multiple validation failures in same job run
v1.1.1 Behavior:
- Wrote
echo "false" > /tmp/validation_failed.txtfrom different points - Files could be left behind from previous runs
- Race conditions in concurrent validations
v1.1.2 Behavior:
- Uses in-memory bash arrays:
VALIDATION_FAILED=false,FAILED_IMAGES=() - Accumulates all failures before exiting
- Deterministic, no file system dependencies
Severity: High Impact: Validation failed for valid private registry images
Scenario: Using a mirror registry (e.g., mirror.gcr.io/dotcms/dotcms:25.12.08)
v1.1.1 Behavior: ❌ Failed
- Only checked Docker Hub:
docker manifest inspect dotcms/dotcms:25.12.08 - If image not in Docker Hub → validation failed
- Didn't fallback to full image path
v1.1.2 Behavior: ✅ Success
- First tries Docker Hub:
dotcms/dotcms:25.12.08 - If not found, tries full path:
mirror.gcr.io/dotcms/dotcms:25.12.08 - Gracefully handles both public and private registries
- v1.1.2: Current stable release (recommended) - Bug fixes
- v1.1.1: Previous release (deprecated - contains critical bugs)
- v1.1.0: Deprecated (use v1.1.2)
- v1.0.0: Deprecated (use v1.1.2)
For issues or questions:
- Report bugs: https://github.com/dotCMS/ai-workflows/issues
- Security issues: security@dotcms.com