Env Compare & Bulk Ops
Compare configurations across environments and perform bulk image updates across tenants.
Overview
As projects grow in complexity — more tenants, more environments, more services — keeping configurations consistent and performing coordinated updates becomes a challenge. GitOpsHQ provides two tools to address this:
- Environment Compare — Side-by-side comparison of configurations across environments
- Bulk Image Update — Coordinated image tag changes across multiple tenants and environments
Both features work alongside the webhook system for CI/CD automation.
Environment Compare
UI Route: /projects/:slug/compare
Environment Compare provides a structured, side-by-side view of how configurations differ between any two environments within a project. It is the primary tool for pre-promotion verification — answering the question: "What will change when I promote from staging to production?"
Accessing the Compare View
Open the Project
Navigate to the project and select the Compare tab in the project navigation.
Select Source and Target Environments
Use the dropdown selectors to choose:
- Source Environment: The environment you're comparing from (e.g.,
staging) - Target Environment: The environment you're comparing to (e.g.,
production)
Review the Diff
The compare view renders a diff grouped by tenant and service, showing all configuration differences between the two environments.
What is Compared
The compare view analyzes differences across multiple dimensions:
| Dimension | Description |
|---|---|
| Helm Values | Per-service Helm values differences between environments |
| Image Tags | Container image versions deployed in each environment |
| HQ Variables | Environment-scoped variable values |
| Kustomize Overlays | Per-tenant-environment overlay differences |
| Manifest Overlays | Per-tenant-environment raw manifest differences |
| Chart Versions | Helm chart versions if they differ between environments |
Diff Format
The diff is presented in a familiar unified diff format:
# Tenant: acme-corp / Service: api
# Helm Values Diff
- replicaCount: 2
+ replicaCount: 3
- image:
- tag: "v1.4.0"
+ image:
+ tag: "v1.3.8"
- resources:
- limits:
- memory: "512Mi"
+ resources:
+ limits:
+ memory: "1Gi"Lines prefixed with - exist in the source environment but not the target. Lines prefixed with + exist in the target but not the source.
Filtering and Navigation
| Filter | Description |
|---|---|
| By Tenant | Show diffs for a specific tenant only |
| By Service | Show diffs for a specific workload only |
| By Diff Type | Filter to only image tag changes, value changes, or overlay changes |
| Changed Only | Hide sections with no differences (default: on) |
Use Cases
| Scenario | How to Use Compare |
|---|---|
| Pre-promotion check | Compare staging → production before promoting a release |
| Debugging inconsistencies | Compare dev → staging to find why a service behaves differently |
| Audit trail | Verify that production matches staging after a promotion |
| Onboarding review | Compare a new tenant's dev config against an established tenant |
Environment Compare is read-only. To act on the differences you see, navigate to the values editor or create a release.
Bulk Image Update
UI Route: /projects/:slug/bulk-update
Bulk Image Update allows you to change container image tags across multiple tenants and environments in a single atomic operation. Instead of editing values for each tenant-environment-service combination individually, you select the scope and apply the update in one action.
Performing a Bulk Update
Open Bulk Update
Navigate to the project and select the Bulk Update tab.
Select the Workload
Choose which workload (service) you want to update. This filters the view to show only service deployments for that workload.
Select Target Scope
Use the tenant and environment checkboxes to select which combinations should receive the update.
| Selector | Behavior |
|---|---|
| Select All Tenants | All tenants across selected environments |
| Select All Environments | All environments for selected tenants |
| Individual Checkboxes | Precise control over which tenant-environment pairs to update |
Specify New Image Tag
Enter the new image tag (e.g., v1.5.0, sha-abc1234, latest).
Preview Changes
Before committing, GitOpsHQ shows a preview of all changes:
Changes to commit:
├── tenants/acme-corp/dev/api/values.yaml image.tag: v1.4.0 → v1.5.0
├── tenants/acme-corp/staging/api/values.yaml image.tag: v1.3.8 → v1.5.0
├── tenants/beta-inc/dev/api/values.yaml image.tag: v1.4.0 → v1.5.0
└── tenants/beta-inc/staging/api/values.yaml image.tag: v1.3.8 → v1.5.0
Total: 4 files changedCommit
Click Apply to create a single Git commit with all image tag changes. The commit message includes the workload name, new tag, and affected scope.
Bulk updates bypass the release workflow by default — changes are committed directly to the hosted repository. If your project requires releases for all changes, coordinate bulk updates with your release process.
Image Update Webhook
Endpoint: POST /api/v1/webhooks/image-update
The image update webhook automates bulk image updates from CI/CD pipelines. When your CI pipeline builds and pushes a new container image, it can notify GitOpsHQ to update matching service deployments automatically.
Webhook Configuration
Configure the webhook in Project Settings → Webhooks → Image Update:
| Setting | Description |
|---|---|
| Shared Secret | HMAC secret for signature verification |
| Auto-Update Policy | Which environments to auto-update (e.g., only dev and staging) |
| Image Filter | Regex pattern to match image repositories (e.g., ghcr.io/myorg/.*) |
| Tag Filter | Regex pattern to match accepted tag formats (e.g., ^v\d+\.\d+\.\d+$) |
Request Format
{
"image": "ghcr.io/myorg/api",
"tag": "v1.5.0",
"digest": "sha256:abc123...",
"project": "my-project",
"workload": "api",
"environments": ["dev", "staging"],
"tenants": ["*"],
"timestamp": "2026-03-27T10:30:00Z"
}Authentication
The webhook uses HMAC-SHA256 signature verification:
X-GitOpsHQ-Signature: sha256=<HMAC-SHA256(shared_secret, request_body)>Replay Protection
GitOpsHQ prevents replay attacks by:
- Requiring a
timestampfield in the payload - Rejecting requests older than 5 minutes
- Storing processed request hashes in a shared store and rejecting duplicates
Response Codes
| Status | Meaning |
|---|---|
200 OK | Image update accepted and committed |
202 Accepted | Image update queued (async processing) |
400 Bad Request | Invalid payload or missing required fields |
401 Unauthorized | Invalid or missing signature |
404 Not Found | Project or workload not found |
409 Conflict | Duplicate request (replay protection) |
422 Unprocessable | Tag or image does not match configured filters |
CI/CD Integration Examples
- name: Notify GitOpsHQ of new image
run: |
BODY='{"image":"ghcr.io/myorg/api","tag":"${{ github.sha }}","project":"my-project","workload":"api","environments":["dev"],"tenants":["*"],"timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}'
SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "${{ secrets.GITOPSHQ_WEBHOOK_SECRET }}" | sed 's/.* //')
curl -X POST https://app.gitopshq.io/api/v1/webhooks/image-update \
-H "Content-Type: application/json" \
-H "X-GitOpsHQ-Signature: sha256=$SIGNATURE" \
-d "$BODY"notify_gitopshq:
stage: deploy
script:
- BODY='{"image":"registry.gitlab.com/myorg/api","tag":"'"$CI_COMMIT_SHORT_SHA"'","project":"my-project","workload":"api","environments":["dev"],"tenants":["*"],"timestamp":"'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"}'
- SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$GITOPSHQ_WEBHOOK_SECRET" | sed 's/.* //')
- 'curl -X POST https://app.gitopshq.io/api/v1/webhooks/image-update -H "Content-Type: application/json" -H "X-GitOpsHQ-Signature: sha256=$SIGNATURE" -d "$BODY"'stage('Notify GitOpsHQ') {
steps {
script {
def body = """{"image":"docker.io/myorg/api","tag":"${env.BUILD_TAG}","project":"my-project","workload":"api","environments":["dev"],"tenants":["*"],"timestamp":"${new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone('UTC'))}"}"""
def secret = credentials('gitopshq-webhook-secret')
def signature = sh(script: "echo -n '${body}' | openssl dgst -sha256 -hmac '${secret}' | sed 's/.* //'", returnStdout: true).trim()
httpRequest(
url: 'https://app.gitopshq.io/api/v1/webhooks/image-update',
httpMode: 'POST',
contentType: 'APPLICATION_JSON',
customHeaders: [[name: 'X-GitOpsHQ-Signature', value: "sha256=${signature}"]],
requestBody: body
)
}
}
}ArgoCD Webhook
Endpoint: POST /api/v1/webhooks/argocd
The ArgoCD webhook receives sync status events from ArgoCD notification triggers. This provides a secondary channel for status updates alongside the agent's gRPC reporting.
Configuration
- In ArgoCD, configure a notification trigger that sends HTTP webhooks on sync events
- Point the webhook URL to your GitOpsHQ instance's ArgoCD webhook endpoint
- Configure the HMAC shared secret in both ArgoCD and GitOpsHQ
Payload Format
{
"app": {
"metadata": {
"name": "my-project-acme-corp-dev-api",
"namespace": "argocd"
},
"status": {
"sync": {
"status": "Synced",
"revision": "abc123def456"
},
"health": {
"status": "Healthy"
}
}
},
"timestamp": "2026-03-27T10:35:00Z"
}GitOpsHQ parses the application name to identify the project, tenant, environment, and service, then updates the corresponding deployment status.
Best Practices
| Practice | Recommendation |
|---|---|
| Always compare before promoting | Use Environment Compare to verify expected changes before running a promotion |
| Use webhooks for CI-triggered updates | Automate image tag updates rather than manually running bulk updates |
| Limit auto-update environments | Configure webhooks to auto-update only dev (and optionally staging). Require manual promotion to production. |
| Combine with approval policies | Use approval policies on production environments so webhook-triggered changes still require human review for production deployment |
| Monitor webhook deliveries | Check webhook delivery logs for failed or rejected requests. A high failure rate may indicate misconfigured secrets or payload issues. |
| Use tag filters | Configure tag filters on webhook endpoints to reject non-semver or non-compliant tags from being deployed |
Related Pages
- Tenant Management — Manage service deployments per tenant-environment
- Drift Detection — Detect configuration divergence after bulk updates
- API Keys and Automation — Configure API keys for webhook authentication
- Dashboard — Monitor the impact of bulk operations