-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Allow tags from GitHub webhooks #3546
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
This looks like a great PR. It needs to at least have a test that shows what wasn't working before, but does work now. I'm +1 on it though! |
8ca0809
to
0859712
Compare
Well, the current tests didn't really check this functionality, |
@@ -335,17 +335,20 @@ class IntegrationsTests(TestCase): | |||
def setUp(self): | |||
self.project = get(Project) | |||
self.version = get(Version, verbose_name='master', project=self.project) | |||
self.version_tag = get(Version, verbose_name='v1.2', project=self.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.
This really doesn't make any difference to the current tests
{'ref': 'refs/tags/v1.2'}, | ||
format='json', | ||
) | ||
trigger_build.assert_has_calls( |
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.
This just test if the method was called, no if the branch/tag was correctly parsed
@ericholscher After fighting with the mocks, the tests are ready 😊 |
trigger_build.assert_has_calls( | ||
[mock.call(force=True, version=self.version, project=self.project)]) | ||
|
||
@mock.patch('readthedocs.restapi.views.integrations.WebhookMixin.get_response_push', return_value=None) |
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.
Here the return value is None, since we only care to test if the ref value is parsed correctly, the other test covers the all flow
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.
Since what you want to test is the parsing, instead of writing the test in this way, why not avoid mocking this function and calling it for real and assert the return value with the one that it's expected?
Like this:
wm = WebhookMixin()
assertEqual(wm._normalize_ref('refs/heads/master'), 'master')
It's clearer this way.
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 wasn't sure if that way was the correct 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.
Thanks for this PR!
I didn't find anything that it's wrong, but I left some suggestions on the comments.
@@ -751,7 +751,8 @@ def versions_from_branch_name(self, branch): | |||
return ( | |||
self.versions.filter(identifier=branch) | | |||
self.versions.filter(identifier='remotes/origin/%s' % branch) | | |||
self.versions.filter(identifier='origin/%s' % branch) | |||
self.versions.filter(identifier='origin/%s' % branch) | | |||
self.versions.filter(verbose_name=branch) |
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 think this could return duplicated values when the identifier
and the verbose name
are the same, right? Maybe we should use here the .distinct()
On the other hand, I don't follow why we need to add this line here, hehe. Can you clarify?
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.
Tags are saved this way: {identifier: hash, verbose_name: tagname}.
GitHub only provides the tag name on the ref.
The only case were I think duplicate values may occur is for branches, since the identifier isn't a hash like they are for tags. I'm going to research a little.
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 is what I found, looks like the querysets are really sets p:
>>> p.versions.filter(identifier=branch)
[<Version: Version awesome of Read The Docs (8)>]
>>> p.versions.filter(verbose_name=branch)
[<Version: Version awesome of Read The Docs (8)>]
>>> p.versions.filter(identifier=branch) | p.versions.filter(verbose_name=branch)
[<Version: Version awesome of Read The Docs (8)>]
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.
They aren't really sets. In fact, that's why the distinct
is: https://docs.djangoproject.com/en/2.0/ref/models/querysets/#django.db.models.query.QuerySet.distinct
Anyway, it seems that we are not bitten by this problem here.
[mock.call(force=True, version=mock.ANY, project=self.project)]) | ||
[mock.call(force=True, version=self.version, project=self.project)]) | ||
|
||
client.post( |
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.
Write this as a separte test for tag
and rename this one for branch
since they the branch was working previously and we are adding a new feature. It's good to each test written to try a specific thing.
trigger_build.assert_has_calls( | ||
[mock.call(force=True, version=self.version, project=self.project)]) | ||
|
||
@mock.patch('readthedocs.restapi.views.integrations.WebhookMixin.get_response_push', return_value=None) |
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.
Since what you want to test is the parsing, instead of writing the test in this way, why not avoid mocking this function and calling it for real and assert the return value with the one that it's expected?
Like this:
wm = WebhookMixin()
assertEqual(wm._normalize_ref('refs/heads/master'), 'master')
It's clearer this way.
|
||
client.post( | ||
'/api/v2/webhook/github/{0}/'.format(self.project.slug), | ||
{'ref': 'refs/tags/v1.0'}, |
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: move this cases to a specific test.
@humitos all corrections were made, thanks again! |
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.
Good job! It's ready to be merged for me.
8586e29
to
49fadeb
Compare
Nothing change on this PR, just rebase to the current master :) |
This closes #3508
This is just a proposal, since I'm not sure if this is the best way of do it (since various methods are named branch* and no tags o versions, e.g.
versions_from_branch_name
)The GitHub payload looks like this when a tag is pushed:
If the tag isn't registered on rtd active versions (recent created tags), the build isn't triggered; but if the tag is forced on the gh repo and the tag is an active version, the build is triggered.