-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Allow to skip a build on commit messages #3457
Conversation
Marks proposed: - [skip doc] - [skip docs] - [docs skip] - [doc skip]
@@ -159,7 +167,13 @@ def handle_webhook(self): | |||
# Handle push events and trigger builds | |||
if event == GITHUB_PUSH: | |||
try: | |||
branches = [self.data['ref'].replace('refs/heads/', '')] | |||
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 change branch to be a dict with name
and last_commit
as elements.
last_commit
must have an id
and message
.
branch = { | ||
'name': self.request.data['ref'].replace('refs/heads/', ''), | ||
# Assuming the first element is the last commit. | ||
'commit': self.request.data['commits'][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.
Not sure about this, didn't found much documentation about this on gitlab.
} | ||
}] | ||
} | ||
|
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 is what I proposed for the general webhook, maintaining the backwards compatibility.
version.slug | ||
for version in versions | ||
} | ||
return (to_build, not_building) |
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 is the logic for skipping the build, not sure if this is the correct place
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.
So, if the last commit contains the mark we don't build any version?
I'm confused here since the next few lines there is a logic that can build some version but not some others comming in the same webhook, right? Shouldn't we apply a similar logic here also?
That to_build
and not_building
rely on the function _build_version
. So, this logic shouldn't be in that method? (I don't know, but is has the logging integrated and returns what it needs. On the other hand, it seems that we shouldn't call that method if we already know that we need to skip the version but there are some logic to skip versions inside that function too :/
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'm confused here since the next few lines there is a logic that can build some version but not some others comming in the same webhook, right? Shouldn't we apply a similar logic here also?
Of what I understand, a branch/tag/commit can be tied to various versions so there is only one commit message for all versions, this means that all versions from this branch aren't going to be built. And also is about what you mention, we already know if the version isn't going to be built.
... | ||
} | ||
|
||
See full payload here: | ||
https://developer.github.com/v3/activity/events/types/#pushevent |
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.
Are we using the v3 of the gh api?
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.
It seems, https://developer.github.com/v3/#current-version, since we are not sending the Accept
header and v3
is the default.
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.
And also v4 is using GraphQL, this will break everything.
Tests from generic aren't updated for now
Json and urlencoded test case
@@ -62,15 +71,17 @@ def test_exchange_form_request_body(self): | |||
integration = fixture.get(Integration, project=project, | |||
integration_type=Integration.GITHUB_WEBHOOK, | |||
provider_data='') | |||
resp = client.post( | |||
payload_decode = '{"head_commit": {"id": "3eea78b2", "message": "Update README.md"}, "ref": "exchange_form"}' | |||
payload_encode = '%7B%22head_commit%22%3A%20%7B%22id%22%3A%20%223eea78b2%22%2C%20%22message%22%3A%20%22Update%20README.md%22%7D%2C%20%22ref%22%3A%20%22exchange_form%22%7D' |
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 use this tool for encode/decode https://meyerweb.com/eric/tools/dencoder/
Note: the order matters!
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.
Can you do this with a Python function to encode a JSON into an URL query string? (it should be there one in the standard library)
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.
Sure, I think that's cleaner, just wanted to keep to the current tests style.
While updating some tests, I found that there is some old webhook code (https://github.com/rtfd/readthedocs.org/blob/master/readthedocs/core/views/hooks.py#L158) that is marked as deprecated, should we remove this code? (another PR?) o should we still support the v1 webhooks? |
Hehe, I asked the same to Eric and he checked the logs: many people still use this so we can't remove this endpoint :( |
readthedocs/core/views/hooks.py
Outdated
@@ -66,6 +66,23 @@ def _build_version(project, slug, already_built=()): | |||
return None | |||
|
|||
|
|||
def _contains_skip_mark(commit): |
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.
Receive the message itself, instead of relying on a commit
object.
readthedocs/core/views/hooks.py
Outdated
to_build = set() | ||
not_building = set() | ||
if _contains_skip_mark(commit): | ||
log.info('(Branch Build) Skip build %s', project.slug) |
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.
Add the reason of the skip, like "because contains skip mark" or something better :)
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 like the addition of this new feature.
Although, I think it needs more work and make some decision on the logic/flow followed when a webhook is received. It's still kind of complex to me how the path is and "where this code should live" (the skip you wrote).
Please, take a look at my comments and let's keep discussing where and how :)
version.slug | ||
for version in versions | ||
} | ||
return (to_build, not_building) |
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.
So, if the last commit contains the mark we don't build any version?
I'm confused here since the next few lines there is a logic that can build some version but not some others comming in the same webhook, right? Shouldn't we apply a similar logic here also?
That to_build
and not_building
rely on the function _build_version
. So, this logic shouldn't be in that method? (I don't know, but is has the logging integrated and returns what it needs. On the other hand, it seems that we shouldn't call that method if we already know that we need to skip the version but there are some logic to skip versions inside that function too :/
... | ||
} | ||
|
||
See full payload here: | ||
https://developer.github.com/v3/activity/events/types/#pushevent |
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.
It seems, https://developer.github.com/v3/#current-version, since we are not sending the Accept
header and v3
is the default.
readthedocs/core/views/hooks.py
Outdated
@@ -75,9 +92,17 @@ def build_branches(project, branch_list): | |||
not_building - a list of branches that we won't build | |||
""" | |||
for branch in branch_list: | |||
versions = project.versions_from_branch_name(branch) | |||
commit = branch['last_commit'] | |||
versions = project.versions_from_branch_name(branch['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.
Why did you change branch
by branch['name']
here?
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.
See #3457 (comment)
branches = [self.request.data['ref'].replace('refs/heads/', '')] | ||
# GitLab only returns one branch. | ||
branch = { | ||
'name': self.request.data['ref'].replace('refs/heads/', ''), |
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.
Won't this interferes with your other PR at #3546?
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.
Just when merging/rebasing, on the logic everything would work as expected :)
# Assuming the first element is the last commit. | ||
'last_commit': self.request.data['commits'][0], | ||
} | ||
branches = [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.
Another thought here... If we already know at this point the last commit message, shouldn't skip here the call to self.get_response_push
instead of going deeper in the path?
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 need the (buid, not_building) from the build_branches
function to make the response.
@@ -62,15 +71,17 @@ def test_exchange_form_request_body(self): | |||
integration = fixture.get(Integration, project=project, | |||
integration_type=Integration.GITHUB_WEBHOOK, | |||
provider_data='') | |||
resp = client.post( | |||
payload_decode = '{"head_commit": {"id": "3eea78b2", "message": "Update README.md"}, "ref": "exchange_form"}' | |||
payload_encode = '%7B%22head_commit%22%3A%20%7B%22id%22%3A%20%223eea78b2%22%2C%20%22message%22%3A%20%22Update%20README.md%22%7D%2C%20%22ref%22%3A%20%22exchange_form%22%7D' |
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.
Can you do this with a Python function to encode a JSON into an URL query string? (it should be there one in the standard library)
Also, if you can, please add test cases for this specific feature so we can be sure that it works and then we are safe while refactoring/restructuring the code. |
@humitos thanks for the feedback, I have improve the log and added some tests, I also made sure to keep the changes backwards compatible with the old webhooks and with the generic webhook. |
Some previous tests were wrong and pass unnoticed because of the old mock library. Everything is correct now (I think). |
Feels like this has a larger refactor in it. Is this still something useful that we should try and get in? |
Hmm, not sure. This will allow users to help us to save some resources, but I don't know how much. |
This is "nice to have" but I'm not sure that it worth to add this complexity to the code. Also, I'm not sure how many people will use this feature in the end since it's something manually that also could "mess/dirty" the commit messages from the repo. |
I'm closing this PR here because it was off our roadmap and we consider that adding this complexity to the code base for a feature that will affect more our servers than the user itself does not worth it. Thanks a lot for this code and I'm sorry that it's not going to be merged 😞 |
This implements a feature discussed here #871
When a webhook is called, its receive the last commit after the push event,
the following marks are searched in the commit message:
If one is found, the build process is skipped.
Still wip, this is what I have so far: