-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Support for generic webhooks #8522
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
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.
Looks like a good first approach to me. I did a non-complete review for now and I left some comments.
if not self.version or self.version.type != EXTERNAL: | ||
send_notifications.delay(version_pk, build_pk=build_pk, email=email) | ||
build_tasks.send_build_notifications.delay( |
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.
Actually, we may want to add this as a config for the Webhook. Like a checkbox for Send notifications on PRs
so the user can decide whether or not to send them instead of us deciding by them.
c93065a
to
fd27634
Compare
2d05db6
to
9843252
Compare
HttpExchange.objects.from_requests_exchange( | ||
response=response, | ||
related_object=webhook, | ||
) |
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.
We could create this object in two steps, before sending the request and updating it after the request was made. This is so we save the exchange even if the request failed (like timeout).
model = WebHook | ||
fields = ['project', 'url', 'events', 'payload', 'secret'] | ||
widgets = { | ||
'events': forms.CheckboxSelectMultiple, |
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.
readthedocs/projects/models.py
Outdated
'${event}': event, | ||
'${build.id}': build.id, | ||
'${build.commit}': build.commit or '', | ||
'${organization.name}': organization_name, | ||
'${organization.slug}': organization_slug, | ||
'${project.slug}': project.slug, | ||
'${project.name}': project.name, | ||
'${version.slug}': version.slug, | ||
'${version.name}': version.verbose_name, |
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.
don't know what others substitutions would be useful
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.
URLs: project, version, build on Read the Docs and, maybe on VCS
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.
added some urls, but most of that information can be built using the pk or slug of the models.
</p> | ||
|
||
{% if has_old_webhooks %} | ||
<p class="help_text"> |
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.
These could have a "warning" class or something more prominent, but don't think we are using a class like that in somewhere else.
@@ -0,0 +1,39 @@ | |||
{% extends "projects/project_edit_base.html" %} |
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.
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.
Is there a way to share the same file instead of copy/paste?
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 body could be moved to another file. But I do see this having more options (like retry the webhook), so don't know.
|
||
{# If the webhook was created from the old implementation, it doesn't have a custom payload. #} | ||
{% if object.pk and not object.payload %} | ||
<p class="help_text"> |
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.
same here, could be a warning class or something
Think this should be ready for review, only docs are missing. |
readthedocs/projects/models.py
Outdated
substitutions = { | ||
'${event}': event, | ||
'${build.id}': build.id, | ||
'${build.commit}': build.commit or '', |
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.
was thinking we could have ${build.commit.short}
to display only the 7/8 first chars of the commit.
def __init__(self, version, build, event): | ||
self.version = version | ||
self.build = build | ||
self.project = version.project |
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.
Why this requires version
and build
? It should be enough just with the build
.
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 old code was sending the build and version pk separately, don't know if there is a case where a build doesn't have the version attached.
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.
Is it still required with the new code after the refactor? Can we remove it?
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 have no idea why the old code required it, so not sure about changing that on this PR.
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.
First of all, the PR's description looks awesome! 💯 --It helped me a lot to understand all the changes.
I'd say that all the future improvements could be an issue/issues. Besides, together with those improvements, I think we will also want a way to send extra HTTP headers together with a custom body.
The PR looks great! The only thing I'd like to change before merging, is the substitution syntax (${variable}
) to use the Django Template syntax instead ({{ variable }}
) which is more known.
@@ -0,0 +1,39 @@ | |||
{% extends "projects/project_edit_base.html" %} |
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.
Is there a way to share the same file instead of copy/paste?
readthedocs/projects/models.py
Outdated
'${event}': event, | ||
'${build.id}': build.id, | ||
'${build.commit}': build.commit or '', | ||
'${organization.name}': organization_name, | ||
'${organization.slug}': organization_slug, | ||
'${project.slug}': project.slug, | ||
'${project.name}': project.name, | ||
'${version.slug}': version.slug, | ||
'${version.name}': version.verbose_name, |
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.
URLs: project, version, build on Read the Docs and, maybe on VCS
that can be done with some duplication, this is creating a webhook for each event just changing the payload. But, I think the most common case for slack notifications is failed builds. |
I feel like we've been talking about this for a long time. I'd like to propose the following path forward:
I feel like this is the path forward, but this PR has gotten overwhelming, and we should just get this baseline feature merged. |
Is that with one space around the name? Or is it using the template engine from django to support all variations? |
1 or 0 spaces. Should be simple enough to implement (eg. just loop over the list of replacements twice). |
$foo -> {{ foo }}
Changed to allow |
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.
Let's move this forward 👍
Co-authored-by: Eric Holscher <[email protected]>
Co-authored-by: Santos Gallegos <[email protected]>
Document generic webhooks
Currently we support webhooks to notify external services when a build starts/fails. The problem with this is that most of the time users want a quick integration with slack or whatever, but those services require you to send a payload with a determined format (usually just a json body). So, in order to have that, users need to implement a proxy between our webhooks and the service they want to use. In order to provide more flexibility and easy to integrate webhooks I'm reworking our current implementation like so:
To make it more easy, we could document or suggest some "quick templates" for users to use, like a nice notification for slack or discord and some step by step tutorials https://api.slack.com/messaging/webhooks https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks
Moving webhooks to their own page
Currently, we have webhooks under the "Notifications" tab,
there they are mixed with email notifications.
In order to have a better UI, I have moved the webhooks to its own page instead,
and renamed the other section as "Email notifications".
And to avoid having two pages to manage the webhooks,
the old and new webhooks can be accessed from the same page.
I have added some checks to see if the user has old webhooks and show a note
that those have been moved to the other page.
Old webhooks don't have a custom payload, but instead will be using the defined payload from https://docs.readthedocs.io/en/stable/guides/build-notifications.html#using-webhook.
Users can migrate to a custom payload by just editing the webhook,
we don't support creating webhooks from the old implementation.
Screenshots
Some confusing documentation...
So, in our docs we have a
webhooks
page https://docs.readthedocs.io/en/stable/webhooks.html,but they are about the webhook we provide in order for vcs services to notify us when a new branch/tag is created or when new changes are pushed so we can build the docs for those. We actually refer to those as "integrations" rather than webhooks in our codebase/docs.
The actual webhooks docs are in a page called "build notifications"
https://docs.readthedocs.io/en/stable/guides/build-notifications.html.
Which make sense, but we could expand our webhooks to listen to more events outside builds.
Future improvements
without having to delete the webhook in order to stop sending events to it.
Right now we don't send notifications on builds from external versions,
doing this by default could be too spammy.
Currently, we send webhooks for any version on the subscribed events
(but I do see having people only want to be notified about changes on master for example).
Users could implement a proxy to filter those, or we could implement a filter in our side so they don't need to maintain that.
Closes #6942