##// END OF EJS Templates
events: expose server_url for repo events.
marcink -
r649:724715f1 default
parent child Browse files
Show More
@@ -1,59 +1,69 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 from datetime import datetime
19 from datetime import datetime
20 from pyramid.threadlocal import get_current_request
20 from pyramid.threadlocal import get_current_request
21 from rhodecode.lib.utils2 import AttributeDict
21 from rhodecode.lib.utils2 import AttributeDict
22
22
23
23
24 # this is a user object to be used for events caused by the system (eg. shell)
24 # this is a user object to be used for events caused by the system (eg. shell)
25 SYSTEM_USER = AttributeDict(dict(
25 SYSTEM_USER = AttributeDict(dict(
26 username='__SYSTEM__'
26 username='__SYSTEM__'
27 ))
27 ))
28
28
29
29
30 class RhodecodeEvent(object):
30 class RhodecodeEvent(object):
31 """
31 """
32 Base event class for all Rhodecode events
32 Base event class for all Rhodecode events
33 """
33 """
34 name = "RhodeCodeEvent"
35
34 def __init__(self):
36 def __init__(self):
35 self.request = get_current_request()
37 self.request = get_current_request()
36 self.utc_timestamp = datetime.utcnow()
38 self.utc_timestamp = datetime.utcnow()
37
39
38 @property
40 @property
39 def actor(self):
41 def actor(self):
40 if self.request:
42 if self.request:
41 return self.request.user.get_instance()
43 return self.request.user.get_instance()
42 return SYSTEM_USER
44 return SYSTEM_USER
43
45
44 @property
46 @property
45 def actor_ip(self):
47 def actor_ip(self):
46 if self.request:
48 if self.request:
47 return self.request.user.ip_addr
49 return self.request.user.ip_addr
48 return '<no ip available>'
50 return '<no ip available>'
49
51
52 @property
53 def server_url(self):
54 if self.request:
55 from rhodecode.lib import helpers as h
56 return h.url('home', qualified=True)
57 return '<no server_url available>'
58
50 def as_dict(self):
59 def as_dict(self):
51 data = {
60 data = {
52 'name': self.name,
61 'name': self.name,
53 'utc_timestamp': self.utc_timestamp,
62 'utc_timestamp': self.utc_timestamp,
54 'actor_ip': self.actor_ip,
63 'actor_ip': self.actor_ip,
55 'actor': {
64 'actor': {
56 'username': self.actor.username
65 'username': self.actor.username
57 }
66 },
67 'server_url': self.server_url
58 }
68 }
59 return data No newline at end of file
69 return data
@@ -1,252 +1,257 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 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
25
25
26 log = logging.getLogger(__name__)
26 log = logging.getLogger(__name__)
27
27
28 def _commits_as_dict(commit_ids, repos):
28 def _commits_as_dict(commit_ids, repos):
29 """
29 """
30 Helper function to serialize commit_ids
30 Helper function to serialize commit_ids
31
31
32 :param commit_ids: commits to get
32 :param commit_ids: commits to get
33 :param repos: list of repos to check
33 :param repos: list of repos to check
34 """
34 """
35 from rhodecode.lib.utils2 import extract_mentioned_users
35 from rhodecode.lib.utils2 import extract_mentioned_users
36 from rhodecode.model.db import Repository
36 from rhodecode.model.db import Repository
37 from rhodecode.lib import helpers as h
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib.helpers import process_patterns
38 from rhodecode.lib.helpers import process_patterns
39 from rhodecode.lib.helpers import urlify_commit_message
39 from rhodecode.lib.helpers import urlify_commit_message
40
40
41 if not repos:
41 if not repos:
42 raise Exception('no repo defined')
42 raise Exception('no repo defined')
43
43
44 if not isinstance(repos, (tuple, list)):
44 if not isinstance(repos, (tuple, list)):
45 repos = [repos]
45 repos = [repos]
46
46
47 if not commit_ids:
47 if not commit_ids:
48 return []
48 return []
49
49
50 needed_commits = set(commit_ids)
50 needed_commits = set(commit_ids)
51
51
52 commits = []
52 commits = []
53 reviewers = []
53 reviewers = []
54 for repo in repos:
54 for repo in repos:
55 if not needed_commits:
55 if not needed_commits:
56 return commits # return early if we have the commits we need
56 return commits # return early if we have the commits we need
57
57
58 vcs_repo = repo.scm_instance(cache=False)
58 vcs_repo = repo.scm_instance(cache=False)
59 try:
59 try:
60 for commit_id in list(needed_commits):
60 for commit_id in list(needed_commits):
61 try:
61 try:
62 cs = vcs_repo.get_changeset(commit_id)
62 cs = vcs_repo.get_changeset(commit_id)
63 except CommitDoesNotExistError:
63 except CommitDoesNotExistError:
64 continue # maybe its in next repo
64 continue # maybe its in next repo
65
65
66 cs_data = cs.__json__()
66 cs_data = cs.__json__()
67 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
67 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
68 cs_data['reviewers'] = reviewers
68 cs_data['reviewers'] = reviewers
69 cs_data['url'] = h.url('changeset_home',
69 cs_data['url'] = h.url('changeset_home',
70 repo_name=repo.repo_name,
70 repo_name=repo.repo_name,
71 revision=cs_data['raw_id'],
71 revision=cs_data['raw_id'],
72 qualified=True
72 qualified=True
73 )
73 )
74 urlified_message, issues_data = process_patterns(
74 urlified_message, issues_data = process_patterns(
75 cs_data['message'], repo.repo_name)
75 cs_data['message'], repo.repo_name)
76 cs_data['issues'] = issues_data
76 cs_data['issues'] = issues_data
77 cs_data['message_html'] = urlify_commit_message(cs_data['message'],
77 cs_data['message_html'] = urlify_commit_message(cs_data['message'],
78 repo.repo_name)
78 repo.repo_name)
79 commits.append(cs_data)
79 commits.append(cs_data)
80
80
81 needed_commits.discard(commit_id)
81 needed_commits.discard(commit_id)
82
82
83 except Exception as e:
83 except Exception as e:
84 log.exception(e)
84 log.exception(e)
85 # we don't send any commits when crash happens, only full list matters
85 # we don't send any commits when crash happens, only full list matters
86 # we short circuit then.
86 # we short circuit then.
87 return []
87 return []
88
88
89 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
89 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
90 if missing_commits:
90 if missing_commits:
91 log.error('missing commits: %s' % ', '.join(missing_commits))
91 log.error('missing commits: %s' % ', '.join(missing_commits))
92
92
93 return commits
93 return commits
94
94
95
95
96 def _issues_as_dict(commits):
96 def _issues_as_dict(commits):
97 """ Helper function to serialize issues from commits """
97 """ Helper function to serialize issues from commits """
98 issues = {}
98 issues = {}
99 for commit in commits:
99 for commit in commits:
100 for issue in commit['issues']:
100 for issue in commit['issues']:
101 issues[issue['id']] = issue
101 issues[issue['id']] = issue
102 return issues
102 return issues
103
103
104 class RepoEvent(RhodecodeEvent):
104 class RepoEvent(RhodecodeEvent):
105 """
105 """
106 Base class for events acting on a repository.
106 Base class for events acting on a repository.
107
107
108 :param repo: a :class:`Repository` instance
108 :param repo: a :class:`Repository` instance
109 """
109 """
110
110
111 def __init__(self, repo):
111 def __init__(self, repo):
112 super(RepoEvent, self).__init__()
112 super(RepoEvent, self).__init__()
113 self.repo = repo
113 self.repo = repo
114
114
115 def as_dict(self):
115 def as_dict(self):
116 from rhodecode.model.repo import RepoModel
116 from rhodecode.model.repo import RepoModel
117 data = super(RepoEvent, self).as_dict()
117 data = super(RepoEvent, self).as_dict()
118 data.update({
118 data.update({
119 'repo': {
119 'repo': {
120 'repo_id': self.repo.repo_id,
120 'repo_id': self.repo.repo_id,
121 'repo_name': self.repo.repo_name,
121 'repo_name': self.repo.repo_name,
122 'repo_type': self.repo.repo_type,
122 'repo_type': self.repo.repo_type,
123 'url': RepoModel().get_url(self.repo)
123 'url': RepoModel().get_url(self.repo)
124 }
124 }
125 })
125 })
126 return data
126 return data
127
127
128
128
129 class RepoPreCreateEvent(RepoEvent):
129 class RepoPreCreateEvent(RepoEvent):
130 """
130 """
131 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
132 created.
132 created.
133 """
133 """
134 name = 'repo-pre-create'
134 name = 'repo-pre-create'
135 display_name = lazy_ugettext('repository pre create')
135 display_name = lazy_ugettext('repository pre create')
136
136
137
137
138 class RepoCreateEvent(RepoEvent):
138 class RepoCreateEvent(RepoEvent):
139 """
139 """
140 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
141 created.
141 created.
142 """
142 """
143 name = 'repo-create'
143 name = 'repo-create'
144 display_name = lazy_ugettext('repository created')
144 display_name = lazy_ugettext('repository created')
145
145
146
146
147 class RepoPreDeleteEvent(RepoEvent):
147 class RepoPreDeleteEvent(RepoEvent):
148 """
148 """
149 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
150 created.
150 created.
151 """
151 """
152 name = 'repo-pre-delete'
152 name = 'repo-pre-delete'
153 display_name = lazy_ugettext('repository pre delete')
153 display_name = lazy_ugettext('repository pre delete')
154
154
155
155
156 class RepoDeleteEvent(RepoEvent):
156 class RepoDeleteEvent(RepoEvent):
157 """
157 """
158 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
159 created.
159 created.
160 """
160 """
161 name = 'repo-delete'
161 name = 'repo-delete'
162 display_name = lazy_ugettext('repository deleted')
162 display_name = lazy_ugettext('repository deleted')
163
163
164
164
165 class RepoVCSEvent(RepoEvent):
165 class RepoVCSEvent(RepoEvent):
166 """
166 """
167 Base class for events triggered by the VCS
167 Base class for events triggered by the VCS
168 """
168 """
169 def __init__(self, repo_name, extras):
169 def __init__(self, repo_name, extras):
170 self.repo = Repository.get_by_repo_name(repo_name)
170 self.repo = Repository.get_by_repo_name(repo_name)
171 if not self.repo:
171 if not self.repo:
172 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)
173 self.extras = extras
173 self.extras = extras
174 super(RepoVCSEvent, self).__init__(self.repo)
174 super(RepoVCSEvent, self).__init__(self.repo)
175
175
176 @property
176 @property
177 def actor(self):
177 def actor(self):
178 if self.extras.get('username'):
178 if self.extras.get('username'):
179 return User.get_by_username(self.extras['username'])
179 return User.get_by_username(self.extras['username'])
180
180
181 @property
181 @property
182 def actor_ip(self):
182 def actor_ip(self):
183 if self.extras.get('ip'):
183 if self.extras.get('ip'):
184 return self.extras['ip']
184 return self.extras['ip']
185
185
186 @property
187 def server_url(self):
188 if self.extras.get('server_url'):
189 return self.extras['server_url']
190
186
191
187 class RepoPrePullEvent(RepoVCSEvent):
192 class RepoPrePullEvent(RepoVCSEvent):
188 """
193 """
189 An instance of this class is emitted as an :term:`event` before commits
194 An instance of this class is emitted as an :term:`event` before commits
190 are pulled from a repo.
195 are pulled from a repo.
191 """
196 """
192 name = 'repo-pre-pull'
197 name = 'repo-pre-pull'
193 display_name = lazy_ugettext('repository pre pull')
198 display_name = lazy_ugettext('repository pre pull')
194
199
195
200
196 class RepoPullEvent(RepoVCSEvent):
201 class RepoPullEvent(RepoVCSEvent):
197 """
202 """
198 An instance of this class is emitted as an :term:`event` after commits
203 An instance of this class is emitted as an :term:`event` after commits
199 are pulled from a repo.
204 are pulled from a repo.
200 """
205 """
201 name = 'repo-pull'
206 name = 'repo-pull'
202 display_name = lazy_ugettext('repository pull')
207 display_name = lazy_ugettext('repository pull')
203
208
204
209
205 class RepoPrePushEvent(RepoVCSEvent):
210 class RepoPrePushEvent(RepoVCSEvent):
206 """
211 """
207 An instance of this class is emitted as an :term:`event` before commits
212 An instance of this class is emitted as an :term:`event` before commits
208 are pushed to a repo.
213 are pushed to a repo.
209 """
214 """
210 name = 'repo-pre-push'
215 name = 'repo-pre-push'
211 display_name = lazy_ugettext('repository pre push')
216 display_name = lazy_ugettext('repository pre push')
212
217
213
218
214 class RepoPushEvent(RepoVCSEvent):
219 class RepoPushEvent(RepoVCSEvent):
215 """
220 """
216 An instance of this class is emitted as an :term:`event` after commits
221 An instance of this class is emitted as an :term:`event` after commits
217 are pushed to a repo.
222 are pushed to a repo.
218
223
219 :param extras: (optional) dict of data from proxied VCS actions
224 :param extras: (optional) dict of data from proxied VCS actions
220 """
225 """
221 name = 'repo-push'
226 name = 'repo-push'
222 display_name = lazy_ugettext('repository push')
227 display_name = lazy_ugettext('repository push')
223
228
224 def __init__(self, repo_name, pushed_commit_ids, extras):
229 def __init__(self, repo_name, pushed_commit_ids, extras):
225 super(RepoPushEvent, self).__init__(repo_name, extras)
230 super(RepoPushEvent, self).__init__(repo_name, extras)
226 self.pushed_commit_ids = pushed_commit_ids
231 self.pushed_commit_ids = pushed_commit_ids
227
232
228 def as_dict(self):
233 def as_dict(self):
229 data = super(RepoPushEvent, self).as_dict()
234 data = super(RepoPushEvent, self).as_dict()
230 branch_url = repo_url = data['repo']['url']
235 branch_url = repo_url = data['repo']['url']
231
236
232 commits = _commits_as_dict(
237 commits = _commits_as_dict(
233 commit_ids=self.pushed_commit_ids, repos=[self.repo])
238 commit_ids=self.pushed_commit_ids, repos=[self.repo])
234 issues = _issues_as_dict(commits)
239 issues = _issues_as_dict(commits)
235
240
236 branches = set(
241 branches = set(
237 commit['branch'] for commit in commits if commit['branch'])
242 commit['branch'] for commit in commits if commit['branch'])
238 branches = [
243 branches = [
239 {
244 {
240 'name': branch,
245 'name': branch,
241 'url': '{}/changelog?branch={}'.format(
246 'url': '{}/changelog?branch={}'.format(
242 data['repo']['url'], branch)
247 data['repo']['url'], branch)
243 }
248 }
244 for branch in branches
249 for branch in branches
245 ]
250 ]
246
251
247 data['push'] = {
252 data['push'] = {
248 'commits': commits,
253 'commits': commits,
249 'issues': issues,
254 'issues': issues,
250 'branches': branches,
255 'branches': branches,
251 }
256 }
252 return data
257 return data
General Comments 0
You need to be logged in to leave comments. Login now