##// END OF EJS Templates
events: change target to source repo for pull request events...
dan -
r514:b4f9553f default
parent child Browse files
Show More
@@ -1,126 +1,131 b''
1 # Copyright (C) 2016-2016 RhodeCode GmbH
1 # Copyright (C) 2016-2016 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19
19
20 from rhodecode.translation import lazy_ugettext
20 from rhodecode.translation import lazy_ugettext
21 from rhodecode.events.repo import RepoEvent
21 from rhodecode.events.repo import (
22 RepoEvent, _commits_as_dict, _issues_as_dict)
22
23
23
24
24 class PullRequestEvent(RepoEvent):
25 class PullRequestEvent(RepoEvent):
25 """
26 """
26 Base class for pull request events.
27 Base class for pull request events.
27
28
28 :param pullrequest: a :class:`PullRequest` instance
29 :param pullrequest: a :class:`PullRequest` instance
29 """
30 """
30
31
31 def __init__(self, pullrequest):
32 def __init__(self, pullrequest):
32 super(PullRequestEvent, self).__init__(pullrequest.target_repo)
33 super(PullRequestEvent, self).__init__(pullrequest.target_repo)
33 self.pullrequest = pullrequest
34 self.pullrequest = pullrequest
34
35
35 def as_dict(self):
36 def as_dict(self):
36 from rhodecode.model.pull_request import PullRequestModel
37 from rhodecode.model.pull_request import PullRequestModel
37 data = super(PullRequestEvent, self).as_dict()
38 data = super(PullRequestEvent, self).as_dict()
38
39
39 commits = self._commits_as_dict(self.pullrequest.revisions)
40 commits = _commits_as_dict(
40 issues = self._issues_as_dict(commits)
41 commit_ids=self.pullrequest.revisions,
42 repos=[self.pullrequest.source_repo]
43 )
44 issues = _issues_as_dict(commits)
41
45
42 data.update({
46 data.update({
43 'pullrequest': {
47 'pullrequest': {
44 'title': self.pullrequest.title,
48 'title': self.pullrequest.title,
45 'issues': issues,
49 'issues': issues,
46 'pull_request_id': self.pullrequest.pull_request_id,
50 'pull_request_id': self.pullrequest.pull_request_id,
47 'url': PullRequestModel().get_url(self.pullrequest),
51 'url': PullRequestModel().get_url(self.pullrequest),
48 'status': self.pullrequest.calculated_review_status(),
52 'status': self.pullrequest.calculated_review_status(),
53 'commits': commits,
49 }
54 }
50 })
55 })
51 return data
56 return data
52
57
53
58
54 class PullRequestCreateEvent(PullRequestEvent):
59 class PullRequestCreateEvent(PullRequestEvent):
55 """
60 """
56 An instance of this class is emitted as an :term:`event` after a pull
61 An instance of this class is emitted as an :term:`event` after a pull
57 request is created.
62 request is created.
58 """
63 """
59 name = 'pullrequest-create'
64 name = 'pullrequest-create'
60 display_name = lazy_ugettext('pullrequest created')
65 display_name = lazy_ugettext('pullrequest created')
61
66
62
67
63 class PullRequestCloseEvent(PullRequestEvent):
68 class PullRequestCloseEvent(PullRequestEvent):
64 """
69 """
65 An instance of this class is emitted as an :term:`event` after a pull
70 An instance of this class is emitted as an :term:`event` after a pull
66 request is closed.
71 request is closed.
67 """
72 """
68 name = 'pullrequest-close'
73 name = 'pullrequest-close'
69 display_name = lazy_ugettext('pullrequest closed')
74 display_name = lazy_ugettext('pullrequest closed')
70
75
71
76
72 class PullRequestUpdateEvent(PullRequestEvent):
77 class PullRequestUpdateEvent(PullRequestEvent):
73 """
78 """
74 An instance of this class is emitted as an :term:`event` after a pull
79 An instance of this class is emitted as an :term:`event` after a pull
75 request's commits have been updated.
80 request's commits have been updated.
76 """
81 """
77 name = 'pullrequest-update'
82 name = 'pullrequest-update'
78 display_name = lazy_ugettext('pullrequest commits updated')
83 display_name = lazy_ugettext('pullrequest commits updated')
79
84
80
85
81 class PullRequestReviewEvent(PullRequestEvent):
86 class PullRequestReviewEvent(PullRequestEvent):
82 """
87 """
83 An instance of this class is emitted as an :term:`event` after a pull
88 An instance of this class is emitted as an :term:`event` after a pull
84 request review has changed.
89 request review has changed.
85 """
90 """
86 name = 'pullrequest-review'
91 name = 'pullrequest-review'
87 display_name = lazy_ugettext('pullrequest review changed')
92 display_name = lazy_ugettext('pullrequest review changed')
88
93
89
94
90 class PullRequestMergeEvent(PullRequestEvent):
95 class PullRequestMergeEvent(PullRequestEvent):
91 """
96 """
92 An instance of this class is emitted as an :term:`event` after a pull
97 An instance of this class is emitted as an :term:`event` after a pull
93 request is merged.
98 request is merged.
94 """
99 """
95 name = 'pullrequest-merge'
100 name = 'pullrequest-merge'
96 display_name = lazy_ugettext('pullrequest merged')
101 display_name = lazy_ugettext('pullrequest merged')
97
102
98
103
99 class PullRequestCommentEvent(PullRequestEvent):
104 class PullRequestCommentEvent(PullRequestEvent):
100 """
105 """
101 An instance of this class is emitted as an :term:`event` after a pull
106 An instance of this class is emitted as an :term:`event` after a pull
102 request comment is created.
107 request comment is created.
103 """
108 """
104 name = 'pullrequest-comment'
109 name = 'pullrequest-comment'
105 display_name = lazy_ugettext('pullrequest commented')
110 display_name = lazy_ugettext('pullrequest commented')
106
111
107 def __init__(self, pullrequest, comment):
112 def __init__(self, pullrequest, comment):
108 super(PullRequestCommentEvent, self).__init__(pullrequest)
113 super(PullRequestCommentEvent, self).__init__(pullrequest)
109 self.comment = comment
114 self.comment = comment
110
115
111 def as_dict(self):
116 def as_dict(self):
112 from rhodecode.model.comment import ChangesetCommentsModel
117 from rhodecode.model.comment import ChangesetCommentsModel
113 data = super(PullRequestCommentEvent, self).as_dict()
118 data = super(PullRequestCommentEvent, self).as_dict()
114
119
115 status = None
120 status = None
116 if self.comment.status_change:
121 if self.comment.status_change:
117 status = self.comment.status_change[0].status
122 status = self.comment.status_change[0].status
118
123
119 data.update({
124 data.update({
120 'comment': {
125 'comment': {
121 'status': status,
126 'status': status,
122 'text': self.comment.text,
127 'text': self.comment.text,
123 'url': ChangesetCommentsModel().get_url(self.comment)
128 'url': ChangesetCommentsModel().get_url(self.comment)
124 }
129 }
125 })
130 })
126 return data
131 return data
@@ -1,220 +1,252 b''
1 # Copyright (C) 2016-2016 RhodeCode GmbH
1 # Copyright (C) 2016-2016 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20
20
21 from rhodecode.translation import lazy_ugettext
21 from rhodecode.translation import lazy_ugettext
22 from rhodecode.model.db import User, Repository, Session
22 from rhodecode.model.db import User, Repository, Session
23 from rhodecode.events.base import RhodecodeEvent
23 from rhodecode.events.base import RhodecodeEvent
24 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
24
25
25 log = logging.getLogger(__name__)
26 log = logging.getLogger(__name__)
26
27
28 def _commits_as_dict(commit_ids, repos):
29 """
30 Helper function to serialize commit_ids
31
32 :param commit_ids: commits to get
33 :param repos: list of repos to check
34 """
35 from rhodecode.lib.utils2 import extract_mentioned_users
36 from rhodecode.model.db import Repository
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib.helpers import process_patterns
39 from rhodecode.lib.helpers import urlify_commit_message
40
41 if not repos:
42 raise Exception('no repo defined')
43
44 if not isinstance(repos, (tuple, list)):
45 repos = [repos]
46
47 if not commit_ids:
48 return []
49
50 needed_commits = set(commit_ids)
51
52 commits = []
53 reviewers = []
54 for repo in repos:
55 if not needed_commits:
56 return commits # return early if we have the commits we need
57
58 vcs_repo = repo.scm_instance(cache=False)
59 try:
60 for commit_id in list(needed_commits):
61 try:
62 cs = vcs_repo.get_changeset(commit_id)
63 except CommitDoesNotExistError:
64 continue # maybe its in next repo
65
66 cs_data = cs.__json__()
67 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
68 cs_data['reviewers'] = reviewers
69 cs_data['url'] = h.url('changeset_home',
70 repo_name=repo.repo_name,
71 revision=cs_data['raw_id'],
72 qualified=True
73 )
74 urlified_message, issues_data = process_patterns(
75 cs_data['message'], repo.repo_name)
76 cs_data['issues'] = issues_data
77 cs_data['message_html'] = urlify_commit_message(cs_data['message'],
78 repo.repo_name)
79 commits.append(cs_data)
80
81 needed_commits.discard(commit_id)
82
83 except Exception as e:
84 log.exception(e)
85 # we don't send any commits when crash happens, only full list matters
86 # we short circuit then.
87 return []
88
89 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
90 if missing_commits:
91 log.error('missing commits: %s' % ', '.join(missing_commits))
92
93 return commits
94
95
96 def _issues_as_dict(commits):
97 """ Helper function to serialize issues from commits """
98 issues = {}
99 for commit in commits:
100 for issue in commit['issues']:
101 issues[issue['id']] = issue
102 return issues
27
103
28 class RepoEvent(RhodecodeEvent):
104 class RepoEvent(RhodecodeEvent):
29 """
105 """
30 Base class for events acting on a repository.
106 Base class for events acting on a repository.
31
107
32 :param repo: a :class:`Repository` instance
108 :param repo: a :class:`Repository` instance
33 """
109 """
34
110
35 def __init__(self, repo):
111 def __init__(self, repo):
36 super(RepoEvent, self).__init__()
112 super(RepoEvent, self).__init__()
37 self.repo = repo
113 self.repo = repo
38
114
39 def as_dict(self):
115 def as_dict(self):
40 from rhodecode.model.repo import RepoModel
116 from rhodecode.model.repo import RepoModel
41 data = super(RepoEvent, self).as_dict()
117 data = super(RepoEvent, self).as_dict()
42 data.update({
118 data.update({
43 'repo': {
119 'repo': {
44 'repo_id': self.repo.repo_id,
120 'repo_id': self.repo.repo_id,
45 'repo_name': self.repo.repo_name,
121 'repo_name': self.repo.repo_name,
46 'repo_type': self.repo.repo_type,
122 'repo_type': self.repo.repo_type,
47 'url': RepoModel().get_url(self.repo)
123 'url': RepoModel().get_url(self.repo)
48 }
124 }
49 })
125 })
50 return data
126 return data
51
127
52 def _commits_as_dict(self, commit_ids):
53 """ Helper function to serialize commit_ids """
54
55 from rhodecode.lib.utils2 import extract_mentioned_users
56 from rhodecode.model.db import Repository
57 from rhodecode.lib import helpers as h
58 from rhodecode.lib.helpers import process_patterns
59 from rhodecode.lib.helpers import urlify_commit_message
60 if not commit_ids:
61 return []
62 commits = []
63 reviewers = []
64 vcs_repo = self.repo.scm_instance(cache=False)
65 try:
66 for commit_id in commit_ids:
67 cs = vcs_repo.get_changeset(commit_id)
68 cs_data = cs.__json__()
69 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
70 cs_data['reviewers'] = reviewers
71 cs_data['url'] = h.url('changeset_home',
72 repo_name=self.repo.repo_name,
73 revision=cs_data['raw_id'],
74 qualified=True
75 )
76 urlified_message, issues_data = process_patterns(
77 cs_data['message'], self.repo.repo_name)
78 cs_data['issues'] = issues_data
79 cs_data['message_html'] = urlify_commit_message(cs_data['message'],
80 self.repo.repo_name)
81 commits.append(cs_data)
82 except Exception as e:
83 log.exception(e)
84 # we don't send any commits when crash happens, only full list matters
85 # we short circuit then.
86 return []
87 return commits
88
89 def _issues_as_dict(self, commits):
90 """ Helper function to serialize issues from commits """
91 issues = {}
92 for commit in commits:
93 for issue in commit['issues']:
94 issues[issue['id']] = issue
95 return issues
96
97
128
98 class RepoPreCreateEvent(RepoEvent):
129 class RepoPreCreateEvent(RepoEvent):
99 """
130 """
100 An instance of this class is emitted as an :term:`event` before a repo is
131 An instance of this class is emitted as an :term:`event` before a repo is
101 created.
132 created.
102 """
133 """
103 name = 'repo-pre-create'
134 name = 'repo-pre-create'
104 display_name = lazy_ugettext('repository pre create')
135 display_name = lazy_ugettext('repository pre create')
105
136
106
137
107 class RepoCreateEvent(RepoEvent):
138 class RepoCreateEvent(RepoEvent):
108 """
139 """
109 An instance of this class is emitted as an :term:`event` whenever a repo is
140 An instance of this class is emitted as an :term:`event` whenever a repo is
110 created.
141 created.
111 """
142 """
112 name = 'repo-create'
143 name = 'repo-create'
113 display_name = lazy_ugettext('repository created')
144 display_name = lazy_ugettext('repository created')
114
145
115
146
116 class RepoPreDeleteEvent(RepoEvent):
147 class RepoPreDeleteEvent(RepoEvent):
117 """
148 """
118 An instance of this class is emitted as an :term:`event` whenever a repo is
149 An instance of this class is emitted as an :term:`event` whenever a repo is
119 created.
150 created.
120 """
151 """
121 name = 'repo-pre-delete'
152 name = 'repo-pre-delete'
122 display_name = lazy_ugettext('repository pre delete')
153 display_name = lazy_ugettext('repository pre delete')
123
154
124
155
125 class RepoDeleteEvent(RepoEvent):
156 class RepoDeleteEvent(RepoEvent):
126 """
157 """
127 An instance of this class is emitted as an :term:`event` whenever a repo is
158 An instance of this class is emitted as an :term:`event` whenever a repo is
128 created.
159 created.
129 """
160 """
130 name = 'repo-delete'
161 name = 'repo-delete'
131 display_name = lazy_ugettext('repository deleted')
162 display_name = lazy_ugettext('repository deleted')
132
163
133
164
134 class RepoVCSEvent(RepoEvent):
165 class RepoVCSEvent(RepoEvent):
135 """
166 """
136 Base class for events triggered by the VCS
167 Base class for events triggered by the VCS
137 """
168 """
138 def __init__(self, repo_name, extras):
169 def __init__(self, repo_name, extras):
139 self.repo = Repository.get_by_repo_name(repo_name)
170 self.repo = Repository.get_by_repo_name(repo_name)
140 if not self.repo:
171 if not self.repo:
141 raise Exception('repo by this name %s does not exist' % repo_name)
172 raise Exception('repo by this name %s does not exist' % repo_name)
142 self.extras = extras
173 self.extras = extras
143 super(RepoVCSEvent, self).__init__(self.repo)
174 super(RepoVCSEvent, self).__init__(self.repo)
144
175
145 @property
176 @property
146 def actor(self):
177 def actor(self):
147 if self.extras.get('username'):
178 if self.extras.get('username'):
148 return User.get_by_username(self.extras['username'])
179 return User.get_by_username(self.extras['username'])
149
180
150 @property
181 @property
151 def actor_ip(self):
182 def actor_ip(self):
152 if self.extras.get('ip'):
183 if self.extras.get('ip'):
153 return self.extras['ip']
184 return self.extras['ip']
154
185
155
186
156 class RepoPrePullEvent(RepoVCSEvent):
187 class RepoPrePullEvent(RepoVCSEvent):
157 """
188 """
158 An instance of this class is emitted as an :term:`event` before commits
189 An instance of this class is emitted as an :term:`event` before commits
159 are pulled from a repo.
190 are pulled from a repo.
160 """
191 """
161 name = 'repo-pre-pull'
192 name = 'repo-pre-pull'
162 display_name = lazy_ugettext('repository pre pull')
193 display_name = lazy_ugettext('repository pre pull')
163
194
164
195
165 class RepoPullEvent(RepoVCSEvent):
196 class RepoPullEvent(RepoVCSEvent):
166 """
197 """
167 An instance of this class is emitted as an :term:`event` after commits
198 An instance of this class is emitted as an :term:`event` after commits
168 are pulled from a repo.
199 are pulled from a repo.
169 """
200 """
170 name = 'repo-pull'
201 name = 'repo-pull'
171 display_name = lazy_ugettext('repository pull')
202 display_name = lazy_ugettext('repository pull')
172
203
173
204
174 class RepoPrePushEvent(RepoVCSEvent):
205 class RepoPrePushEvent(RepoVCSEvent):
175 """
206 """
176 An instance of this class is emitted as an :term:`event` before commits
207 An instance of this class is emitted as an :term:`event` before commits
177 are pushed to a repo.
208 are pushed to a repo.
178 """
209 """
179 name = 'repo-pre-push'
210 name = 'repo-pre-push'
180 display_name = lazy_ugettext('repository pre push')
211 display_name = lazy_ugettext('repository pre push')
181
212
182
213
183 class RepoPushEvent(RepoVCSEvent):
214 class RepoPushEvent(RepoVCSEvent):
184 """
215 """
185 An instance of this class is emitted as an :term:`event` after commits
216 An instance of this class is emitted as an :term:`event` after commits
186 are pushed to a repo.
217 are pushed to a repo.
187
218
188 :param extras: (optional) dict of data from proxied VCS actions
219 :param extras: (optional) dict of data from proxied VCS actions
189 """
220 """
190 name = 'repo-push'
221 name = 'repo-push'
191 display_name = lazy_ugettext('repository push')
222 display_name = lazy_ugettext('repository push')
192
223
193 def __init__(self, repo_name, pushed_commit_ids, extras):
224 def __init__(self, repo_name, pushed_commit_ids, extras):
194 super(RepoPushEvent, self).__init__(repo_name, extras)
225 super(RepoPushEvent, self).__init__(repo_name, extras)
195 self.pushed_commit_ids = pushed_commit_ids
226 self.pushed_commit_ids = pushed_commit_ids
196
227
197 def as_dict(self):
228 def as_dict(self):
198 data = super(RepoPushEvent, self).as_dict()
229 data = super(RepoPushEvent, self).as_dict()
199 branch_url = repo_url = data['repo']['url']
230 branch_url = repo_url = data['repo']['url']
200
231
201 commits = self._commits_as_dict(self.pushed_commit_ids)
232 commits = _commits_as_dict(
202 issues = self._issues_as_dict(commits)
233 commit_ids=self.pushed_commit_ids, repos=[self.repo])
234 issues = _issues_as_dict(commits)
203
235
204 branches = set(
236 branches = set(
205 commit['branch'] for commit in commits if commit['branch'])
237 commit['branch'] for commit in commits if commit['branch'])
206 branches = [
238 branches = [
207 {
239 {
208 'name': branch,
240 'name': branch,
209 'url': '{}/changelog?branch={}'.format(
241 'url': '{}/changelog?branch={}'.format(
210 data['repo']['url'], branch)
242 data['repo']['url'], branch)
211 }
243 }
212 for branch in branches
244 for branch in branches
213 ]
245 ]
214
246
215 data['push'] = {
247 data['push'] = {
216 'commits': commits,
248 'commits': commits,
217 'issues': issues,
249 'issues': issues,
218 'branches': branches,
250 'branches': branches,
219 }
251 }
220 return data
252 return data
General Comments 0
You need to be logged in to leave comments. Login now