Show More
@@ -0,0 +1,78 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | ||||
|
3 | import logging | |||
|
4 | from sqlalchemy import * | |||
|
5 | ||||
|
6 | from alembic.migration import MigrationContext | |||
|
7 | from alembic.operations import Operations | |||
|
8 | ||||
|
9 | from rhodecode.lib.dbmigrate.versions import _reset_base | |||
|
10 | from rhodecode.model import meta, init_model_encryption | |||
|
11 | ||||
|
12 | ||||
|
13 | log = logging.getLogger(__name__) | |||
|
14 | ||||
|
15 | ||||
|
16 | def upgrade(migrate_engine): | |||
|
17 | """ | |||
|
18 | Upgrade operations go here. | |||
|
19 | Don't create your own engine; bind migrate_engine to your metadata | |||
|
20 | """ | |||
|
21 | _reset_base(migrate_engine) | |||
|
22 | from rhodecode.lib.dbmigrate.schema import db_4_20_0_0 as db | |||
|
23 | ||||
|
24 | init_model_encryption(db) | |||
|
25 | ||||
|
26 | context = MigrationContext.configure(migrate_engine.connect()) | |||
|
27 | op = Operations(context) | |||
|
28 | ||||
|
29 | table = db.RepoReviewRule.__table__ | |||
|
30 | with op.batch_alter_table(table.name) as batch_op: | |||
|
31 | ||||
|
32 | new_column = Column('pr_author', UnicodeText().with_variant(UnicodeText(255), 'mysql'), nullable=True) | |||
|
33 | batch_op.add_column(new_column) | |||
|
34 | ||||
|
35 | new_column = Column('commit_author', UnicodeText().with_variant(UnicodeText(255), 'mysql'), nullable=True) | |||
|
36 | batch_op.add_column(new_column) | |||
|
37 | ||||
|
38 | _migrate_review_flags_to_new_cols(op, meta.Session) | |||
|
39 | ||||
|
40 | ||||
|
41 | def downgrade(migrate_engine): | |||
|
42 | meta = MetaData() | |||
|
43 | meta.bind = migrate_engine | |||
|
44 | ||||
|
45 | ||||
|
46 | def fixups(models, _SESSION): | |||
|
47 | pass | |||
|
48 | ||||
|
49 | ||||
|
50 | def _migrate_review_flags_to_new_cols(op, session): | |||
|
51 | ||||
|
52 | # set defaults for pr_author | |||
|
53 | query = text( | |||
|
54 | 'UPDATE repo_review_rules SET pr_author = :val' | |||
|
55 | ).bindparams(val='no_rule') | |||
|
56 | op.execute(query) | |||
|
57 | ||||
|
58 | # set defaults for commit_author | |||
|
59 | query = text( | |||
|
60 | 'UPDATE repo_review_rules SET commit_author = :val' | |||
|
61 | ).bindparams(val='no_rule') | |||
|
62 | op.execute(query) | |||
|
63 | ||||
|
64 | session().commit() | |||
|
65 | ||||
|
66 | # now change the flags to forbid based on | |||
|
67 | # forbid_author_to_review, forbid_commit_author_to_review | |||
|
68 | query = text( | |||
|
69 | 'UPDATE repo_review_rules SET pr_author = :val WHERE forbid_author_to_review = TRUE' | |||
|
70 | ).bindparams(val='forbid_pr_author') | |||
|
71 | op.execute(query) | |||
|
72 | ||||
|
73 | query = text( | |||
|
74 | 'UPDATE repo_review_rules SET commit_author = :val WHERE forbid_commit_author_to_review = TRUE' | |||
|
75 | ).bindparams(val='forbid_commit_author') | |||
|
76 | op.execute(query) | |||
|
77 | ||||
|
78 | session().commit() |
@@ -48,7 +48,7 b' PYRAMID_SETTINGS = {}' | |||||
48 | EXTENSIONS = {} |
|
48 | EXTENSIONS = {} | |
49 |
|
49 | |||
50 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) |
|
50 | __version__ = ('.'.join((str(each) for each in VERSION[:3]))) | |
51 |
__dbversion__ = 11 |
|
51 | __dbversion__ = 112 # defines current db version for migrations | |
52 | __platform__ = platform.system() |
|
52 | __platform__ = platform.system() | |
53 | __license__ = 'AGPLv3, and Commercial License' |
|
53 | __license__ = 'AGPLv3, and Commercial License' | |
54 | __author__ = 'RhodeCode GmbH' |
|
54 | __author__ = 'RhodeCode GmbH' |
@@ -24,7 +24,8 b' from rhodecode.model.pull_request import' | |||||
24 | from rhodecode.model.db import PullRequestReviewers |
|
24 | from rhodecode.model.db import PullRequestReviewers | |
25 | # V3 - Reviewers, with default rules data |
|
25 | # V3 - Reviewers, with default rules data | |
26 | # v4 - Added observers metadata |
|
26 | # v4 - Added observers metadata | |
27 | REVIEWER_API_VERSION = 'V4' |
|
27 | # v5 - pr_author/commit_author include/exclude logic | |
|
28 | REVIEWER_API_VERSION = 'V5' | |||
28 |
|
29 | |||
29 |
|
30 | |||
30 | def reviewer_as_json(user, reasons=None, role=None, mandatory=False, rules=None, user_group=None): |
|
31 | def reviewer_as_json(user, reasons=None, role=None, mandatory=False, rules=None, user_group=None): | |
@@ -88,6 +89,7 b' def get_default_reviewers_data(current_u' | |||||
88 | 'reviewers': json_reviewers, |
|
89 | 'reviewers': json_reviewers, | |
89 | 'rules': {}, |
|
90 | 'rules': {}, | |
90 | 'rules_data': {}, |
|
91 | 'rules_data': {}, | |
|
92 | 'rules_humanized': [], | |||
91 | } |
|
93 | } | |
92 |
|
94 | |||
93 |
|
95 |
@@ -428,16 +428,12 b' class RepoPullRequestsView(RepoAppView, ' | |||||
428 | c.allowed_to_close = c.allowed_to_merge and not pr_closed |
|
428 | c.allowed_to_close = c.allowed_to_merge and not pr_closed | |
429 |
|
429 | |||
430 | c.forbid_adding_reviewers = False |
|
430 | c.forbid_adding_reviewers = False | |
431 | c.forbid_author_to_review = False |
|
|||
432 | c.forbid_commit_author_to_review = False |
|
|||
433 |
|
431 | |||
434 | if pull_request_latest.reviewer_data and \ |
|
432 | if pull_request_latest.reviewer_data and \ | |
435 | 'rules' in pull_request_latest.reviewer_data: |
|
433 | 'rules' in pull_request_latest.reviewer_data: | |
436 | rules = pull_request_latest.reviewer_data['rules'] or {} |
|
434 | rules = pull_request_latest.reviewer_data['rules'] or {} | |
437 | try: |
|
435 | try: | |
438 | c.forbid_adding_reviewers = rules.get('forbid_adding_reviewers') |
|
436 | c.forbid_adding_reviewers = rules.get('forbid_adding_reviewers') | |
439 | c.forbid_author_to_review = rules.get('forbid_author_to_review') |
|
|||
440 | c.forbid_commit_author_to_review = rules.get('forbid_commit_author_to_review') |
|
|||
441 | except Exception: |
|
437 | except Exception: | |
442 | pass |
|
438 | pass | |
443 |
|
439 |
@@ -5058,8 +5058,14 b' class RepoReviewRule(Base, BaseModel):' | |||||
5058 | _file_pattern = Column("file_pattern", UnicodeText().with_variant(UnicodeText(255), 'mysql'), default=u'*') # glob |
|
5058 | _file_pattern = Column("file_pattern", UnicodeText().with_variant(UnicodeText(255), 'mysql'), default=u'*') # glob | |
5059 |
|
5059 | |||
5060 | use_authors_for_review = Column("use_authors_for_review", Boolean(), nullable=False, default=False) |
|
5060 | use_authors_for_review = Column("use_authors_for_review", Boolean(), nullable=False, default=False) | |
5061 | forbid_author_to_review = Column("forbid_author_to_review", Boolean(), nullable=False, default=False) |
|
5061 | ||
5062 | forbid_commit_author_to_review = Column("forbid_commit_author_to_review", Boolean(), nullable=False, default=False) |
|
5062 | # Legacy fields, just for backward compat | |
|
5063 | _forbid_author_to_review = Column("forbid_author_to_review", Boolean(), nullable=False, default=False) | |||
|
5064 | _forbid_commit_author_to_review = Column("forbid_commit_author_to_review", Boolean(), nullable=False, default=False) | |||
|
5065 | ||||
|
5066 | pr_author = Column("pr_author", UnicodeText().with_variant(UnicodeText(255), 'mysql'), nullable=True) | |||
|
5067 | commit_author = Column("commit_author", UnicodeText().with_variant(UnicodeText(255), 'mysql'), nullable=True) | |||
|
5068 | ||||
5063 | forbid_adding_reviewers = Column("forbid_adding_reviewers", Boolean(), nullable=False, default=False) |
|
5069 | forbid_adding_reviewers = Column("forbid_adding_reviewers", Boolean(), nullable=False, default=False) | |
5064 |
|
5070 | |||
5065 | rule_users = relationship('RepoReviewRuleUser') |
|
5071 | rule_users = relationship('RepoReviewRuleUser') | |
@@ -5095,6 +5101,22 b' class RepoReviewRule(Base, BaseModel):' | |||||
5095 | self._validate_pattern(value) |
|
5101 | self._validate_pattern(value) | |
5096 | self._file_pattern = value or '*' |
|
5102 | self._file_pattern = value or '*' | |
5097 |
|
5103 | |||
|
5104 | @hybrid_property | |||
|
5105 | def forbid_pr_author_to_review(self): | |||
|
5106 | return self.pr_author == 'forbid_pr_author' | |||
|
5107 | ||||
|
5108 | @hybrid_property | |||
|
5109 | def include_pr_author_to_review(self): | |||
|
5110 | return self.pr_author == 'include_pr_author' | |||
|
5111 | ||||
|
5112 | @hybrid_property | |||
|
5113 | def forbid_commit_author_to_review(self): | |||
|
5114 | return self.commit_author == 'forbid_commit_author' | |||
|
5115 | ||||
|
5116 | @hybrid_property | |||
|
5117 | def include_commit_author_to_review(self): | |||
|
5118 | return self.commit_author == 'include_commit_author' | |||
|
5119 | ||||
5098 | def matches(self, source_branch, target_branch, files_changed): |
|
5120 | def matches(self, source_branch, target_branch, files_changed): | |
5099 | """ |
|
5121 | """ | |
5100 | Check if this review rule matches a branch/files in a pull request |
|
5122 | Check if this review rule matches a branch/files in a pull request |
@@ -182,83 +182,34 b' window.ReviewersController = function ()' | |||||
182 | if (!data || data.rules === undefined || $.isEmptyObject(data.rules)) { |
|
182 | if (!data || data.rules === undefined || $.isEmptyObject(data.rules)) { | |
183 | // default rule, case for older repo that don't have any rules stored |
|
183 | // default rule, case for older repo that don't have any rules stored | |
184 | self.$rulesList.append( |
|
184 | self.$rulesList.append( | |
185 | self.addRule( |
|
185 | self.addRule(_gettext('All reviewers must vote.')) | |
186 | _gettext('All reviewers must vote.')) |
|
|||
187 | ); |
|
186 | ); | |
188 | return self.forbidUsers |
|
187 | return self.forbidUsers | |
189 | } |
|
188 | } | |
190 |
|
189 | |||
191 |
if (data.rules. |
|
190 | if (data.rules.forbid_adding_reviewers) { | |
192 | if (data.rules.voting < 0) { |
|
191 | $('#add_reviewer_input').remove(); | |
193 | self.$rulesList.append( |
|
|||
194 | self.addRule( |
|
|||
195 | _gettext('All individual reviewers must vote.')) |
|
|||
196 | ) |
|
|||
197 | } else if (data.rules.voting === 1) { |
|
|||
198 | self.$rulesList.append( |
|
|||
199 | self.addRule( |
|
|||
200 | _gettext('At least {0} reviewer must vote.').format(data.rules.voting)) |
|
|||
201 | ) |
|
|||
202 |
|
||||
203 | } else { |
|
|||
204 | self.$rulesList.append( |
|
|||
205 | self.addRule( |
|
|||
206 | _gettext('At least {0} reviewers must vote.').format(data.rules.voting)) |
|
|||
207 | ) |
|
|||
208 | } |
|
|||
209 | } |
|
192 | } | |
210 |
|
193 | |||
211 |
if (data.rules. |
|
194 | if (data.rules_data !== undefined && data.rules_data.forbidden_users !== undefined) { | |
212 |
$.each(data.rules. |
|
195 | $.each(data.rules_data.forbidden_users, function(idx, val){ | |
213 | self.$rulesList.append( |
|
196 | self.forbidUsers.push(val) | |
214 | self.addRule(rule_data.text) |
|
197 | }) | |
215 | ) |
|
|||
216 | }); |
|
|||
217 | } |
|
|||
218 |
|
||||
219 | if (data.rules.use_code_authors_for_review) { |
|
|||
220 | self.$rulesList.append( |
|
|||
221 | self.addRule( |
|
|||
222 | _gettext('Reviewers picked from source code changes.')) |
|
|||
223 | ) |
|
|||
224 | } |
|
198 | } | |
225 |
|
199 | |||
226 | if (data.rules.forbid_adding_reviewers) { |
|
200 | if (data.rules_humanized !== undefined && data.rules_humanized.length > 0) { | |
227 | $('#add_reviewer_input').remove(); |
|
201 | $.each(data.rules_humanized, function(idx, val) { | |
|
202 | self.$rulesList.append( | |||
|
203 | self.addRule(val) | |||
|
204 | ) | |||
|
205 | }) | |||
|
206 | } else { | |||
|
207 | // we don't have any rules set, so we inform users about it | |||
228 | self.$rulesList.append( |
|
208 | self.$rulesList.append( | |
229 | self.addRule( |
|
209 | self.addRule(_gettext('No additional review rules set.')) | |
230 | _gettext('Adding new reviewers is forbidden.')) |
|
|||
231 | ) |
|
|||
232 | } |
|
|||
233 |
|
||||
234 | if (data.rules.forbid_author_to_review) { |
|
|||
235 | self.forbidUsers.push(data.rules_data.pr_author); |
|
|||
236 | self.$rulesList.append( |
|
|||
237 | self.addRule( |
|
|||
238 | _gettext('Author is not allowed to be a reviewer.')) |
|
|||
239 | ) |
|
210 | ) | |
240 | } |
|
211 | } | |
241 |
|
212 | |||
242 | if (data.rules.forbid_commit_author_to_review) { |
|
|||
243 |
|
||||
244 | if (data.rules_data.forbidden_users) { |
|
|||
245 | $.each(data.rules_data.forbidden_users, function (index, member_data) { |
|
|||
246 | self.forbidUsers.push(member_data) |
|
|||
247 | }); |
|
|||
248 | } |
|
|||
249 |
|
||||
250 | self.$rulesList.append( |
|
|||
251 | self.addRule( |
|
|||
252 | _gettext('Commit Authors are not allowed to be a reviewer.')) |
|
|||
253 | ) |
|
|||
254 | } |
|
|||
255 |
|
||||
256 | // we don't have any rules set, so we inform users about it |
|
|||
257 | if (self.enabledRules.length === 0) { |
|
|||
258 | self.addRule( |
|
|||
259 | _gettext('No review rules set.')) |
|
|||
260 | } |
|
|||
261 |
|
||||
262 | return self.forbidUsers |
|
213 | return self.forbidUsers | |
263 | }; |
|
214 | }; | |
264 |
|
215 |
General Comments 0
You need to be logged in to leave comments.
Login now