-
Notifications
You must be signed in to change notification settings - Fork 0
feat: implement deployment guard workflow #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- 4-step validation: file allowlist → image-only → image validation → finalize - Only allows changes to dotCMS container image field - Validates image repository, tag pattern, and existence - Workflow-based control - Supports configurable patterns and repositories
- Handle .ya?ml pattern correctly by converting to (yaml|yml) - Use # as sed delimiter to avoid conflicts with pipe character - Tested on both macOS and Linux sed variants
BREAKING CHANGE: Workflow renamed from deutsche-bank-guard.yml to deployment-guard.yml Features: - More generic workflow name for reusability across projects - Configurable validation checks via enable_* parameters - Optional repository allowlist (skipped if empty) - Flexible defaults for different use cases Enabled checks (all true by default): - enable_file_allowlist: Validate only allowed files changed - enable_image_only_check: Ensure only image field modified - enable_image_validation: Validate image repo, format, version Configuration parameters now optional with sensible defaults: - allowed_files_pattern: defaults to '**/*' (all files) - allowed_image_repositories: defaults to '' (no restriction) - allowed_version_pattern: defaults to '.*' (any version) - verify_image_existence: defaults to false Example configurations: 1. Deutsche Bank (strict): All checks enabled, specific patterns 2. Generic use: Only file allowlist or image validation 3. Flexible: Mix and match checks as needed
- Remove unused variables (ALL_ALLOWED, ALL_PASS, ALL_VALID, DISALLOWED_FILES, NEW_IMAGES) - Replace 'cat file | cmd' with 'cmd < file' pattern - Add -r flag to all read commands to properly handle backslashes This fixes all actionlint/shellcheck warnings while maintaining functionality.
The previous conversion of ** to .* was incorrect - it would match any characters but wouldn't properly match path segments with slashes. Changed ** → ([^/]+/)* to properly match zero or more path segments. Example: - Pattern: kubernetes/dotcms/**/statefulset.yaml - Now matches: kubernetes/dotcms/poc/uat/statefulset.yaml - Regex: kubernetes/dotcms/([^/]+/)*statefulset\.(yaml|yml) This fixes file allowlist validation for nested directories.
Two critical fixes: 1. Replace **/ as a unit (not just **) to avoid extra slash 2. Remove backslash escape from | in grep -E (it's an alternation operator) The pattern kubernetes/dotcms/**/statefulset.yaml now correctly converts to: kubernetes/dotcms/([^/]+/)*statefulset\.(yaml|yml) This properly matches: - kubernetes/dotcms/statefulset.yaml (zero subdirs) - kubernetes/dotcms/poc/statefulset.yaml (one subdir) - kubernetes/dotcms/poc/uat/statefulset.yaml (two subdirs) Fixes file allowlist validation for all directory depths.
Changes: - Renamed parameter: trusted_github_team → trusted_github_teams (plural) - Added support for comma-separated list of teams - Check membership in ANY team (short-circuit on first match) - Added matched-team output to track which team granted bypass - Updated PR comments to show matched team - Updated logs to show all teams being checked This allows using existing GitHub teams (platform-engineers, dotSysadmins, cloudeng-support) without creating new teams. Validates with actionlint ✅
Due to GitHub API limitations, GITHUB_TOKEN cannot check organization team membership. Changed implementation to verify repository permission levels instead: - Users with 'admin' or 'maintain' permissions can bypass validations - These permissions typically align with membership in trusted teams - No additional tokens or secrets required - More straightforward and maintainable solution This approach works because: - platform-engineers team has Admin permission - dotSysadmins team has Maintain permission - cloudeng-support team has Write permission (will need Maintain for bypass) - All team members with sufficient permissions can bypass checks
…ogic Add optional testing parameter to force non-bypass mode, allowing us to test validation logic even with users who have admin/maintain permissions. This enables comprehensive testing of: - File allowlist validation - Image-only change validation - Image version validation - Multiple field change detection The parameter: - Defaults to false (normal operation) - Can be enabled for testing purposes - Clearly marked in logs when active - Can safely remain in production code
Switch from repository permission-based bypass to organization membership checking for simpler and more flexible access control. Changes: - Replace trusted_github_teams input with trusted_organization - Use checkPublicMembershipForUser API (works with GITHUB_TOKEN) - Update all job references from check-team-membership to check-org-membership - Update PR comment to reference organization membership - Update outputs: is-org-member, organization (instead of is-team-member, matched-team) - Add helpful troubleshooting messages for public membership requirement Benefits: - No additional tokens required (works with GITHUB_TOKEN) - More flexible: any org member can have bypass (not just admin/maintain) - Clearer intent: organization membership = trusted - Better error messages: guides users to make membership public Requirements: - Organization membership must be set to PUBLIC visibility - Users can make their membership public at github.com/orgs/ORG/people
Remove redundant 'automatically approved' message from PR comment when user has organization membership bypass. The bypass status is already clearly indicated in the main message, no need for additional validation complete section.
|
|
||
| if [ -z "$CHANGED_FILES" ]; then | ||
| echo "No YAML files changed" | ||
| echo "files=" >> "$GITHUB_OUTPUT" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should files be json or is empty string ok?
echo "files=[]" >> "$GITHUB_OUTPUT"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yolabingo GiTHUB_OUTPUT acts like an appendable properties file it is not yaml.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now though we are treating the value as yaml.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The else case there (if files are found) returned a json array. I wasn't sure if whatever ingested this output assumed that files would contain json.
| HEAD_SHA="${{ github.event.pull_request.head.sha }}" | ||
| else | ||
| BASE_SHA="origin/${{ github.event.repository.default_branch }}" | ||
| HEAD_SHA="HEAD" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chatGPT suggested this, not sure if it is correct:
On push events, BASE_SHA/HEAD_SHA didn’t correctly reflect the commit range
Better to use ${{ github.event.before }} and ${{ github.event.after }}
yolabingo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some comments but approved to keep you unblocked.
Resolve review comments from @yolabingo: 1. Use JSON empty array [] instead of empty string for files output when no YAML files are changed. This ensures consistent JSON format for downstream processing. 2. For push events, use github.event.before and github.event.after instead of default branch comparison. This provides the correct commit range for push events as suggested.
|
Thanks @yolabingo for the review feedback! I've addressed both comments in commit 3c86caf:
Both changes improve correctness and data handling. Please let me know if there's anything else to address! |
Deployment Guard Workflow - Initial Release
Summary
This PR introduces a new reusable workflow called
deployment-guard.ymlthat provides configurable deployment validation for Kubernetes manifests. The workflow enforces guardrails around file changes, YAML structure modifications, and container image updates.Key Features
🔧 Configurable Validation Checks
Three independent validation stages that can be enabled/disabled:
File Allowlist (
enable_file_allowlist)Image-Only Changes (
enable_image_only_check)Image Validation (
enable_image_validation)📦 Flexible Configuration
All parameters are optional with sensible defaults:
🎯 Use Cases
Strict Validation (all checks enabled):
File Allowlist Only:
Image Validation Only:
Implementation Details
4-Stage Validation Pipeline
validate-changed-files (conditional)
validate-image-only-changed (conditional)
validate-images (conditional)
finalize-validation (always runs)
Cross-Platform Compatibility
#as sed delimiter for macOS/Linux compatibility10#prefix.yamland.ymlextensions**,*,?Security Features
Testing
Comprehensive test coverage includes:
Next Steps
After merging:
Create version tag:
git checkout main git pull origin main git tag -a v1.0.0 -m "Release: Deployment Guard v1.0.0" git push origin v1.0.0Update downstream repositories to reference
@v1.0.0Configure branch protection rules to require status checks
Documentation
Complete documentation available in consuming repositories:
Release Version: v1.0.0
Issue: #339
Type: New Feature