-
Couldn't load subscription status.
- Fork 285
feat: add generic webhook receiver #4408
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
✅ Deploy Preview for docs-kargo-io ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4408 +/- ##
==========================================
+ Coverage 53.00% 53.14% +0.13%
==========================================
Files 356 357 +1
Lines 31605 31750 +145
==========================================
+ Hits 16751 16872 +121
- Misses 13990 14012 +22
- Partials 864 866 +2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
392eb0c to
2ff4eaa
Compare
api/v1alpha1/project_config_types.go
Outdated
| // GitRepoURL is a user-defined expression that should return a Git repository | ||
| // URL for which all subscribed Warehouses should be refreshed. If an empty | ||
| // string is returned, no Warehouses will be refreshed. If a non-empty string | ||
| // is returned, Git repo URL normalization will be applied before the URL is | ||
| // used to find Warehouses to refresh. | ||
| // | ||
| // +optional | ||
| GitRepoURL string `json:"gitRepoURL,omitempty" protobuf:"bytes,2,opt,name=gitRepoURL"` | ||
| // ImageRepoURL is a user-defined expression that should return a container | ||
| // image repository URL for which all subscribed Warehouses should be | ||
| // refreshed. If an empty string is returned, no Warehouses will be refreshed. | ||
| // If a non-empty string is returned, container image repo URL normalization | ||
| // will be applied before the URL is used to find Warehouses to refresh. | ||
| // | ||
| // +optional | ||
| ImageRepoURL string `json:"imageRepoURL,omitempty" protobuf:"bytes,3,opt,name=imageRepoURL"` | ||
| // ChartRepoURL is a user-defined expression that should return a Helm | ||
| // chart repository URL for which all subscribed Warehouses should be | ||
| // refreshed. If an empty string is returned, no Warehouses will be refreshed. | ||
| // If a non-empty string is returned, Helm chart repo URL normalization | ||
| // will be applied before the URL is used to find Warehouses to refresh. | ||
| // | ||
| // +optional | ||
| ChartRepoURL string `json:"chartRepoURL,omitempty" protobuf:"bytes,4,opt,name=chartRepoURL"` |
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.
Having separate fields for each of the supported repo types does two things:
-
It allows specifying separate repo URL extraction logic for each kind of repo, making it possible, for instance, for one generic receiver to process push events for multiple types of repos.
-
It allows us to know what kind of normalization process to apply to the URL, as the logic for normalizing each of Git, image, and chart URLs is different.
internal/webhook/external/generic.go
Outdated
| } | ||
| env["request"].(map[string]any)["body"] = parsedBody // nolint: forcetypeassert | ||
|
|
||
| program, err := expr.Compile(g.cfg.ArtifactPush.Predicate) |
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.
If I am understanding this correctly, a predicate is always required and it's not sufficient to declare e.g. artifactPush without one?
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.
As things stand currently, yes.
I had thought about blindly jumping into seeing if the other expressions evaluate to anything, but that seems to invite in the possibility that one or more of those expressions do coincidentally evaluate to something, but the actual event we're being notified of is not one of interest.
By way of example, ignore for a moment that we have a dedicated receiver for GitHub, and imagine we're using a generic receiver to handle incoming webhooks from there. Nearly all event types include repository.url in the payload. The predicate request.header('X-GitHub-Event') == 'push' would prevent us from blindly reading repository.url from an event that turned out to be, for instance, someone adding a comment to an issue.
Please note that I think this works well, but I'm not entirely convinced that there isn't a more ergonomic option I am overlooking, so if you have ideas, I'm totally open to them.
Signed-off-by: Kent Rancourt <kent.rancourt@gmail.com>
Signed-off-by: Kent Rancourt <kent.rancourt@gmail.com>
Signed-off-by: Kent Rancourt <kent.rancourt@gmail.com>
Signed-off-by: Kent Rancourt <kent.rancourt@gmail.com>
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
5669816 to
f7bf66c
Compare
Signed-off-by: Hidde Beydals <hidde@hhh.computer>
|
There's too much discussion to be had about this for this to reasonably make it into 1.7.0. Deferring to v1.8.0. |
|
@fuskovic you've worked extensively on the webhook receivers and have worked quite a bit with expressions recently. You're sitting right at the intersection of the things involved in this... I'm going to turn this over to to you. Feel free to either build on what I've done or scrap it and start fresh if that's what ends up making more sense, but either way, don't start any work on this until we have 1.8 buttoned up and until you, @hiddeco, and I can meet to hammer out what a reasonable UX looks like here... previous conversation between @hiddeco and myself was offline, but revealed that there are a lot small concerns that aren't addressed by this PR. |
|
Closing in favor of #5305 |
Fixes #4486
Example usage using expr-lang:
Example usage using exact matches:
Note the API was designed with future expansion in mind. For instance, if handling of events representing the merge of a PR were added in the future, the above could be updated without any interference to what it's already doing: