-
-
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
Changes from 9 commits
f6d9780
e851bf0
e21af7e
634a6ed
3eea78b
177f0f7
f20fcd3
8150793
1c89e6a
64e00b0
435726c
24dd729
a930dc3
517d3eb
8ab67be
12147c8
b808ce4
c8b8756
836c9ca
806789d
97235a3
5803557
ce0fa0f
808f835
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,6 +66,23 @@ def _build_version(project, slug, already_built=()): | |
return None | ||
|
||
|
||
def _contains_skip_mark(commit): | ||
""" | ||
Check if a commit message has a skip mark, for example: [skip docs], | ||
[docs skip]. | ||
""" | ||
skip_marks = [ | ||
r'\[skip docs?\]', | ||
r'\[docs? skip\]', | ||
] | ||
message = commit['message'] | ||
for skip_mark in skip_marks: | ||
mark = re.compile(skip_mark, re.IGNORECASE) | ||
if mark.search(message): | ||
return True | ||
return False | ||
|
||
|
||
def build_branches(project, branch_list): | ||
""" | ||
Build the branches for a specific project. | ||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more. Why did you change There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See #3457 (comment) |
||
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 commentThe 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 :) |
||
not_building = { | ||
version.slug | ||
for version in versions | ||
} | ||
return (to_build, not_building) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
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. |
||
for version in versions: | ||
log.info("(Branch Build) Processing %s:%s", | ||
project.slug, version.slug) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -137,8 +137,16 @@ class GitHubWebhookView(WebhookMixin, APIView): | |
|
||
{ | ||
"ref": "branch-name", | ||
"head_commit": { | ||
"id": "sha", | ||
"message": "Update README.md", | ||
... | ||
} | ||
... | ||
} | ||
|
||
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 commentThe 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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And also v4 is using GraphQL, this will break everything. |
||
""" | ||
|
||
integration_type = Integration.GITHUB_WEBHOOK | ||
|
@@ -159,7 +167,12 @@ def handle_webhook(self): | |
# Handle push events and trigger builds | ||
if event == GITHUB_PUSH: | ||
try: | ||
branches = [self.data['ref'].replace('refs/heads/', '')] | ||
# GitHub only returns one branch. | ||
branch = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I change branch to be a dict with |
||
'name': self.data['ref'].replace('refs/heads/', ''), | ||
'last_commit': self.data['head_commit'], | ||
} | ||
branches = [branch] | ||
return self.get_response_push(self.project, branches) | ||
except KeyError: | ||
raise ParseError('Parameter "ref" is required') | ||
|
@@ -177,8 +190,16 @@ class GitLabWebhookView(WebhookMixin, APIView): | |
{ | ||
"object_kind": "push", | ||
"ref": "branch-name", | ||
"commits": [{ | ||
"id": "sha", | ||
"message": "Update README.md", | ||
... | ||
}] | ||
... | ||
} | ||
|
||
See full payload here: | ||
https://docs.gitlab.com/ce/user/project/integrations/webhooks.html#push-events | ||
""" | ||
|
||
integration_type = Integration.GITLAB_WEBHOOK | ||
|
@@ -191,7 +212,13 @@ def handle_webhook(self): | |
# Handle push events and trigger builds | ||
if event == GITLAB_PUSH: | ||
try: | ||
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 commentThe 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 commentThe 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 commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need the (buid, not_building) from the |
||
return self.get_response_push(self.project, branches) | ||
except KeyError: | ||
raise ParseError('Parameter "ref" is required') | ||
|
@@ -211,6 +238,11 @@ class BitbucketWebhookView(WebhookMixin, APIView): | |
"changes": [{ | ||
"new": { | ||
"name": "branch-name", | ||
"target": { | ||
"hash": "sha", | ||
"message": "Update README.md", | ||
... | ||
} | ||
... | ||
}, | ||
... | ||
|
@@ -219,6 +251,9 @@ class BitbucketWebhookView(WebhookMixin, APIView): | |
}, | ||
... | ||
} | ||
|
||
See full payload here: | ||
https://confluence.atlassian.com/bitbucket/event-payloads-740262817.html#EventPayloads-Push | ||
""" | ||
|
||
integration_type = Integration.BITBUCKET_WEBHOOK | ||
|
@@ -232,12 +267,32 @@ def handle_webhook(self): | |
if event == BITBUCKET_PUSH: | ||
try: | ||
changes = self.request.data['push']['changes'] | ||
branches = [change['new']['name'] | ||
for change in changes] | ||
branches = [ | ||
{ | ||
'name': change['new']['name'], | ||
'last_commit': self._normalize_commit( | ||
change['new']['target'] | ||
), | ||
} | ||
for change in changes | ||
] | ||
return self.get_response_push(self.project, branches) | ||
except KeyError: | ||
raise ParseError('Invalid request') | ||
|
||
def _normalize_commit(self, commit): | ||
""" | ||
All commit dicts must have this elements at least:: | ||
{ | ||
'id': 'sha', | ||
'message': 'Update README.md', | ||
} | ||
""" | ||
return { | ||
'id': commit['hash'], | ||
'message': commit['message'], | ||
} | ||
|
||
|
||
class IsAuthenticatedOrHasToken(permissions.IsAuthenticated): | ||
|
||
|
@@ -264,6 +319,19 @@ class APIWebhookView(WebhookMixin, APIView): | |
{ | ||
"branches": ["master"] | ||
} | ||
|
||
Or the following JSON:: | ||
|
||
{ | ||
"branches": [{ | ||
"name": "branch-name", | ||
"last_commit": { | ||
"id": "sha", | ||
"message": "Update README.md" | ||
} | ||
}] | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
""" | ||
|
||
integration_type = Integration.API_WEBHOOK | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,15 +29,24 @@ def test_exchange_json_request_body(self): | |
integration = fixture.get(Integration, project=project, | ||
integration_type=Integration.GITHUB_WEBHOOK, | ||
provider_data='') | ||
resp = client.post( | ||
payload_dict = { | ||
'head_commit': { | ||
'id': '3eea78b2', | ||
'message': 'Update README.md', | ||
}, | ||
'ref': 'exchange_json', | ||
} | ||
payload_json = '{"head_commit": {"id": "3eea78b2", "message": "Update README.md"}, "ref": "exchange_json"}' | ||
|
||
client.post( | ||
'/api/v2/webhook/github/{0}/'.format(project.slug), | ||
{'ref': 'exchange_json'}, | ||
payload_dict, | ||
format='json' | ||
) | ||
exchange = HttpExchange.objects.get(integrations=integration) | ||
self.assertEqual( | ||
exchange.request_body, | ||
'{"ref": "exchange_json"}' | ||
payload_json | ||
) | ||
self.assertEqual( | ||
exchange.request_headers, | ||
|
@@ -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 commentThe 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 commentThe 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 commentThe 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. |
||
client.post( | ||
'/api/v2/webhook/github/{0}/'.format(project.slug), | ||
'payload=%7B%22ref%22%3A+%22exchange_form%22%7D', | ||
'payload={}'.format(payload_encode), | ||
content_type='application/x-www-form-urlencoded', | ||
) | ||
exchange = HttpExchange.objects.get(integrations=integration) | ||
self.assertEqual( | ||
exchange.request_body, | ||
'{"ref": "exchange_form"}' | ||
payload_decode | ||
) | ||
self.assertEqual( | ||
exchange.request_headers, | ||
|
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.