Skip to content

feat: implement webhook receiver for Docker, GHCR and Harbor to receive triggers for image update #1159

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

binhnguyenduc
Copy link

This PR is to address #1 and is essentially a continuation of #284

This pull request introduces a webhook server to handle container registry events, enabling automated image updates in ArgoCD applications. Key changes include adding webhook server functionality, integrating registry-specific webhook handlers, and providing configuration options for the webhook server.

Webhook Server Implementation:

  • Added webhook server functionality: Implemented a new WebhookServer class to handle registry events, including initialization, event handling, and graceful shutdown. (cmd/main.go, cmd/run.go, pkg/webhook/docker.go, pkg/webhook/docker_test.go) [1] [2] [3] [4] [5] [6]
  • Introduced WebhookOptions and CLI command: Added a new webhook CLI command with configuration options such as port, registry secrets, and ArgoCD integration settings. (cmd/webhook.go)

Registry-Specific Webhook Handlers:

  • Docker Hub webhook handler: Created a handler for Docker Hub registry events, including payload validation using HMAC-SHA256 signatures and event parsing. (pkg/webhook/docker.go, pkg/webhook/docker_test.go) [1] [2]

Configuration Enhancements:

  • Updater configuration: Introduced UpdaterConfig to encapsulate settings for image updates, such as Git commit details and concurrency limits. (pkg/argocd/updater_config.go)

Integration with ArgoCD:

  • ArgoCD client initialization: Added logic to initialize ArgoCD clients based on the application API kind (kubernetes or argocd) for webhook server operations. (cmd/run.go, cmd/webhook.go) [1] [2]

These changes collectively enhance the automation capabilities of the ArgoCD Image Updater by enabling it to respond to registry events and update applications accordingly.

I've also made sure to address concerns from the original PR:

  • the feature is guarded behind a flag enable-webhook and is off by default
  • user can set their own port via webhook-port

I have not update the manifests to add new Service and Ingress. If needed, let me know.

Disclaimer: the integration with Harbor is well tested and currently running on our own cluster. Unfortunately, I don't have access to Dockerhub and GHCR to test thoroughly, so any help is welcomed.

@Copilot Copilot AI review requested due to automatic review settings June 4, 2025 10:34
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds webhook server functionality to the image updater, enabling it to respond to container registry events (Docker Hub, GHCR, Harbor) and trigger ArgoCD application updates. Key changes include the implementation of a dedicated WebhookServer and multiple registry-specific webhook handlers with associated tests, as well as CLI configuration enhancements.

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/webhook/webhook*.go Core webhook handler definitions and registry type detection
pkg/webhook/server.go New HTTP server implementation for webhook requests
pkg/webhook/harbor.go Added Harbor registry webhook handler and payload parsing
pkg/webhook/ghcr.go Added GHCR webhook handler with validation and payload parsing
pkg/webhook/docker*.go Docker Hub webhook handler and tests
pkg/argocd/updater_config.go New updater configuration for image update operations
cmd/webhook.go New CLI command for starting the webhook server
cmd/run.go & cmd/main.go Integration of the webhook server into the main application flow

if err != nil {
return nil, fmt.Errorf("failed to read request body: %w", err)
}
fmt.Printf("Received Harbor webhook payload: %s", string(body))
Copy link
Preview

Copilot AI Jun 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider replacing fmt.Printf with the project's logging utility (e.g. log.Infof) for consistency in logging throughout the codebase.

Suggested change
fmt.Printf("Received Harbor webhook payload: %s", string(body))
log.Infof("Received Harbor webhook payload: %s", string(body))

Copilot uses AI. Check for mistakes.

Comment on lines +44 to +51
body, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}

// Reset body for later reading
r.Body = io.NopCloser(strings.NewReader(string(body)))

Copy link
Preview

Copilot AI Jun 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The pattern for reading and then resetting the request body is repeated across several webhook validation methods. Consider extracting this logic into a shared helper function to reduce duplication and maintain consistency.

Suggested change
body, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}
// Reset body for later reading
r.Body = io.NopCloser(strings.NewReader(string(body)))
body, err := readAndResetBody(r)
if err != nil {
return fmt.Errorf("failed to read request body: %w", err)
}

Copilot uses AI. Check for mistakes.

@codecov-commenter
Copy link

codecov-commenter commented Jun 4, 2025

Codecov Report

Attention: Patch coverage is 51.41956% with 308 lines in your changes missing coverage. Please review.

Project coverage is 60.85%. Comparing base (975081e) to head (46aae4d).

Files with missing lines Patch % Lines
pkg/webhook/server.go 0.00% 141 Missing ⚠️
cmd/webhook.go 27.65% 67 Missing and 1 partial ⚠️
cmd/run.go 3.22% 60 Missing ⚠️
pkg/webhook/harbor.go 89.83% 9 Missing and 3 partials ⚠️
pkg/argocd/updater_config.go 0.00% 11 Missing ⚠️
pkg/webhook/docker.go 91.78% 4 Missing and 2 partials ⚠️
pkg/webhook/ghcr.go 94.17% 4 Missing and 2 partials ⚠️
pkg/webhook/webhook.go 87.09% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1159      +/-   ##
==========================================
- Coverage   63.34%   60.85%   -2.49%     
==========================================
  Files          15       22       +7     
  Lines        2357     2989     +632     
==========================================
+ Hits         1493     1819     +326     
- Misses        769     1066     +297     
- Partials       95      104       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…ve update of image pushes and trigger application updates

Signed-off-by: Binh Nguyen <binh.nguyen@encapital.io>
@chengfang
Copy link
Collaborator

UpdaterConfig in pkg/argocd/updater_config.go: is it possible to use other existing struct, instead of creating a new one?

webhook secrets: can we keep them in a secret file, similar to https://argo-cd.readthedocs.io/en/latest/operator-manual/webhook/#2-configure-argo-cd-with-the-webhook-secret-optional ?

@chengfang
Copy link
Collaborator

I have not update the manifests to add new Service and Ingress. If needed, let me know.

Yes, the service, ingress and related manifests would be great to have.

@chengfang
Copy link
Collaborator

How do you currently use this feature, using the standalone run command with webhook enabled, or using the standalone webhook command, or run image updater workload in cluster with webhook enabled?

@binhnguyenduc
Copy link
Author

I have not update the manifests to add new Service and Ingress. If needed, let me know.

Yes, the service, ingress and related manifests would be great to have.

I'll update as soon as I can

@binhnguyenduc
Copy link
Author

How do you currently use this feature, using the standalone run command with webhook enabled, or using the standalone webhook command, or run image updater workload in cluster with webhook enabled?

Currently, we enable webhook with the run command (via env var) and reduce the interval to 30m or 60m. That way, we have both the webhook trigger and registry scanner running side by side. One way is to potentially run the webhook command, with the registry scanner off altogether, but we haven't actually done that in production.

@binhnguyenduc
Copy link
Author

UpdaterConfig in pkg/argocd/updater_config.go: is it possible to use other existing struct, instead of creating a new one?

webhook secrets: can we keep them in a secret file, similar to https://argo-cd.readthedocs.io/en/latest/operator-manual/webhook/#2-configure-argo-cd-with-the-webhook-secret-optional ?

I'll see what I can do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants