feature: implements AI code review PR checkbox; adds AI PR settings
This commit is contained in:
parent
bf9cd8455f
commit
c71db28d3f
9 changed files with 132 additions and 48 deletions
|
|
@ -36,6 +36,7 @@ class AdminAiView(BaseAppView):
|
||||||
c.selected_ai_model_version = app_settings.get("rhodecode_ai_model_version")
|
c.selected_ai_model_version = app_settings.get("rhodecode_ai_model_version")
|
||||||
c.api_key = app_settings.get("rhodecode_ai_api_key")
|
c.api_key = app_settings.get("rhodecode_ai_api_key")
|
||||||
c.ai_features_enabled = app_settings.get("rhodecode_ai_features_enabled", False)
|
c.ai_features_enabled = app_settings.get("rhodecode_ai_features_enabled", False)
|
||||||
|
c.ai_default_code_review = app_settings.get("rhodecode_ai_default_code_review", False)
|
||||||
|
|
||||||
c.ai_instructions = app_settings.get("rhodecode_ai_code_review_instructions")
|
c.ai_instructions = app_settings.get("rhodecode_ai_code_review_instructions")
|
||||||
if not c.ai_instructions:
|
if not c.ai_instructions:
|
||||||
|
|
@ -112,6 +113,7 @@ class AdminAiView(BaseAppView):
|
||||||
try:
|
try:
|
||||||
settings = [
|
settings = [
|
||||||
("ai_features_enabled", "rhodecode_ai_features_enabled", "bool"),
|
("ai_features_enabled", "rhodecode_ai_features_enabled", "bool"),
|
||||||
|
("ai_default_code_review", "rhodecode_ai_default_code_review", "bool"),
|
||||||
("ai_model", "rhodecode_ai_model", "unicode"),
|
("ai_model", "rhodecode_ai_model", "unicode"),
|
||||||
("ai_model_version", "rhodecode_ai_model_version", "unicode"),
|
("ai_model_version", "rhodecode_ai_model_version", "unicode"),
|
||||||
("ai_api_key", "rhodecode_ai_api_key", "unicode"),
|
("ai_api_key", "rhodecode_ai_api_key", "unicode"),
|
||||||
|
|
|
||||||
|
|
@ -913,6 +913,9 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
|
||||||
self.assure_not_empty_repo()
|
self.assure_not_empty_repo()
|
||||||
source_repo = self.db_repo
|
source_repo = self.db_repo
|
||||||
|
|
||||||
|
app_settings = c.rc_config
|
||||||
|
c.ai_enabled = app_settings.get("rhodecode_ai_features_enabled", False)
|
||||||
|
|
||||||
commit_id = self.request.GET.get("commit")
|
commit_id = self.request.GET.get("commit")
|
||||||
branch_ref = self.request.GET.get("branch")
|
branch_ref = self.request.GET.get("branch")
|
||||||
bookmark_ref = self.request.GET.get("bookmark")
|
bookmark_ref = self.request.GET.get("bookmark")
|
||||||
|
|
@ -971,6 +974,9 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
|
||||||
# Get security scan setting for pre-checking the checkbox
|
# Get security scan setting for pre-checking the checkbox
|
||||||
c.pr_security_scan_enabled = self._get_repo_setting(source_repo, "rhodecode_pr_security_scan_enabled", False)
|
c.pr_security_scan_enabled = self._get_repo_setting(source_repo, "rhodecode_pr_security_scan_enabled", False)
|
||||||
|
|
||||||
|
c.ai_pr_review = self._get_repo_setting(
|
||||||
|
source_repo, "rhodecode_ai_default_code_review", app_settings.get("rhodecode_ai_default_code_review", False)
|
||||||
|
)
|
||||||
return self._get_template_context(c)
|
return self._get_template_context(c)
|
||||||
|
|
||||||
@LoginRequired()
|
@LoginRequired()
|
||||||
|
|
@ -1311,6 +1317,11 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
log.warning("EE security audit tasks not available, skipping")
|
log.warning("EE security audit tasks not available, skipping")
|
||||||
|
|
||||||
|
rc_settings = SettingsModel()
|
||||||
|
ai_enabled = rc_settings.get_setting_by_name("ai_features_enabled")
|
||||||
|
if ai_enabled and _form.get("run_ai_codereview", False):
|
||||||
|
self._try_start_ai_code_review(_, pull_request, add_existing_users=True)
|
||||||
|
|
||||||
Session().commit()
|
Session().commit()
|
||||||
|
|
||||||
h.flash(_("Successfully opened new pull request"), category="success")
|
h.flash(_("Successfully opened new pull request"), category="success")
|
||||||
|
|
@ -1373,15 +1384,6 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
|
||||||
log.warning("Code review already finished.")
|
log.warning("Code review already finished.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
admin_permissions = (
|
|
||||||
"repository.admin",
|
|
||||||
"hg.admin",
|
|
||||||
)
|
|
||||||
is_admin = h.HasRepoPermissionAny(*admin_permissions)(
|
|
||||||
user=self._rhodecode_user, repo_name=pull_request.target_repo.repo_name
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_admin:
|
|
||||||
ai_user = User.get_ai_user()
|
ai_user = User.get_ai_user()
|
||||||
log.debug("Initiating code review for pull request id: %s", pull_request.pull_request_id)
|
log.debug("Initiating code review for pull request id: %s", pull_request.pull_request_id)
|
||||||
|
|
||||||
|
|
@ -1421,14 +1423,7 @@ class RepoPullRequestsView(RepoAppView, DataGridAppView):
|
||||||
|
|
||||||
msg = _("AI code review has started. The review will be ready in about 1–3 minutes.")
|
msg = _("AI code review has started. The review will be ready in about 1–3 minutes.")
|
||||||
h.flash(msg, category="success")
|
h.flash(msg, category="success")
|
||||||
else:
|
|
||||||
log.debug("AI code review canceled, only admin can initiate AI code review.")
|
|
||||||
msg = _("AI code review is not available. This feature is in BETA and can only be initiated by an admin.")
|
|
||||||
h.flash(
|
|
||||||
msg,
|
|
||||||
category="warning",
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@LoginRequired()
|
@LoginRequired()
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,18 @@ class RepoSettingsVcsView(RepoAppView):
|
||||||
c = self.load_default_context()
|
c = self.load_default_context()
|
||||||
model = VcsSettingsModel(repo=self.db_repo_name)
|
model = VcsSettingsModel(repo=self.db_repo_name)
|
||||||
|
|
||||||
|
app_settings = c.rc_config
|
||||||
|
|
||||||
c.active = "vcs"
|
c.active = "vcs"
|
||||||
|
c.repo_vcs_settings = True
|
||||||
|
|
||||||
|
c.ai_features_enabled = app_settings.get("rhodecode_ai_features_enabled", False)
|
||||||
|
c.ai_default_code_review = self._get_repo_setting(
|
||||||
|
self.db_repo,
|
||||||
|
"rhodecode_ai_default_code_review",
|
||||||
|
app_settings.get("rhodecode_ai_default_code_review", False),
|
||||||
|
)
|
||||||
|
|
||||||
c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
|
c.global_svn_branch_patterns = model.get_global_svn_branch_patterns()
|
||||||
c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
|
c.global_svn_tag_patterns = model.get_global_svn_tag_patterns()
|
||||||
c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
|
c.svn_branch_patterns = model.get_repo_svn_branch_patterns()
|
||||||
|
|
|
||||||
|
|
@ -444,6 +444,7 @@ class _BaseVcsSettingsForm(formencode.Schema):
|
||||||
rhodecode_auto_merge_enabled = v.StringBoolean(if_missing=False)
|
rhodecode_auto_merge_enabled = v.StringBoolean(if_missing=False)
|
||||||
rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
|
rhodecode_use_outdated_comments = v.StringBoolean(if_missing=False)
|
||||||
rhodecode_pr_security_scan_enabled = v.StringBoolean(if_missing=False)
|
rhodecode_pr_security_scan_enabled = v.StringBoolean(if_missing=False)
|
||||||
|
rhodecode_ai_default_code_review = v.StringBoolean(if_missing=False)
|
||||||
|
|
||||||
# hg
|
# hg
|
||||||
extensions_largefiles = v.StringBoolean(if_missing=False)
|
extensions_largefiles = v.StringBoolean(if_missing=False)
|
||||||
|
|
@ -673,6 +674,7 @@ def PullRequestForm(localizer, repo_id):
|
||||||
description_renderer = v.UnicodeString(strip=True, required=False)
|
description_renderer = v.UnicodeString(strip=True, required=False)
|
||||||
close_branch_before_merging = v.StringBoolean(if_missing=False)
|
close_branch_before_merging = v.StringBoolean(if_missing=False)
|
||||||
run_security_audit = v.StringBoolean(if_missing=False)
|
run_security_audit = v.StringBoolean(if_missing=False)
|
||||||
|
run_ai_codereview = v.StringBoolean(if_missing=False)
|
||||||
|
|
||||||
return _PullRequestForm
|
return _PullRequestForm
|
||||||
|
|
||||||
|
|
@ -692,6 +694,7 @@ def AiSettingsForm():
|
||||||
class _AiSettingsForm(formencode.Schema):
|
class _AiSettingsForm(formencode.Schema):
|
||||||
allow_extra_fields = True
|
allow_extra_fields = True
|
||||||
rhodecode_ai_features_enabled = v.StringBoolean(if_missing=False)
|
rhodecode_ai_features_enabled = v.StringBoolean(if_missing=False)
|
||||||
|
rhodecode_ai_default_code_review = v.StringBoolean(if_missing=False)
|
||||||
rhodecode_ai_model = v.UnicodeString(strip=True, required=True)
|
rhodecode_ai_model = v.UnicodeString(strip=True, required=True)
|
||||||
rhodecode_ai_model_version = v.UnicodeString(strip=True, required=True)
|
rhodecode_ai_model_version = v.UnicodeString(strip=True, required=True)
|
||||||
rhodecode_ai_api_key = v.UnicodeString(strip=True)
|
rhodecode_ai_api_key = v.UnicodeString(strip=True)
|
||||||
|
|
|
||||||
|
|
@ -457,6 +457,7 @@ class VcsSettingsModel:
|
||||||
"pr_merge_enabled",
|
"pr_merge_enabled",
|
||||||
"auto_merge_enabled",
|
"auto_merge_enabled",
|
||||||
"pr_security_scan_enabled",
|
"pr_security_scan_enabled",
|
||||||
|
"ai_default_code_review",
|
||||||
"hg_use_rebase_for_merging",
|
"hg_use_rebase_for_merging",
|
||||||
"hg_close_branch_before_merging",
|
"hg_close_branch_before_merging",
|
||||||
"hg_merge_strategy_selector",
|
"hg_merge_strategy_selector",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
<style>
|
||||||
|
.field > .label {
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h3 class="panel-title">${_('Ai Configuration')}</h3>
|
<h3 class="panel-title">${_('Ai Configuration')}</h3>
|
||||||
|
|
@ -15,6 +21,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field" id="ai-default-review-toggle" >
|
||||||
|
<div class="label label-checkbox">
|
||||||
|
<label for="rhodecode_ai_default_code_review">${_('Turn on AI code review by default for new PRs')}:</label>
|
||||||
|
<strong>Warning</strong>: can potentially spend a lot of tokens
|
||||||
|
</div>
|
||||||
|
<div class="checkboxes">
|
||||||
|
${h.checkbox('rhodecode_ai_default_code_review',value=True, checked=c.ai_default_code_review==True)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field" id="model" style="display: flex;">
|
<div class="field" id="model" style="display: flex;">
|
||||||
<div class="label label">
|
<div class="label label">
|
||||||
<label for="model">${_('Model')}</label>
|
<label for="model">${_('Model')}</label>
|
||||||
|
|
@ -79,6 +95,7 @@ import json
|
||||||
const $model = $('#rhodecode_ai_model');
|
const $model = $('#rhodecode_ai_model');
|
||||||
const $slot = $('#model_version_slot');
|
const $slot = $('#model_version_slot');
|
||||||
const $enable = $('#rhodecode_ai_features_enabled');
|
const $enable = $('#rhodecode_ai_features_enabled');
|
||||||
|
const $codeReview = $('#rhodecode_ai_default_code_review');
|
||||||
const $form = $('#ai_features_form');
|
const $form = $('#ai_features_form');
|
||||||
const $updateModelsBtn = $('#model_version_button_update');
|
const $updateModelsBtn = $('#model_version_button_update');
|
||||||
|
|
||||||
|
|
@ -181,7 +198,8 @@ import json
|
||||||
data: {
|
data: {
|
||||||
'rhodecode_ai_model': $model.val(),
|
'rhodecode_ai_model': $model.val(),
|
||||||
'rhodecode_ai_api_key': $apiKey.val(),
|
'rhodecode_ai_api_key': $apiKey.val(),
|
||||||
'rhodecode_ai_features_enabled': $enable.is(':checked')
|
'rhodecode_ai_features_enabled': $enable.is(':checked'),
|
||||||
|
'rhodecode_ai_default_code_review': $codeReview.is(':checked')
|
||||||
},
|
},
|
||||||
success: function (response) {
|
success: function (response) {
|
||||||
$.Topic('/notifications').publish({
|
$.Topic('/notifications').publish({
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,34 @@
|
||||||
<span class="help-block">${_('When enabled, the security scan checkbox will be pre-selected when creating pull requests. This scans the PR diff for exposed secrets and credentials.')}</span>
|
<span class="help-block">${_('When enabled, the security scan checkbox will be pre-selected when creating pull requests. This scans the PR diff for exposed secrets and credentials.')}</span>
|
||||||
</div>
|
</div>
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if hasattr(c, 'repo_vcs_settings') and c.repo_vcs_settings:
|
||||||
|
|
||||||
|
%if c.rhodecode_edition_id != 'EE':
|
||||||
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" disabled>
|
||||||
|
<label>${_('Enable AI review for pull requests')}</label>
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
<span class="help-block">${_('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')|n}</span>
|
||||||
|
</div>
|
||||||
|
%else:
|
||||||
|
<div class="checkbox">
|
||||||
|
%if c.ai_features_enabled:
|
||||||
|
${h.checkbox('rhodecode_ai_default_code_review' + suffix, 'True', checked=c.ai_default_code_review, **kwargs)}
|
||||||
|
<label for="rhodecode_ai_default_code_review${suffix}">${_('Enable AI review for pull requests')}</label>
|
||||||
|
%else:
|
||||||
|
<span class="tooltip" title="${_('AI features disabled, enable AI features to activate this checkbox.')}">
|
||||||
|
${h.checkbox('rhodecode_ai_default_code_review' + suffix, 'True', checked=c.ai_default_code_review, disabled=True, **kwargs)}
|
||||||
|
<label for="rhodecode_ai_default_code_review${suffix}">${_('Enable AI review for pull requests')}</label>
|
||||||
|
</span>
|
||||||
|
%endif
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
<span class="help-block">${_('When enabled, the AI code review checkbox will be pre-selected when creating pull requests. This will schedule AI code review for the PR.')}</span>
|
||||||
|
</div>
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,31 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
|
% if c.ai_enabled and c.rhodecode_edition_id == 'EE':
|
||||||
|
<div class="pull-request-settings" style="margin-left: 220px">
|
||||||
|
${h.checkbox('run_ai_codereview', checked=c.ai_pr_review, value=True)}
|
||||||
|
<label for="run_ai_codereview">
|
||||||
|
${h.literal(_('Run run AI code review'))}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
% elif not c.ai_enabled:
|
||||||
|
<div class="pull-request-settings" style="margin-left: 220px">
|
||||||
|
${h.checkbox('run_ai_codereview', checked=False, value=True, disabled=True, **{'class': 'disabled-checkbox'})}
|
||||||
|
<label for="run_ai_codereview" class="disabled-label">
|
||||||
|
${h.literal(_('Run AI code review'))}
|
||||||
|
<span class="tooltip" title="${_('Enable AI features to use this checkbox')}">[?]</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
% elif c.rhodecode_edition_id != 'EE':
|
||||||
|
<div class="pull-request-settings" style="margin-left: 220px">
|
||||||
|
${h.checkbox('run_ai_codereview', checked=False, value=True, disabled=True, **{'class': 'disabled-checkbox'})}
|
||||||
|
<label for="run_ai_codereview" class="disabled-label">
|
||||||
|
${h.literal(_('Run AI code review'))}
|
||||||
|
<span class="ee-feature-label">[EE Only]</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ GENERAL_FORM_DATA = {
|
||||||
"rhodecode_auto_merge_enabled": True,
|
"rhodecode_auto_merge_enabled": True,
|
||||||
"rhodecode_use_outdated_comments": True,
|
"rhodecode_use_outdated_comments": True,
|
||||||
"rhodecode_pr_security_scan_enabled": True,
|
"rhodecode_pr_security_scan_enabled": True,
|
||||||
|
"rhodecode_ai_default_code_review": True,
|
||||||
"rhodecode_hg_use_rebase_for_merging": True,
|
"rhodecode_hg_use_rebase_for_merging": True,
|
||||||
"rhodecode_hg_close_branch_before_merging": True,
|
"rhodecode_hg_close_branch_before_merging": True,
|
||||||
"rhodecode_hg_merge_strategy_selector": True,
|
"rhodecode_hg_merge_strategy_selector": True,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue