Show More
@@ -40,7 +40,7 b' from rhodecode.admin.navigation import n' | |||||
40 | from rhodecode.translation import _ |
|
40 | from rhodecode.translation import _ | |
41 | from rhodecode.integrations import integration_type_registry |
|
41 | from rhodecode.integrations import integration_type_registry | |
42 | from rhodecode.model.validation_schema.schemas.integration_schema import ( |
|
42 | from rhodecode.model.validation_schema.schemas.integration_schema import ( | |
43 | make_integration_schema) |
|
43 | make_integration_schema, IntegrationScopeType) | |
44 |
|
44 | |||
45 | log = logging.getLogger(__name__) |
|
45 | log = logging.getLogger(__name__) | |
46 |
|
46 | |||
@@ -151,7 +151,11 b' class IntegrationSettingsViewBase(object' | |||||
151 | defaults['options'] = { |
|
151 | defaults['options'] = { | |
152 | 'name': self.integration.name, |
|
152 | 'name': self.integration.name, | |
153 | 'enabled': self.integration.enabled, |
|
153 | 'enabled': self.integration.enabled, | |
154 |
'scope': |
|
154 | 'scope': { | |
|
155 | 'repo': self.integration.repo, | |||
|
156 | 'repo_group': self.integration.repo_group, | |||
|
157 | 'child_repos_only': self.integration.child_repos_only, | |||
|
158 | }, | |||
155 | } |
|
159 | } | |
156 | else: |
|
160 | else: | |
157 | if self.repo: |
|
161 | if self.repo: | |
@@ -168,10 +172,10 b' class IntegrationSettingsViewBase(object' | |||||
168 | 'name': _('{name} integration').format( |
|
172 | 'name': _('{name} integration').format( | |
169 | name=self.IntegrationType.display_name), |
|
173 | name=self.IntegrationType.display_name), | |
170 | } |
|
174 | } | |
171 | if self.repo: |
|
175 | defaults['options']['scope'] = { | |
172 |
|
|
176 | 'repo': self.repo, | |
173 |
|
|
177 | 'repo_group': self.repo_group, | |
174 | defaults['options']['scope'] = self.repo_group |
|
178 | } | |
175 |
|
179 | |||
176 | return defaults |
|
180 | return defaults | |
177 |
|
181 | |||
@@ -250,11 +254,10 b' class IntegrationSettingsViewBase(object' | |||||
250 | # scope is read only field in these cases, and has to be added |
|
254 | # scope is read only field in these cases, and has to be added | |
251 | options = pstruct.setdefault('options', {}) |
|
255 | options = pstruct.setdefault('options', {}) | |
252 | if 'scope' not in options: |
|
256 | if 'scope' not in options: | |
253 | if self.repo: |
|
257 | options['scope'] = IntegrationScopeType().serialize(None, { | |
254 |
|
|
258 | 'repo': self.repo, | |
255 |
|
|
259 | 'repo_group': self.repo_group, | |
256 | options['scope'] = 'repogroup:{}'.format( |
|
260 | }) | |
257 | self.repo_group.group_name) |
|
|||
258 |
|
261 | |||
259 | try: |
|
262 | try: | |
260 | valid_data = form.validate_pstruct(pstruct) |
|
263 | valid_data = form.validate_pstruct(pstruct) | |
@@ -276,7 +279,11 b' class IntegrationSettingsViewBase(object' | |||||
276 | name=valid_data['options']['name'], |
|
279 | name=valid_data['options']['name'], | |
277 | enabled=valid_data['options']['enabled'], |
|
280 | enabled=valid_data['options']['enabled'], | |
278 | settings=valid_data['settings'], |
|
281 | settings=valid_data['settings'], | |
279 |
|
|
282 | repo=scope['repo'], | |
|
283 | repo_group=scope['repo_group'], | |||
|
284 | child_repos_only=scope['child_repos_only'], | |||
|
285 | ) | |||
|
286 | ||||
280 |
|
287 | |||
281 | self.integration.settings = valid_data['settings'] |
|
288 | self.integration.settings = valid_data['settings'] | |
282 | Session().commit() |
|
289 | Session().commit() | |
@@ -291,16 +298,16 b' class IntegrationSettingsViewBase(object' | |||||
291 | # keeping in mind if the original view was for /repo/ or /_admin/ |
|
298 | # keeping in mind if the original view was for /repo/ or /_admin/ | |
292 | admin_view = not (self.repo or self.repo_group) |
|
299 | admin_view = not (self.repo or self.repo_group) | |
293 |
|
300 | |||
294 |
if |
|
301 | if self.integration.repo and not admin_view: | |
295 | redirect_to = self.request.route_path( |
|
302 | redirect_to = self.request.route_path( | |
296 | 'repo_integrations_edit', |
|
303 | 'repo_integrations_edit', | |
297 |
repo_name=self.integration. |
|
304 | repo_name=self.integration.repo.repo_name, | |
298 | integration=self.integration.integration_type, |
|
305 | integration=self.integration.integration_type, | |
299 | integration_id=self.integration.integration_id) |
|
306 | integration_id=self.integration.integration_id) | |
300 |
elif |
|
307 | elif self.integration.repo_group and not admin_view: | |
301 | redirect_to = self.request.route_path( |
|
308 | redirect_to = self.request.route_path( | |
302 | 'repo_group_integrations_edit', |
|
309 | 'repo_group_integrations_edit', | |
303 |
repo_group_name=self.integration. |
|
310 | repo_group_name=self.integration.repo_group.group_name, | |
304 | integration=self.integration.integration_type, |
|
311 | integration=self.integration.integration_type, | |
305 | integration_id=self.integration.integration_id) |
|
312 | integration_id=self.integration.integration_id) | |
306 | else: |
|
313 | else: |
@@ -3499,36 +3499,18 b' class Integration(Base, BaseModel):' | |||||
3499 | nullable=True, unique=None, default=None) |
|
3499 | nullable=True, unique=None, default=None) | |
3500 | repo_group = relationship('RepoGroup', lazy='joined') |
|
3500 | repo_group = relationship('RepoGroup', lazy='joined') | |
3501 |
|
3501 | |||
3502 |
@ |
|
3502 | @property | |
3503 | def scope(self): |
|
3503 | def scope(self): | |
3504 | if self.repo: |
|
3504 | if self.repo: | |
3505 | return self.repo |
|
3505 | return repr(self.repo) | |
3506 | if self.repo_group: |
|
3506 | if self.repo_group: | |
3507 |
|
|
3507 | if self.child_repos_only: | |
|
3508 | return repr(self.repo_group) + ' (child repos only)' | |||
|
3509 | else: | |||
|
3510 | return repr(self.repo_group) + ' (recursive)' | |||
3508 | if self.child_repos_only: |
|
3511 | if self.child_repos_only: | |
3509 | return 'root_repos' |
|
3512 | return 'root_repos' | |
3510 | return 'global' |
|
3513 | return 'global' | |
3511 |
|
3514 | |||
3512 | @scope.setter |
|
|||
3513 | def scope(self, value): |
|
|||
3514 | self.repo = None |
|
|||
3515 | self.repo_id = None |
|
|||
3516 | self.repo_group_id = None |
|
|||
3517 | self.repo_group = None |
|
|||
3518 | self.child_repos_only = False |
|
|||
3519 | if isinstance(value, Repository): |
|
|||
3520 | self.repo_id = value.repo_id |
|
|||
3521 | self.repo = value |
|
|||
3522 | elif isinstance(value, RepoGroup): |
|
|||
3523 | self.repo_group_id = value.group_id |
|
|||
3524 | self.repo_group = value |
|
|||
3525 | elif value == 'root_repos': |
|
|||
3526 | self.child_repos_only = True |
|
|||
3527 | elif value == 'global': |
|
|||
3528 | pass |
|
|||
3529 | else: |
|
|||
3530 | raise Exception("invalid scope: %s, must be one of " |
|
|||
3531 | "['global', 'root_repos', <RepoGroup>. <Repository>]" % value) |
|
|||
3532 |
|
||||
3533 | def __repr__(self): |
|
3515 | def __repr__(self): | |
3534 | return '<Integration(%r, %r)>' % (self.integration_type, self.scope) |
|
3516 | return '<Integration(%r, %r)>' % (self.integration_type, self.scope) |
@@ -61,23 +61,24 b' class IntegrationModel(BaseModel):' | |||||
61 | raise Exception('integration must be int, long or Instance' |
|
61 | raise Exception('integration must be int, long or Instance' | |
62 | ' of Integration got %s' % type(integration)) |
|
62 | ' of Integration got %s' % type(integration)) | |
63 |
|
63 | |||
64 |
def create(self, IntegrationType, name, enabled, |
|
64 | def create(self, IntegrationType, name, enabled, repo, repo_group, | |
|
65 | child_repos_only, settings): | |||
65 | """ Create an IntegrationType integration """ |
|
66 | """ Create an IntegrationType integration """ | |
66 | integration = Integration() |
|
67 | integration = Integration() | |
67 | integration.integration_type = IntegrationType.key |
|
68 | integration.integration_type = IntegrationType.key | |
68 | self.sa.add(integration) |
|
69 | self.sa.add(integration) | |
69 |
self.update_integration(integration, name, enabled, |
|
70 | self.update_integration(integration, name, enabled, repo, repo_group, | |
|
71 | child_repos_only, settings) | |||
70 | self.sa.commit() |
|
72 | self.sa.commit() | |
71 | return integration |
|
73 | return integration | |
72 |
|
74 | |||
73 |
def update_integration(self, integration, name, enabled, |
|
75 | def update_integration(self, integration, name, enabled, repo, repo_group, | |
74 | """ |
|
76 | child_repos_only, settings): | |
75 | :param scope: one of ['global', 'root_repos', <RepoGroup>. <Repository>] |
|
|||
76 | """ |
|
|||
77 |
|
||||
78 | integration = self.__get_integration(integration) |
|
77 | integration = self.__get_integration(integration) | |
79 |
|
78 | |||
80 |
integration. |
|
79 | integration.repo = repo | |
|
80 | integration.repo_group = repo_group | |||
|
81 | integration.child_repos_only = child_repos_only | |||
81 | integration.name = name |
|
82 | integration.name = name | |
82 | integration.enabled = enabled |
|
83 | integration.enabled = enabled | |
83 | integration.settings = settings |
|
84 | integration.settings = settings | |
@@ -127,7 +128,7 b' class IntegrationModel(BaseModel):' | |||||
127 | query = self.sa.query(Integration).filter( |
|
128 | query = self.sa.query(Integration).filter( | |
128 | and_(Integration.repo_id==None, Integration.repo_group_id==None) |
|
129 | and_(Integration.repo_id==None, Integration.repo_group_id==None) | |
129 | ) |
|
130 | ) | |
130 |
elif scope == 'root |
|
131 | elif scope == 'root-repos': | |
131 | query = self.sa.query(Integration).filter( |
|
132 | query = self.sa.query(Integration).filter( | |
132 | and_(Integration.repo_id==None, |
|
133 | and_(Integration.repo_id==None, | |
133 | Integration.repo_group_id==None, |
|
134 | Integration.repo_group_id==None, | |
@@ -185,13 +186,21 b' class IntegrationModel(BaseModel):' | |||||
185 |
|
186 | |||
186 | if event.repo.group: |
|
187 | if event.repo.group: | |
187 | clauses.append( |
|
188 | clauses.append( | |
188 | Integration.repo_group_id == event.repo.group.group_id |
|
189 | and_( | |
|
190 | Integration.repo_group_id==event.repo.group.group_id, | |||
|
191 | Integration.child_repos_only==True | |||
|
192 | ) | |||
189 | ) |
|
193 | ) | |
190 |
# repo group cascade to kids |
|
194 | # repo group cascade to kids | |
191 |
|
|
195 | clauses.append( | |
192 | # [group.group_id for group in |
|
196 | and_( | |
193 |
|
|
197 | Integration.repo_group_id.in_( | |
194 | # )) |
|
198 | [group.group_id for group in | |
|
199 | event.repo.groups_with_parents] | |||
|
200 | ), | |||
|
201 | Integration.child_repos_only==False | |||
|
202 | ) | |||
|
203 | ) | |||
195 |
|
204 | |||
196 |
|
205 | |||
197 | if not event.repo.group: # root repo |
|
206 | if not event.repo.group: # root repo |
@@ -37,7 +37,7 b' def integration_scope_choices(permission' | |||||
37 | if 'hg.admin' in permissions['global']: |
|
37 | if 'hg.admin' in permissions['global']: | |
38 | result.extend([ |
|
38 | result.extend([ | |
39 | ('global', _('Global (all repositories)')), |
|
39 | ('global', _('Global (all repositories)')), | |
40 |
('root |
|
40 | ('root-repos', _('Top level repositories only')), | |
41 | ]) |
|
41 | ]) | |
42 |
|
42 | |||
43 | repo_choices = [ |
|
43 | repo_choices = [ | |
@@ -47,13 +47,19 b' def integration_scope_choices(permission' | |||||
47 | if repo_perm == 'repository.admin' |
|
47 | if repo_perm == 'repository.admin' | |
48 | ] |
|
48 | ] | |
49 | repogroup_choices = [ |
|
49 | repogroup_choices = [ | |
50 |
('repogroup:%s' % repo_group_name, '/' + repo_group_name + ' |
|
50 | ('repogroup:%s' % repo_group_name, '/' + repo_group_name + '/ (child repos only)') | |
|
51 | for repo_group_name, repo_group_perm | |||
|
52 | in permissions['repositories_groups'].items() | |||
|
53 | if repo_group_perm == 'group.admin' | |||
|
54 | ] | |||
|
55 | repogroup_recursive_choices = [ | |||
|
56 | ('repogroup-recursive:%s' % repo_group_name, '/' + repo_group_name + '/ (recursive)') | |||
51 | for repo_group_name, repo_group_perm |
|
57 | for repo_group_name, repo_group_perm | |
52 | in permissions['repositories_groups'].items() |
|
58 | in permissions['repositories_groups'].items() | |
53 | if repo_group_perm == 'group.admin' |
|
59 | if repo_group_perm == 'group.admin' | |
54 | ] |
|
60 | ] | |
55 | result.extend( |
|
61 | result.extend( | |
56 | sorted(repogroup_choices + repo_choices, |
|
62 | sorted(repogroup_recursive_choices + repogroup_choices + repo_choices, | |
57 | key=lambda (choice, label): choice.split(':', 1)[1] |
|
63 | key=lambda (choice, label): choice.split(':', 1)[1] | |
58 | ) |
|
64 | ) | |
59 | ) |
|
65 | ) | |
@@ -66,27 +72,24 b' def deferred_integration_scopes_validato' | |||||
66 | def _scope_validator(_node, scope): |
|
72 | def _scope_validator(_node, scope): | |
67 | is_super_admin = 'hg.admin' in perms['global'] |
|
73 | is_super_admin = 'hg.admin' in perms['global'] | |
68 |
|
74 | |||
69 |
if scope |
|
75 | if scope.get('repo'): | |
|
76 | if (is_super_admin or perms['repositories'].get( | |||
|
77 | scope['repo'].repo_name) == 'repository.admin'): | |||
|
78 | return True | |||
|
79 | msg = _('Only repo admins can create integrations') | |||
|
80 | raise colander.Invalid(_node, msg) | |||
|
81 | elif scope.get('repo_group'): | |||
|
82 | if (is_super_admin or perms['repositories_groups'].get( | |||
|
83 | scope['repo_group'].group_name) == 'group.admin'): | |||
|
84 | return True | |||
|
85 | ||||
|
86 | msg = _('Only repogroup admins can create integrations') | |||
|
87 | raise colander.Invalid(_node, msg) | |||
|
88 | else: | |||
70 | if is_super_admin: |
|
89 | if is_super_admin: | |
71 | return True |
|
90 | return True | |
72 | msg = _('Only superadmins can create global integrations') |
|
91 | msg = _('Only superadmins can create global integrations') | |
73 | raise colander.Invalid(_node, msg) |
|
92 | raise colander.Invalid(_node, msg) | |
74 | elif isinstance(scope, Repository): |
|
|||
75 | if (is_super_admin or perms['repositories'].get( |
|
|||
76 | scope.repo_name) == 'repository.admin'): |
|
|||
77 | return True |
|
|||
78 | msg = _('Only repo admins can create integrations') |
|
|||
79 | raise colander.Invalid(_node, msg) |
|
|||
80 | elif isinstance(scope, RepoGroup): |
|
|||
81 | if (is_super_admin or perms['repositories_groups'].get( |
|
|||
82 | scope.group_name) == 'group.admin'): |
|
|||
83 | return True |
|
|||
84 |
|
||||
85 | msg = _('Only repogroup admins can create integrations') |
|
|||
86 | raise colander.Invalid(_node, msg) |
|
|||
87 |
|
||||
88 | msg = _('Invalid integration scope: %s' % scope) |
|
|||
89 | raise colander.Invalid(node, msg) |
|
|||
90 |
|
93 | |||
91 | return _scope_validator |
|
94 | return _scope_validator | |
92 |
|
95 | |||
@@ -100,17 +103,26 b' def deferred_integration_scopes_widget(n' | |||||
100 | widget = deform.widget.Select2Widget(values=choices) |
|
103 | widget = deform.widget.Select2Widget(values=choices) | |
101 | return widget |
|
104 | return widget | |
102 |
|
105 | |||
103 | class IntegrationScope(colander.SchemaType): |
|
106 | ||
|
107 | class IntegrationScopeType(colander.SchemaType): | |||
104 | def serialize(self, node, appstruct): |
|
108 | def serialize(self, node, appstruct): | |
105 | if appstruct is colander.null: |
|
109 | if appstruct is colander.null: | |
106 | return colander.null |
|
110 | return colander.null | |
107 |
|
111 | |||
108 |
if |
|
112 | if appstruct.get('repo'): | |
109 | return 'repo:%s' % appstruct.repo_name |
|
113 | return 'repo:%s' % appstruct['repo'].repo_name | |
110 |
elif |
|
114 | elif appstruct.get('repo_group'): | |
111 | return 'repogroup:%s' % appstruct.group_name |
|
115 | if appstruct.get('child_repos_only'): | |
112 | elif appstruct in ('global', 'root_repos'): |
|
116 | return 'repogroup:%s' % appstruct['repo_group'].group_name | |
113 |
|
|
117 | else: | |
|
118 | return 'repogroup-recursive:%s' % ( | |||
|
119 | appstruct['repo_group'].group_name) | |||
|
120 | else: | |||
|
121 | if appstruct.get('child_repos_only'): | |||
|
122 | return 'root-repos' | |||
|
123 | else: | |||
|
124 | return 'global' | |||
|
125 | ||||
114 | raise colander.Invalid(node, '%r is not a valid scope' % appstruct) |
|
126 | raise colander.Invalid(node, '%r is not a valid scope' % appstruct) | |
115 |
|
127 | |||
116 | def deserialize(self, node, cstruct): |
|
128 | def deserialize(self, node, cstruct): | |
@@ -120,16 +132,43 b' class IntegrationScope(colander.SchemaTy' | |||||
120 | if cstruct.startswith('repo:'): |
|
132 | if cstruct.startswith('repo:'): | |
121 | repo = Repository.get_by_repo_name(cstruct.split(':')[1]) |
|
133 | repo = Repository.get_by_repo_name(cstruct.split(':')[1]) | |
122 | if repo: |
|
134 | if repo: | |
123 |
return |
|
135 | return { | |
|
136 | 'repo': repo, | |||
|
137 | 'repo_group': None, | |||
|
138 | 'child_repos_only': None, | |||
|
139 | } | |||
|
140 | elif cstruct.startswith('repogroup-recursive:'): | |||
|
141 | repo_group = RepoGroup.get_by_group_name(cstruct.split(':')[1]) | |||
|
142 | if repo_group: | |||
|
143 | return { | |||
|
144 | 'repo': None, | |||
|
145 | 'repo_group': repo_group, | |||
|
146 | 'child_repos_only': False | |||
|
147 | } | |||
124 | elif cstruct.startswith('repogroup:'): |
|
148 | elif cstruct.startswith('repogroup:'): | |
125 | repo_group = RepoGroup.get_by_group_name(cstruct.split(':')[1]) |
|
149 | repo_group = RepoGroup.get_by_group_name(cstruct.split(':')[1]) | |
126 | if repo_group: |
|
150 | if repo_group: | |
127 |
return |
|
151 | return { | |
128 | elif cstruct in ('global', 'root_repos'): |
|
152 | 'repo': None, | |
129 | return cstruct |
|
153 | 'repo_group': repo_group, | |
|
154 | 'child_repos_only': True | |||
|
155 | } | |||
|
156 | elif cstruct == 'global': | |||
|
157 | return { | |||
|
158 | 'repo': None, | |||
|
159 | 'repo_group': None, | |||
|
160 | 'child_repos_only': False | |||
|
161 | } | |||
|
162 | elif cstruct == 'root-repos': | |||
|
163 | return { | |||
|
164 | 'repo': None, | |||
|
165 | 'repo_group': None, | |||
|
166 | 'child_repos_only': True | |||
|
167 | } | |||
130 |
|
168 | |||
131 | raise colander.Invalid(node, '%r is not a valid scope' % cstruct) |
|
169 | raise colander.Invalid(node, '%r is not a valid scope' % cstruct) | |
132 |
|
170 | |||
|
171 | ||||
133 | class IntegrationOptionsSchemaBase(colander.MappingSchema): |
|
172 | class IntegrationOptionsSchemaBase(colander.MappingSchema): | |
134 |
|
173 | |||
135 | name = colander.SchemaNode( |
|
174 | name = colander.SchemaNode( | |
@@ -140,10 +179,10 b' class IntegrationOptionsSchemaBase(colan' | |||||
140 | ) |
|
179 | ) | |
141 |
|
180 | |||
142 | scope = colander.SchemaNode( |
|
181 | scope = colander.SchemaNode( | |
143 | IntegrationScope(), |
|
182 | IntegrationScopeType(), | |
144 | description=_( |
|
183 | description=_( | |
145 |
'Scope of the integration. |
|
184 | 'Scope of the integration. Recursive means the integration ' | |
146 |
' runs on all |
|
185 | ' runs on all repos of that group and children recursively.'), | |
147 | title=_('Integration scope'), |
|
186 | title=_('Integration scope'), | |
148 | validator=deferred_integration_scopes_validator, |
|
187 | validator=deferred_integration_scopes_validator, | |
149 | widget=deferred_integration_scopes_widget, |
|
188 | widget=deferred_integration_scopes_widget, |
@@ -166,14 +166,17 b'' | |||||
166 | %elif integration.repo_group: |
|
166 | %elif integration.repo_group: | |
167 | <a href="${h.url('repo_group_home', group_name=integration.repo_group.group_name)}"> |
|
167 | <a href="${h.url('repo_group_home', group_name=integration.repo_group.group_name)}"> | |
168 | ${_('repogroup')}:${integration.repo_group.group_name} |
|
168 | ${_('repogroup')}:${integration.repo_group.group_name} | |
|
169 | %if integration.child_repos_only: | |||
|
170 | ${_('child repos only')} | |||
|
171 | %else: | |||
|
172 | ${_('cascade to all')} | |||
|
173 | %endif | |||
169 | </a> |
|
174 | </a> | |
170 | %else: |
|
175 | %else: | |
171 |
%if integration. |
|
176 | %if integration.child_repos_only: | |
172 | ${_('top level repos only')} |
|
177 | ${_('top level repos only')} | |
173 | %elif integration.scope == 'global': |
|
178 | %else: | |
174 | ${_('global')} |
|
179 | ${_('global')} | |
175 | %else: |
|
|||
176 | ${_('unknown scope')}: ${integration.scope} |
|
|||
177 | %endif |
|
180 | %endif | |
178 | </td> |
|
181 | </td> | |
179 | %endif |
|
182 | %endif |
@@ -222,12 +222,14 b' def _post_integration_test_helper(app, u' | |||||
222 | scopes_destinations = [ |
|
222 | scopes_destinations = [ | |
223 | ('global', |
|
223 | ('global', | |
224 | ADMIN_PREFIX + '/integrations'), |
|
224 | ADMIN_PREFIX + '/integrations'), | |
225 |
('root |
|
225 | ('root-repos', | |
226 | ADMIN_PREFIX + '/integrations'), |
|
226 | ADMIN_PREFIX + '/integrations'), | |
227 | ('repo:%s' % repo.repo_name, |
|
227 | ('repo:%s' % repo.repo_name, | |
228 | '/%s/settings/integrations' % repo.repo_name), |
|
228 | '/%s/settings/integrations' % repo.repo_name), | |
229 | ('repogroup:%s' % repo_group.group_name, |
|
229 | ('repogroup:%s' % repo_group.group_name, | |
230 | '/%s/settings/integrations' % repo_group.group_name), |
|
230 | '/%s/settings/integrations' % repo_group.group_name), | |
|
231 | ('repogroup-recursive:%s' % repo_group.group_name, | |||
|
232 | '/%s/settings/integrations' % repo_group.group_name), | |||
231 | ] |
|
233 | ] | |
232 |
|
234 | |||
233 | for scope, destination in scopes_destinations: |
|
235 | for scope, destination in scopes_destinations: |
@@ -51,75 +51,84 b' class TestDeleteScopesDeletesIntegration' | |||||
51 | def integration_repos(request, StubIntegrationType, stub_integration_settings): |
|
51 | def integration_repos(request, StubIntegrationType, stub_integration_settings): | |
52 | """ |
|
52 | """ | |
53 | Create repositories and integrations for testing, and destroy them after |
|
53 | Create repositories and integrations for testing, and destroy them after | |
|
54 | ||||
|
55 | Structure: | |||
|
56 | root_repo | |||
|
57 | parent_group/ | |||
|
58 | parent_repo | |||
|
59 | child_group/ | |||
|
60 | child_repo | |||
|
61 | other_group/ | |||
|
62 | other_repo | |||
54 | """ |
|
63 | """ | |
55 | fixture = Fixture() |
|
64 | fixture = Fixture() | |
56 |
|
65 | |||
57 | repo_group_1_id = 'int_test_repo_group_1_%s' % time.time() |
|
66 | ||
58 | repo_group_1 = fixture.create_repo_group(repo_group_1_id) |
|
67 | parent_group_id = 'int_test_parent_group_%s' % time.time() | |
59 | repo_group_2_id = 'int_test_repo_group_2_%s' % time.time() |
|
68 | parent_group = fixture.create_repo_group(parent_group_id) | |
60 | repo_group_2 = fixture.create_repo_group(repo_group_2_id) |
|
69 | ||
|
70 | other_group_id = 'int_test_other_group_%s' % time.time() | |||
|
71 | other_group = fixture.create_repo_group(other_group_id) | |||
61 |
|
72 | |||
62 | repo_1_id = 'int_test_repo_1_%s' % time.time() |
|
73 | child_group_id = ( | |
63 | repo_1 = fixture.create_repo(repo_1_id, repo_group=repo_group_1) |
|
74 | parent_group_id + '/' + 'int_test_child_group_%s' % time.time()) | |
64 | repo_2_id = 'int_test_repo_2_%s' % time.time() |
|
75 | child_group = fixture.create_repo_group(child_group_id) | |
65 | repo_2 = fixture.create_repo(repo_2_id, repo_group=repo_group_2) |
|
76 | ||
|
77 | parent_repo_id = 'int_test_parent_repo_%s' % time.time() | |||
|
78 | parent_repo = fixture.create_repo(parent_repo_id, repo_group=parent_group) | |||
|
79 | ||||
|
80 | child_repo_id = 'int_test_child_repo_%s' % time.time() | |||
|
81 | child_repo = fixture.create_repo(child_repo_id, repo_group=child_group) | |||
|
82 | ||||
|
83 | other_repo_id = 'int_test_other_repo_%s' % time.time() | |||
|
84 | other_repo = fixture.create_repo(other_repo_id, repo_group=other_group) | |||
66 |
|
85 | |||
67 | root_repo_id = 'int_test_repo_root_%s' % time.time() |
|
86 | root_repo_id = 'int_test_repo_root_%s' % time.time() | |
68 | root_repo = fixture.create_repo(root_repo_id) |
|
87 | root_repo = fixture.create_repo(root_repo_id) | |
69 |
|
88 | |||
70 | integration_global = IntegrationModel().create( |
|
89 | integrations = {} | |
71 | StubIntegrationType, settings=stub_integration_settings, |
|
90 | for name, repo, repo_group, child_repos_only in [ | |
72 | enabled=True, name='test global integration', scope='global') |
|
91 | ('global', None, None, None), | |
73 | integration_root_repos = IntegrationModel().create( |
|
92 | ('root_repos', None, None, True), | |
74 | StubIntegrationType, settings=stub_integration_settings, |
|
93 | ('parent_repo', parent_repo, None, None), | |
75 | enabled=True, name='test root repos integration', scope='root_repos') |
|
94 | ('child_repo', child_repo, None, None), | |
76 | integration_repo_1 = IntegrationModel().create( |
|
95 | ('other_repo', other_repo, None, None), | |
|
96 | ('root_repo', root_repo, None, None), | |||
|
97 | ('parent_group', None, parent_group, True), | |||
|
98 | ('parent_group_recursive', None, parent_group, False), | |||
|
99 | ('child_group', None, child_group, True), | |||
|
100 | ('child_group_recursive', None, child_group, False), | |||
|
101 | ('other_group', None, other_group, True), | |||
|
102 | ('other_group_recursive', None, other_group, False), | |||
|
103 | ]: | |||
|
104 | integrations[name] = IntegrationModel().create( | |||
77 | StubIntegrationType, settings=stub_integration_settings, |
|
105 | StubIntegrationType, settings=stub_integration_settings, | |
78 |
enabled=True, name='test |
|
106 | enabled=True, name='test %s integration' % name, | |
79 | integration_repo_group_1 = IntegrationModel().create( |
|
107 | repo=repo, repo_group=repo_group, child_repos_only=child_repos_only) | |
80 | StubIntegrationType, settings=stub_integration_settings, |
|
|||
81 | enabled=True, name='test repo group 1 integration', scope=repo_group_1) |
|
|||
82 | integration_repo_2 = IntegrationModel().create( |
|
|||
83 | StubIntegrationType, settings=stub_integration_settings, |
|
|||
84 | enabled=True, name='test repo 2 integration', scope=repo_2) |
|
|||
85 | integration_repo_group_2 = IntegrationModel().create( |
|
|||
86 | StubIntegrationType, settings=stub_integration_settings, |
|
|||
87 | enabled=True, name='test repo group 2 integration', scope=repo_group_2) |
|
|||
88 |
|
108 | |||
89 | Session().commit() |
|
109 | Session().commit() | |
90 |
|
110 | |||
91 | def _cleanup(): |
|
111 | def _cleanup(): | |
92 | Session().delete(integration_global) |
|
112 | for integration in integrations.values(): | |
93 |
Session |
|
113 | Session.delete(integration) | |
94 | Session().delete(integration_repo_1) |
|
114 | ||
95 | Session().delete(integration_repo_group_1) |
|
|||
96 | Session().delete(integration_repo_2) |
|
|||
97 | Session().delete(integration_repo_group_2) |
|
|||
98 | fixture.destroy_repo(root_repo) |
|
115 | fixture.destroy_repo(root_repo) | |
99 |
fixture.destroy_repo(repo |
|
116 | fixture.destroy_repo(child_repo) | |
100 |
fixture.destroy_repo(repo |
|
117 | fixture.destroy_repo(parent_repo) | |
101 |
fixture.destroy_repo |
|
118 | fixture.destroy_repo(other_repo) | |
102 |
fixture.destroy_repo_group( |
|
119 | fixture.destroy_repo_group(child_group) | |
|
120 | fixture.destroy_repo_group(parent_group) | |||
|
121 | fixture.destroy_repo_group(other_group) | |||
103 |
|
122 | |||
104 | request.addfinalizer(_cleanup) |
|
123 | request.addfinalizer(_cleanup) | |
105 |
|
124 | |||
106 | return { |
|
125 | return { | |
|
126 | 'integrations': integrations, | |||
107 | 'repos': { |
|
127 | 'repos': { | |
108 | 'repo_1': repo_1, |
|
|||
109 | 'repo_2': repo_2, |
|
|||
110 | 'root_repo': root_repo, |
|
128 | 'root_repo': root_repo, | |
111 | }, |
|
129 | 'other_repo': other_repo, | |
112 | 'repo_groups': { |
|
130 | 'parent_repo': parent_repo, | |
113 |
'repo |
|
131 | 'child_repo': child_repo, | |
114 | 'repo_group_2': repo_group_2, |
|
|||
115 | }, |
|
|||
116 | 'integrations': { |
|
|||
117 | 'global': integration_global, |
|
|||
118 | 'root_repos': integration_root_repos, |
|
|||
119 | 'repo_1': integration_repo_1, |
|
|||
120 | 'repo_2': integration_repo_2, |
|
|||
121 | 'repo_group_1': integration_repo_group_1, |
|
|||
122 | 'repo_group_2': integration_repo_group_2, |
|
|||
123 | } |
|
132 | } | |
124 | } |
|
133 | } | |
125 |
|
134 | |||
@@ -133,27 +142,41 b' def test_enabled_integration_repo_scopes' | |||||
133 |
|
142 | |||
134 | assert triggered_integrations == [ |
|
143 | assert triggered_integrations == [ | |
135 | integrations['global'], |
|
144 | integrations['global'], | |
136 | integrations['root_repos'] |
|
145 | integrations['root_repos'], | |
|
146 | integrations['root_repo'], | |||
|
147 | ] | |||
|
148 | ||||
|
149 | ||||
|
150 | triggered_integrations = IntegrationModel().get_for_event( | |||
|
151 | events.RepoEvent(repos['other_repo'])) | |||
|
152 | ||||
|
153 | assert triggered_integrations == [ | |||
|
154 | integrations['global'], | |||
|
155 | integrations['other_repo'], | |||
|
156 | integrations['other_group'], | |||
|
157 | integrations['other_group_recursive'], | |||
137 | ] |
|
158 | ] | |
138 |
|
159 | |||
139 |
|
160 | |||
140 | triggered_integrations = IntegrationModel().get_for_event( |
|
161 | triggered_integrations = IntegrationModel().get_for_event( | |
141 |
events.RepoEvent(repos['repo |
|
162 | events.RepoEvent(repos['parent_repo'])) | |
142 |
|
163 | |||
143 | assert triggered_integrations == [ |
|
164 | assert triggered_integrations == [ | |
144 | integrations['global'], |
|
165 | integrations['global'], | |
145 |
integrations['repo |
|
166 | integrations['parent_repo'], | |
146 |
integrations[' |
|
167 | integrations['parent_group'], | |
|
168 | integrations['parent_group_recursive'], | |||
147 | ] |
|
169 | ] | |
148 |
|
170 | |||
149 |
|
||||
150 | triggered_integrations = IntegrationModel().get_for_event( |
|
171 | triggered_integrations = IntegrationModel().get_for_event( | |
151 |
events.RepoEvent(repos['repo |
|
172 | events.RepoEvent(repos['child_repo'])) | |
152 |
|
173 | |||
153 | assert triggered_integrations == [ |
|
174 | assert triggered_integrations == [ | |
154 | integrations['global'], |
|
175 | integrations['global'], | |
155 |
integrations['repo |
|
176 | integrations['child_repo'], | |
156 |
integrations[' |
|
177 | integrations['parent_group_recursive'], | |
|
178 | integrations['child_group'], | |||
|
179 | integrations['child_group_recursive'], | |||
157 | ] |
|
180 | ] | |
158 |
|
181 | |||
159 |
|
182 | |||
@@ -172,17 +195,24 b' def test_disabled_integration_repo_scope' | |||||
172 |
|
195 | |||
173 |
|
196 | |||
174 | triggered_integrations = IntegrationModel().get_for_event( |
|
197 | triggered_integrations = IntegrationModel().get_for_event( | |
175 |
events.RepoEvent(repos['repo |
|
198 | events.RepoEvent(repos['parent_repo'])) | |
176 |
|
199 | |||
177 | assert triggered_integrations == [] |
|
200 | assert triggered_integrations == [] | |
178 |
|
201 | |||
179 |
|
202 | |||
180 | triggered_integrations = IntegrationModel().get_for_event( |
|
203 | triggered_integrations = IntegrationModel().get_for_event( | |
181 |
events.RepoEvent(repos['repo |
|
204 | events.RepoEvent(repos['child_repo'])) | |
182 |
|
205 | |||
183 | assert triggered_integrations == [] |
|
206 | assert triggered_integrations == [] | |
184 |
|
207 | |||
185 |
|
208 | |||
|
209 | triggered_integrations = IntegrationModel().get_for_event( | |||
|
210 | events.RepoEvent(repos['other_repo'])) | |||
|
211 | ||||
|
212 | assert triggered_integrations == [] | |||
|
213 | ||||
|
214 | ||||
|
215 | ||||
186 | def test_enabled_non_repo_integrations(integration_repos): |
|
216 | def test_enabled_non_repo_integrations(integration_repos): | |
187 | integrations = integration_repos['integrations'] |
|
217 | integrations = integration_repos['integrations'] | |
188 |
|
218 |
@@ -47,8 +47,15 b' class TestIntegrationSchema(object):' | |||||
47 | 'repositories_groups': {}, |
|
47 | 'repositories_groups': {}, | |
48 | } |
|
48 | } | |
49 |
|
49 | |||
50 |
perms_tests = |
|
50 | perms_tests = [ | |
51 | ('repo:%s' % repo.repo_name, repo): [ |
|
51 | ( | |
|
52 | 'repo:%s' % repo.repo_name, | |||
|
53 | { | |||
|
54 | 'child_repos_only': None, | |||
|
55 | 'repo_group': None, | |||
|
56 | 'repo': repo, | |||
|
57 | }, | |||
|
58 | [ | |||
52 | ({}, False), |
|
59 | ({}, False), | |
53 | ({'global': ['hg.admin']}, True), |
|
60 | ({'global': ['hg.admin']}, True), | |
54 | ({'global': []}, False), |
|
61 | ({'global': []}, False), | |
@@ -56,8 +63,16 b' class TestIntegrationSchema(object):' | |||||
56 | ({'repositories': {repo.repo_name: 'repository.read'}}, False), |
|
63 | ({'repositories': {repo.repo_name: 'repository.read'}}, False), | |
57 | ({'repositories': {repo.repo_name: 'repository.write'}}, False), |
|
64 | ({'repositories': {repo.repo_name: 'repository.write'}}, False), | |
58 | ({'repositories': {repo.repo_name: 'repository.none'}}, False), |
|
65 | ({'repositories': {repo.repo_name: 'repository.none'}}, False), | |
59 |
] |
|
66 | ] | |
60 | ('repogroup:%s' % repo_group.group_name, repo_group): [ |
|
67 | ), | |
|
68 | ( | |||
|
69 | 'repogroup:%s' % repo_group.group_name, | |||
|
70 | { | |||
|
71 | 'repo': None, | |||
|
72 | 'repo_group': repo_group, | |||
|
73 | 'child_repos_only': True, | |||
|
74 | }, | |||
|
75 | [ | |||
61 | ({}, False), |
|
76 | ({}, False), | |
62 | ({'global': ['hg.admin']}, True), |
|
77 | ({'global': ['hg.admin']}, True), | |
63 | ({'global': []}, False), |
|
78 | ({'global': []}, False), | |
@@ -69,20 +84,56 b' class TestIntegrationSchema(object):' | |||||
69 | {repo_group.group_name: 'group.write'}}, False), |
|
84 | {repo_group.group_name: 'group.write'}}, False), | |
70 | ({'repositories_groups': |
|
85 | ({'repositories_groups': | |
71 | {repo_group.group_name: 'group.none'}}, False), |
|
86 | {repo_group.group_name: 'group.none'}}, False), | |
72 |
] |
|
87 | ] | |
73 | ('global', 'global'): [ |
|
88 | ), | |
|
89 | ( | |||
|
90 | 'repogroup-recursive:%s' % repo_group.group_name, | |||
|
91 | { | |||
|
92 | 'repo': None, | |||
|
93 | 'repo_group': repo_group, | |||
|
94 | 'child_repos_only': False, | |||
|
95 | }, | |||
|
96 | [ | |||
74 | ({}, False), |
|
97 | ({}, False), | |
75 | ({'global': ['hg.admin']}, True), |
|
98 | ({'global': ['hg.admin']}, True), | |
76 | ({'global': []}, False), |
|
99 | ({'global': []}, False), | |
77 | ], |
|
100 | ({'repositories_groups': | |
78 | ('root_repos', 'root_repos'): [ |
|
101 | {repo_group.group_name: 'group.admin'}}, True), | |
|
102 | ({'repositories_groups': | |||
|
103 | {repo_group.group_name: 'group.read'}}, False), | |||
|
104 | ({'repositories_groups': | |||
|
105 | {repo_group.group_name: 'group.write'}}, False), | |||
|
106 | ({'repositories_groups': | |||
|
107 | {repo_group.group_name: 'group.none'}}, False), | |||
|
108 | ] | |||
|
109 | ), | |||
|
110 | ( | |||
|
111 | 'global', | |||
|
112 | { | |||
|
113 | 'repo': None, | |||
|
114 | 'repo_group': None, | |||
|
115 | 'child_repos_only': False, | |||
|
116 | }, [ | |||
79 | ({}, False), |
|
117 | ({}, False), | |
80 | ({'global': ['hg.admin']}, True), |
|
118 | ({'global': ['hg.admin']}, True), | |
81 | ({'global': []}, False), |
|
119 | ({'global': []}, False), | |
82 |
] |
|
120 | ] | |
83 |
|
|
121 | ), | |
|
122 | ( | |||
|
123 | 'root-repos', | |||
|
124 | { | |||
|
125 | 'repo': None, | |||
|
126 | 'repo_group': None, | |||
|
127 | 'child_repos_only': True, | |||
|
128 | }, [ | |||
|
129 | ({}, False), | |||
|
130 | ({'global': ['hg.admin']}, True), | |||
|
131 | ({'global': []}, False), | |||
|
132 | ] | |||
|
133 | ), | |||
|
134 | ] | |||
84 |
|
135 | |||
85 |
for |
|
136 | for scope_input, scope_output, perms_allowed in perms_tests: | |
86 | for perms_update, allowed in perms_allowed: |
|
137 | for perms_update, allowed in perms_allowed: | |
87 | perms = dict(empty_perms_dict, **perms_update) |
|
138 | perms = dict(empty_perms_dict, **perms_update) | |
88 |
|
139 |
@@ -1709,7 +1709,8 b' def repo_integration_stub(request, repo_' | |||||
1709 | stub_integration_settings): |
|
1709 | stub_integration_settings): | |
1710 | integration = IntegrationModel().create( |
|
1710 | integration = IntegrationModel().create( | |
1711 | StubIntegrationType, settings=stub_integration_settings, enabled=True, |
|
1711 | StubIntegrationType, settings=stub_integration_settings, enabled=True, | |
1712 |
name='test repo integration', |
|
1712 | name='test repo integration', | |
|
1713 | repo=repo_stub, repo_group=None, child_repos_only=None) | |||
1713 |
|
1714 | |||
1714 | @request.addfinalizer |
|
1715 | @request.addfinalizer | |
1715 | def cleanup(): |
|
1716 | def cleanup(): | |
@@ -1723,7 +1724,23 b' def repogroup_integration_stub(request, ' | |||||
1723 | stub_integration_settings): |
|
1724 | stub_integration_settings): | |
1724 | integration = IntegrationModel().create( |
|
1725 | integration = IntegrationModel().create( | |
1725 | StubIntegrationType, settings=stub_integration_settings, enabled=True, |
|
1726 | StubIntegrationType, settings=stub_integration_settings, enabled=True, | |
1726 |
name='test repogroup integration', |
|
1727 | name='test repogroup integration', | |
|
1728 | repo=None, repo_group=test_repo_group, child_repos_only=True) | |||
|
1729 | ||||
|
1730 | @request.addfinalizer | |||
|
1731 | def cleanup(): | |||
|
1732 | IntegrationModel().delete(integration) | |||
|
1733 | ||||
|
1734 | return integration | |||
|
1735 | ||||
|
1736 | ||||
|
1737 | @pytest.fixture | |||
|
1738 | def repogroup_recursive_integration_stub(request, test_repo_group, | |||
|
1739 | StubIntegrationType, stub_integration_settings): | |||
|
1740 | integration = IntegrationModel().create( | |||
|
1741 | StubIntegrationType, settings=stub_integration_settings, enabled=True, | |||
|
1742 | name='test recursive repogroup integration', | |||
|
1743 | repo=None, repo_group=test_repo_group, child_repos_only=False) | |||
1727 |
|
1744 | |||
1728 | @request.addfinalizer |
|
1745 | @request.addfinalizer | |
1729 | def cleanup(): |
|
1746 | def cleanup(): | |
@@ -1737,7 +1754,8 b' def global_integration_stub(request, Stu' | |||||
1737 | stub_integration_settings): |
|
1754 | stub_integration_settings): | |
1738 | integration = IntegrationModel().create( |
|
1755 | integration = IntegrationModel().create( | |
1739 | StubIntegrationType, settings=stub_integration_settings, enabled=True, |
|
1756 | StubIntegrationType, settings=stub_integration_settings, enabled=True, | |
1740 |
name='test global integration', |
|
1757 | name='test global integration', | |
|
1758 | repo=None, repo_group=None, child_repos_only=None) | |||
1741 |
|
1759 | |||
1742 | @request.addfinalizer |
|
1760 | @request.addfinalizer | |
1743 | def cleanup(): |
|
1761 | def cleanup(): | |
@@ -1751,7 +1769,8 b' def root_repos_integration_stub(request,' | |||||
1751 | stub_integration_settings): |
|
1769 | stub_integration_settings): | |
1752 | integration = IntegrationModel().create( |
|
1770 | integration = IntegrationModel().create( | |
1753 | StubIntegrationType, settings=stub_integration_settings, enabled=True, |
|
1771 | StubIntegrationType, settings=stub_integration_settings, enabled=True, | |
1754 |
name='test global integration', |
|
1772 | name='test global integration', | |
|
1773 | repo=None, repo_group=None, child_repos_only=True) | |||
1755 |
|
1774 | |||
1756 | @request.addfinalizer |
|
1775 | @request.addfinalizer | |
1757 | def cleanup(): |
|
1776 | def cleanup(): |
General Comments 0
You need to be logged in to leave comments.
Login now