Merge branch 'master' into ph-inline-js
This commit is contained in:
commit
76704c7960
243 changed files with 4290 additions and 1251 deletions
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
7.5
|
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -2,6 +2,18 @@
|
||||||
documentation](doc/development/changelog.md) for instructions on adding your own
|
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||||
entry.
|
entry.
|
||||||
|
|
||||||
|
## 9.4.1 (2017-07-25)
|
||||||
|
|
||||||
|
- Fix pipeline_schedules pages throwing error 500 (when ref is empty). !12983
|
||||||
|
- Fix editing project with container images present. !13028
|
||||||
|
- Fix some invalid entries in PO files. !13032
|
||||||
|
- Fix cross site request protection when logging in as a regular user when LDAP is enabled. !13049
|
||||||
|
- Fix bug causing metrics files to be truncated. !35420
|
||||||
|
- Fix anonymous access to public projects in groups with pending invites.
|
||||||
|
- Fixed issue boards sidebar close icon size.
|
||||||
|
- Fixed duplicate new milestone buttons when new navigation is turned on.
|
||||||
|
- Fix margins in the mini graph for pipeline in commits box.
|
||||||
|
|
||||||
## 9.4.0 (2017-07-22)
|
## 9.4.0 (2017-07-22)
|
||||||
|
|
||||||
- Add blame view age mapping. !7198 (Jeff Stubler)
|
- Add blame view age mapping. !7198 (Jeff Stubler)
|
||||||
|
|
|
@ -114,8 +114,8 @@ scheduling into milestones. Labelling is a task for everyone.
|
||||||
Most issues will have labels for at least one of the following:
|
Most issues will have labels for at least one of the following:
|
||||||
|
|
||||||
- Type: ~"feature proposal", ~bug, ~customer, etc.
|
- Type: ~"feature proposal", ~bug, ~customer, etc.
|
||||||
- Subject: ~wiki, ~"container registry", ~ldap, ~api, etc.
|
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
|
||||||
- Team: ~CI, ~Discussion, ~Edge, ~Frontend, ~Platform, etc.
|
- Team: ~CI, ~Discussion, ~Edge, ~Platform, etc.
|
||||||
- Priority: ~Deliverable, ~Stretch
|
- Priority: ~Deliverable, ~Stretch
|
||||||
|
|
||||||
All labels, their meaning and priority are defined on the
|
All labels, their meaning and priority are defined on the
|
||||||
|
@ -278,7 +278,7 @@ For feature proposals for EE, open an issue on the
|
||||||
In order to help track the feature proposals, we have created a
|
In order to help track the feature proposals, we have created a
|
||||||
[`feature proposal`][fpl] label. For the time being, users that are not members
|
[`feature proposal`][fpl] label. For the time being, users that are not members
|
||||||
of the project cannot add labels. You can instead ask one of the [core team]
|
of the project cannot add labels. You can instead ask one of the [core team]
|
||||||
members to add the label `feature proposal` to the issue or add the following
|
members to add the label ~"feature proposal" to the issue or add the following
|
||||||
code snippet right after your description in a new line: `~"feature proposal"`.
|
code snippet right after your description in a new line: `~"feature proposal"`.
|
||||||
|
|
||||||
Please keep feature proposals as small and simple as possible, complex ones
|
Please keep feature proposals as small and simple as possible, complex ones
|
||||||
|
|
6
Gemfile
6
Gemfile
|
@ -16,6 +16,7 @@ gem 'mysql2', '~> 0.4.5', group: :mysql
|
||||||
gem 'pg', '~> 0.18.2', group: :postgres
|
gem 'pg', '~> 0.18.2', group: :postgres
|
||||||
|
|
||||||
gem 'rugged', '~> 0.25.1.1'
|
gem 'rugged', '~> 0.25.1.1'
|
||||||
|
gem 'grape-route-helpers', '~> 2.0.0'
|
||||||
|
|
||||||
gem 'faraday', '~> 0.12'
|
gem 'faraday', '~> 0.12'
|
||||||
|
|
||||||
|
@ -60,7 +61,8 @@ gem 'browser', '~> 2.2'
|
||||||
# LDAP Auth
|
# LDAP Auth
|
||||||
# GitLab fork with several improvements to original library. For full list of changes
|
# GitLab fork with several improvements to original library. For full list of changes
|
||||||
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
||||||
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap'
|
gem 'gitlab_omniauth-ldap', '~> 2.0.3', require: 'omniauth-ldap'
|
||||||
|
gem 'net-ldap'
|
||||||
|
|
||||||
# Git Wiki
|
# Git Wiki
|
||||||
# Required manually in config/initializers/gollum.rb to control load order
|
# Required manually in config/initializers/gollum.rb to control load order
|
||||||
|
@ -164,7 +166,7 @@ gem 'rainbow', '~> 2.2'
|
||||||
gem 'settingslogic', '~> 2.0.9'
|
gem 'settingslogic', '~> 2.0.9'
|
||||||
|
|
||||||
# Linear-time regex library for untrusted regular expressions
|
# Linear-time regex library for untrusted regular expressions
|
||||||
gem 're2', '~> 1.1.0'
|
gem 're2', '~> 1.1.1'
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
|
|
||||||
|
|
26
Gemfile.lock
26
Gemfile.lock
|
@ -288,11 +288,11 @@ GEM
|
||||||
mime-types (>= 1.16, < 3)
|
mime-types (>= 1.16, < 3)
|
||||||
posix-spawn (~> 0.3)
|
posix-spawn (~> 0.3)
|
||||||
gitlab-markup (1.5.1)
|
gitlab-markup (1.5.1)
|
||||||
gitlab_omniauth-ldap (1.2.1)
|
gitlab_omniauth-ldap (2.0.3)
|
||||||
net-ldap (~> 0.9)
|
net-ldap (~> 0.16)
|
||||||
omniauth (~> 1.0)
|
omniauth (~> 1.3)
|
||||||
pyu-ruby-sasl (~> 0.0.3.1)
|
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
|
||||||
rubyntlm (~> 0.3)
|
rubyntlm (~> 0.5)
|
||||||
globalid (0.3.7)
|
globalid (0.3.7)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
gollum-grit_adapter (1.0.1)
|
gollum-grit_adapter (1.0.1)
|
||||||
|
@ -345,6 +345,10 @@ GEM
|
||||||
grape-entity (0.6.0)
|
grape-entity (0.6.0)
|
||||||
activesupport
|
activesupport
|
||||||
multi_json (>= 1.3.2)
|
multi_json (>= 1.3.2)
|
||||||
|
grape-route-helpers (2.0.0)
|
||||||
|
activesupport
|
||||||
|
grape (~> 0.16, >= 0.16.0)
|
||||||
|
rake
|
||||||
grpc (1.4.0)
|
grpc (1.4.0)
|
||||||
google-protobuf (~> 3.1)
|
google-protobuf (~> 3.1)
|
||||||
googleauth (~> 0.5.1)
|
googleauth (~> 0.5.1)
|
||||||
|
@ -467,7 +471,7 @@ GEM
|
||||||
mustermann-grape (1.0.0)
|
mustermann-grape (1.0.0)
|
||||||
mustermann (~> 1.0.0)
|
mustermann (~> 1.0.0)
|
||||||
mysql2 (0.4.5)
|
mysql2 (0.4.5)
|
||||||
net-ldap (0.12.1)
|
net-ldap (0.16.0)
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
nokogiri (1.6.8.1)
|
nokogiri (1.6.8.1)
|
||||||
mini_portile2 (~> 2.1.0)
|
mini_portile2 (~> 2.1.0)
|
||||||
|
@ -656,7 +660,7 @@ GEM
|
||||||
debugger-ruby_core_source (~> 1.3)
|
debugger-ruby_core_source (~> 1.3)
|
||||||
rdoc (4.2.2)
|
rdoc (4.2.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
re2 (1.1.0)
|
re2 (1.1.1)
|
||||||
recaptcha (3.0.0)
|
recaptcha (3.0.0)
|
||||||
json
|
json
|
||||||
recursive-open-struct (1.0.0)
|
recursive-open-struct (1.0.0)
|
||||||
|
@ -740,7 +744,7 @@ GEM
|
||||||
nokogiri (>= 1.5.10)
|
nokogiri (>= 1.5.10)
|
||||||
ruby_parser (3.9.0)
|
ruby_parser (3.9.0)
|
||||||
sexp_processor (~> 4.1)
|
sexp_processor (~> 4.1)
|
||||||
rubyntlm (0.5.2)
|
rubyntlm (0.6.2)
|
||||||
rubypants (0.2.0)
|
rubypants (0.2.0)
|
||||||
rubyzip (1.2.1)
|
rubyzip (1.2.1)
|
||||||
rufus-scheduler (3.4.0)
|
rufus-scheduler (3.4.0)
|
||||||
|
@ -974,13 +978,14 @@ DEPENDENCIES
|
||||||
github-linguist (~> 4.7.0)
|
github-linguist (~> 4.7.0)
|
||||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||||
gitlab-markup (~> 1.5.1)
|
gitlab-markup (~> 1.5.1)
|
||||||
gitlab_omniauth-ldap (~> 1.2.1)
|
gitlab_omniauth-ldap (~> 2.0.3)
|
||||||
gollum-lib (~> 4.2)
|
gollum-lib (~> 4.2)
|
||||||
gollum-rugged_adapter (~> 0.4.4)
|
gollum-rugged_adapter (~> 0.4.4)
|
||||||
gon (~> 6.1.0)
|
gon (~> 6.1.0)
|
||||||
google-api-client (~> 0.8.6)
|
google-api-client (~> 0.8.6)
|
||||||
grape (~> 0.19.2)
|
grape (~> 0.19.2)
|
||||||
grape-entity (~> 0.6.0)
|
grape-entity (~> 0.6.0)
|
||||||
|
grape-route-helpers (~> 2.0.0)
|
||||||
haml_lint (~> 0.21.0)
|
haml_lint (~> 0.21.0)
|
||||||
hamlit (~> 2.6.1)
|
hamlit (~> 2.6.1)
|
||||||
hashie-forbidden_attributes
|
hashie-forbidden_attributes
|
||||||
|
@ -1008,6 +1013,7 @@ DEPENDENCIES
|
||||||
minitest (~> 5.7.0)
|
minitest (~> 5.7.0)
|
||||||
mousetrap-rails (~> 1.4.6)
|
mousetrap-rails (~> 1.4.6)
|
||||||
mysql2 (~> 0.4.5)
|
mysql2 (~> 0.4.5)
|
||||||
|
net-ldap
|
||||||
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
||||||
oauth2 (~> 1.4)
|
oauth2 (~> 1.4)
|
||||||
octokit (~> 4.6.2)
|
octokit (~> 4.6.2)
|
||||||
|
@ -1055,7 +1061,7 @@ DEPENDENCIES
|
||||||
raindrops (~> 0.18)
|
raindrops (~> 0.18)
|
||||||
rblineprof (~> 0.3.6)
|
rblineprof (~> 0.3.6)
|
||||||
rdoc (~> 4.2)
|
rdoc (~> 4.2)
|
||||||
re2 (~> 1.1.0)
|
re2 (~> 1.1.1)
|
||||||
recaptcha (~> 3.0)
|
recaptcha (~> 3.0)
|
||||||
redcarpet (~> 3.4)
|
redcarpet (~> 3.4)
|
||||||
redis (~> 3.2)
|
redis (~> 3.2)
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
/* global NamespaceSelects */
|
/* global NamespaceSelects */
|
||||||
/* global Project */
|
/* global Project */
|
||||||
/* global ProjectAvatar */
|
/* global ProjectAvatar */
|
||||||
|
/* global MergeRequest */
|
||||||
|
/* global Compare */
|
||||||
/* global CompareAutocomplete */
|
/* global CompareAutocomplete */
|
||||||
/* global ProjectNew */
|
/* global ProjectNew */
|
||||||
/* global ProjectShow */
|
/* global ProjectShow */
|
||||||
|
@ -228,6 +230,19 @@ import initIssuableSidebar from './init_issuable_sidebar';
|
||||||
new gl.IssuableTemplateSelectors();
|
new gl.IssuableTemplateSelectors();
|
||||||
break;
|
break;
|
||||||
case 'projects:merge_requests:creations:new':
|
case 'projects:merge_requests:creations:new':
|
||||||
|
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
|
||||||
|
if (mrNewCompareNode) {
|
||||||
|
new Compare({
|
||||||
|
targetProjectUrl: mrNewCompareNode.dataset.targetProjectUrl,
|
||||||
|
sourceBranchUrl: mrNewCompareNode.dataset.sourceBranchUrl,
|
||||||
|
targetBranchUrl: mrNewCompareNode.dataset.targetBranchUrl,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
|
||||||
|
new MergeRequest({
|
||||||
|
action: mrNewSubmitNode.dataset.mrSubmitAction,
|
||||||
|
});
|
||||||
|
}
|
||||||
case 'projects:merge_requests:creations:diffs':
|
case 'projects:merge_requests:creations:diffs':
|
||||||
case 'projects:merge_requests:edit':
|
case 'projects:merge_requests:edit':
|
||||||
new gl.Diff();
|
new gl.Diff();
|
||||||
|
@ -267,8 +282,14 @@ import initIssuableSidebar from './init_issuable_sidebar';
|
||||||
new gl.Diff();
|
new gl.Diff();
|
||||||
shortcut_handler = new ShortcutsIssuable(true);
|
shortcut_handler = new ShortcutsIssuable(true);
|
||||||
new ZenMode();
|
new ZenMode();
|
||||||
|
|
||||||
initIssuableSidebar();
|
initIssuableSidebar();
|
||||||
initNotes();
|
initNotes();
|
||||||
|
|
||||||
|
const mrShowNode = document.querySelector('.merge-request');
|
||||||
|
window.mergeRequest = new MergeRequest({
|
||||||
|
action: mrShowNode.dataset.mrAction,
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
case 'dashboard:activity':
|
case 'dashboard:activity':
|
||||||
new gl.Activities();
|
new gl.Activities();
|
||||||
|
|
|
@ -3,10 +3,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
modal: true,
|
modal: true,
|
||||||
show: false,
|
show: false,
|
||||||
});
|
});
|
||||||
$('.how_to_merge_link').bind('click', () => {
|
$('.how_to_merge_link').on('click', () => {
|
||||||
modal.show();
|
modal.show();
|
||||||
});
|
});
|
||||||
$('.modal-header .close').bind('click', () => {
|
$('.modal-header .close').on('click', () => {
|
||||||
modal.hide();
|
modal.hide();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -175,7 +175,7 @@ import Cookies from 'js-cookie';
|
||||||
|
|
||||||
getConflictsCountText() {
|
getConflictsCountText() {
|
||||||
const count = this.getConflictsCount();
|
const count = this.getConflictsCount();
|
||||||
const text = count ? 'conflicts' : 'conflict';
|
const text = count > 1 ? 'conflicts' : 'conflict';
|
||||||
|
|
||||||
return `${count} ${text}`;
|
return `${count} ${text}`;
|
||||||
},
|
},
|
||||||
|
|
|
@ -108,7 +108,8 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
<mr-widget-memory-usage
|
<mr-widget-memory-usage
|
||||||
v-if="deployment.metrics_url"
|
v-if="deployment.metrics_url"
|
||||||
:metricsUrl="deployment.metrics_url"
|
:metrics-url="deployment.metrics_url"
|
||||||
|
:metrics-monitoring-url="deployment.metrics_monitoring_url"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,14 @@ import MRWidgetService from '../services/mr_widget_service';
|
||||||
export default {
|
export default {
|
||||||
name: 'MemoryUsage',
|
name: 'MemoryUsage',
|
||||||
props: {
|
props: {
|
||||||
metricsUrl: { type: String, required: true },
|
metricsUrl: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
metricsMonitoringUrl: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -124,7 +131,7 @@ export default {
|
||||||
<p
|
<p
|
||||||
v-if="shouldShowMemoryGraph"
|
v-if="shouldShowMemoryGraph"
|
||||||
class="usage-info js-usage-info">
|
class="usage-info js-usage-info">
|
||||||
Memory usage <b>{{memoryChangeType}}</b> from {{memoryFrom}}MB to {{memoryTo}}MB
|
<a :href="metricsMonitoringUrl">Memory</a> usage <b>{{memoryChangeType}}</b> from {{memoryFrom}}MB to {{memoryTo}}MB
|
||||||
</p>
|
</p>
|
||||||
<p
|
<p
|
||||||
v-if="shouldShowLoadFailure"
|
v-if="shouldShowLoadFailure"
|
||||||
|
|
|
@ -21,6 +21,11 @@ header.navbar-gitlab-new {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 28px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -211,6 +211,10 @@
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.affix-top .issuable-sidebar {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
&.right-sidebar-expanded {
|
&.right-sidebar-expanded {
|
||||||
width: $gutter_width;
|
width: $gutter_width;
|
||||||
|
|
||||||
|
|
|
@ -597,7 +597,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dropdown button in mini pipeline graph
|
// Dropdown button in mini pipeline graph
|
||||||
.mini-pipeline-graph-dropdown-toggle {
|
button.mini-pipeline-graph-dropdown-toggle {
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
background-color: $white-light;
|
background-color: $white-light;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
|
@ -608,6 +608,7 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: all 0.2s linear;
|
transition: all 0.2s linear;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
> .fa.fa-caret-down {
|
> .fa.fa-caret-down {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -76,11 +76,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
||||||
params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
|
params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
|
||||||
|
|
||||||
params.require(:application_setting).permit(
|
params.require(:application_setting).permit(
|
||||||
application_setting_params_ce
|
application_setting_params_attributes
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def application_setting_params_ce
|
def application_setting_params_attributes
|
||||||
[
|
[
|
||||||
:admin_notification_email,
|
:admin_notification_email,
|
||||||
:after_sign_out_path,
|
:after_sign_out_path,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Admin::DashboardController < Admin::ApplicationController
|
class Admin::DashboardController < Admin::ApplicationController
|
||||||
def index
|
def index
|
||||||
@projects = Project.with_route.limit(10)
|
@projects = Project.without_deleted.with_route.limit(10)
|
||||||
@users = User.limit(10)
|
@users = User.limit(10)
|
||||||
@groups = Group.with_route.limit(10)
|
@groups = Group.with_route.limit(10)
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,6 +22,7 @@ class Projects::ApplicationController < ApplicationController
|
||||||
|
|
||||||
def project
|
def project
|
||||||
return @project if @project
|
return @project if @project
|
||||||
|
return nil unless params[:project_id] || params[:id]
|
||||||
|
|
||||||
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
|
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
|
||||||
auth_proc = ->(project) { !project.pending_delete? }
|
auth_proc = ->(project) { !project.pending_delete? }
|
||||||
|
|
|
@ -224,11 +224,17 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
||||||
metrics_project_environment_deployment_path(environment.project, environment, deployment)
|
metrics_project_environment_deployment_path(environment.project, environment, deployment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
metrics_monitoring_url =
|
||||||
|
if can?(current_user, :read_environment, environment)
|
||||||
|
environment_metrics_path(environment)
|
||||||
|
end
|
||||||
|
|
||||||
{
|
{
|
||||||
id: environment.id,
|
id: environment.id,
|
||||||
name: environment.name,
|
name: environment.name,
|
||||||
url: project_environment_path(project, environment),
|
url: project_environment_path(project, environment),
|
||||||
metrics_url: metrics_url,
|
metrics_url: metrics_url,
|
||||||
|
metrics_monitoring_url: metrics_monitoring_url,
|
||||||
stop_url: stop_url,
|
stop_url: stop_url,
|
||||||
external_url: environment.external_url,
|
external_url: environment.external_url,
|
||||||
external_url_formatted: environment.formatted_external_url,
|
external_url_formatted: environment.formatted_external_url,
|
||||||
|
|
|
@ -296,10 +296,10 @@ class ProjectsController < Projects::ApplicationController
|
||||||
|
|
||||||
def project_params
|
def project_params
|
||||||
params.require(:project)
|
params.require(:project)
|
||||||
.permit(project_params_ce)
|
.permit(project_params_attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
def project_params_ce
|
def project_params_attributes
|
||||||
[
|
[
|
||||||
:avatar,
|
:avatar,
|
||||||
:build_allow_git_fetch,
|
:build_allow_git_fetch,
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
# group_id: integer
|
# group_id: integer
|
||||||
# project_id: integer
|
# project_id: integer
|
||||||
# milestone_title: string
|
# milestone_title: string
|
||||||
|
# author_id: integer
|
||||||
# assignee_id: integer
|
# assignee_id: integer
|
||||||
# search: string
|
# search: string
|
||||||
# label_name: string
|
# label_name: string
|
||||||
|
|
|
@ -18,7 +18,8 @@ module SystemNoteHelper
|
||||||
'milestone' => 'icon_clock_o',
|
'milestone' => 'icon_clock_o',
|
||||||
'discussion' => 'icon_comment_o',
|
'discussion' => 'icon_comment_o',
|
||||||
'moved' => 'icon_arrow_circle_o_right',
|
'moved' => 'icon_arrow_circle_o_right',
|
||||||
'outdated' => 'icon_edit'
|
'outdated' => 'icon_edit',
|
||||||
|
'duplicate' => 'icon_clone'
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def icon_for_system_note(note)
|
def icon_for_system_note(note)
|
||||||
|
|
|
@ -21,7 +21,7 @@ module Ci
|
||||||
has_many :merge_requests, foreign_key: "head_pipeline_id"
|
has_many :merge_requests, foreign_key: "head_pipeline_id"
|
||||||
|
|
||||||
has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
||||||
has_many :retryable_builds, -> { latest.failed_or_canceled }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
has_many :retryable_builds, -> { latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
||||||
has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus'
|
has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus'
|
||||||
has_many :manual_actions, -> { latest.manual_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
has_many :manual_actions, -> { latest.manual_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
||||||
has_many :artifacts, -> { latest.with_artifacts_not_expired.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
has_many :artifacts, -> { latest.with_artifacts_not_expired.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
|
||||||
|
|
|
@ -40,10 +40,6 @@ module Ci
|
||||||
update_attribute(:active, false)
|
update_attribute(:active, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def runnable_by_owner?
|
|
||||||
Ability.allowed?(owner, :create_pipeline, project)
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_next_run_at
|
def set_next_run_at
|
||||||
self.next_run_at = Gitlab::Ci::CronParser.new(cron, cron_timezone).next_time_from(Time.now)
|
self.next_run_at = Gitlab::Ci::CronParser.new(cron, cron_timezone).next_time_from(Time.now)
|
||||||
end
|
end
|
||||||
|
|
|
@ -17,7 +17,13 @@ module ProtectedRef
|
||||||
class_methods do
|
class_methods do
|
||||||
def protected_ref_access_levels(*types)
|
def protected_ref_access_levels(*types)
|
||||||
types.each do |type|
|
types.each do |type|
|
||||||
has_many :"#{type}_access_levels", dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
|
# We need to set `inverse_of` to make sure the `belongs_to`-object is set
|
||||||
|
# when creating children using `accepts_nested_attributes_for`.
|
||||||
|
#
|
||||||
|
# If we don't `protected_branch` or `protected_tag` would be empty and
|
||||||
|
# `project` cannot be delegated to it, which in turn would cause validations
|
||||||
|
# to fail.
|
||||||
|
has_many :"#{type}_access_levels", dependent: :destroy, inverse_of: self.model_name.singular # rubocop:disable Cop/ActiveRecordDependent
|
||||||
|
|
||||||
validates :"#{type}_access_levels", length: { is: 1, message: "are restricted to a single instance per #{self.model_name.human}." }
|
validates :"#{type}_access_levels", length: { is: 1, message: "are restricted to a single instance per #{self.model_name.human}." }
|
||||||
|
|
||||||
|
@ -25,8 +31,8 @@ module ProtectedRef
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def protected_ref_accessible_to?(ref, user, action:)
|
def protected_ref_accessible_to?(ref, user, action:, protected_refs: nil)
|
||||||
access_levels_for_ref(ref, action: action).any? do |access_level|
|
access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
|
||||||
access_level.check_access(user)
|
access_level.check_access(user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -37,8 +43,9 @@ module ProtectedRef
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def access_levels_for_ref(ref, action:)
|
def access_levels_for_ref(ref, action:, protected_refs: nil)
|
||||||
self.matching(ref).map(&:"#{action}_access_levels").flatten
|
self.matching(ref, protected_refs: protected_refs)
|
||||||
|
.map(&:"#{action}_access_levels").flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
def matching(ref_name, protected_refs: nil)
|
def matching(ref_name, protected_refs: nil)
|
||||||
|
|
|
@ -236,10 +236,21 @@ class MergeRequestDiff < ActiveRecord::Base
|
||||||
|
|
||||||
def create_merge_request_diff_files(diffs)
|
def create_merge_request_diff_files(diffs)
|
||||||
rows = diffs.map.with_index do |diff, index|
|
rows = diffs.map.with_index do |diff, index|
|
||||||
diff.to_hash.merge(
|
diff_hash = diff.to_hash.merge(
|
||||||
|
binary: false,
|
||||||
merge_request_diff_id: self.id,
|
merge_request_diff_id: self.id,
|
||||||
relative_order: index
|
relative_order: index
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Compatibility with old diffs created with Psych.
|
||||||
|
diff_hash.tap do |hash|
|
||||||
|
diff_text = hash[:diff]
|
||||||
|
|
||||||
|
if diff_text.encoding == Encoding::BINARY && !diff_text.ascii_only?
|
||||||
|
hash[:binary] = true
|
||||||
|
hash[:diff] = [diff_text].pack('m0')
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
|
Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
|
||||||
|
@ -268,9 +279,7 @@ class MergeRequestDiff < ActiveRecord::Base
|
||||||
st_diffs
|
st_diffs
|
||||||
end
|
end
|
||||||
elsif merge_request_diff_files.present?
|
elsif merge_request_diff_files.present?
|
||||||
merge_request_diff_files
|
merge_request_diff_files.map(&:to_hash)
|
||||||
.as_json(only: Gitlab::Git::Diff::SERIALIZE_KEYS)
|
|
||||||
.map(&:with_indifferent_access)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,4 +8,14 @@ class MergeRequestDiffFile < ActiveRecord::Base
|
||||||
|
|
||||||
encode_utf8(diff) if diff.respond_to?(:encoding)
|
encode_utf8(diff) if diff.respond_to?(:encoding)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def diff
|
||||||
|
binary? ? super.unpack('m0').first : super
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_hash
|
||||||
|
keys = Gitlab::Git::Diff::SERIALIZE_KEYS - [:diff]
|
||||||
|
|
||||||
|
as_json(only: keys).merge(diff: diff).with_indifferent_access
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,10 +3,8 @@ class JiraService < IssueTrackerService
|
||||||
|
|
||||||
validates :url, url: true, presence: true, if: :activated?
|
validates :url, url: true, presence: true, if: :activated?
|
||||||
validates :api_url, url: true, allow_blank: true
|
validates :api_url, url: true, allow_blank: true
|
||||||
validates :project_key, presence: true, if: :activated?
|
|
||||||
|
|
||||||
prop_accessor :username, :password, :url, :api_url, :project_key,
|
prop_accessor :username, :password, :url, :api_url, :jira_issue_transition_id, :title, :description
|
||||||
:jira_issue_transition_id, :title, :description
|
|
||||||
|
|
||||||
before_update :reset_password
|
before_update :reset_password
|
||||||
|
|
||||||
|
@ -54,10 +52,6 @@ class JiraService < IssueTrackerService
|
||||||
@client ||= JIRA::Client.new(options)
|
@client ||= JIRA::Client.new(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def jira_project
|
|
||||||
@jira_project ||= jira_request { client.Project.find(project_key) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def help
|
def help
|
||||||
"You need to configure JIRA before enabling this service. For more details
|
"You need to configure JIRA before enabling this service. For more details
|
||||||
read the
|
read the
|
||||||
|
@ -88,18 +82,12 @@ class JiraService < IssueTrackerService
|
||||||
[
|
[
|
||||||
{ type: 'text', name: 'url', title: 'Web URL', placeholder: 'https://jira.example.com', required: true },
|
{ type: 'text', name: 'url', title: 'Web URL', placeholder: 'https://jira.example.com', required: true },
|
||||||
{ type: 'text', name: 'api_url', title: 'JIRA API URL', placeholder: 'If different from Web URL' },
|
{ type: 'text', name: 'api_url', title: 'JIRA API URL', placeholder: 'If different from Web URL' },
|
||||||
{ type: 'text', name: 'project_key', placeholder: 'Project Key', required: true },
|
|
||||||
{ type: 'text', name: 'username', placeholder: '', required: true },
|
{ type: 'text', name: 'username', placeholder: '', required: true },
|
||||||
{ type: 'password', name: 'password', placeholder: '', required: true },
|
{ type: 'password', name: 'password', placeholder: '', required: true },
|
||||||
{ type: 'text', name: 'jira_issue_transition_id', placeholder: '' }
|
{ type: 'text', name: 'jira_issue_transition_id', title: 'Transition ID', placeholder: '' }
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
# URLs to redirect from Gitlab issues pages to jira issue tracker
|
|
||||||
def project_url
|
|
||||||
"#{url}/issues/?jql=project=#{project_key}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def issues_url
|
def issues_url
|
||||||
"#{url}/browse/:id"
|
"#{url}/browse/:id"
|
||||||
end
|
end
|
||||||
|
@ -184,7 +172,7 @@ class JiraService < IssueTrackerService
|
||||||
def test_settings
|
def test_settings
|
||||||
return unless client_url.present?
|
return unless client_url.present?
|
||||||
# Test settings by getting the project
|
# Test settings by getting the project
|
||||||
jira_request { jira_project.present? }
|
jira_request { client.ServerInfo.all.attrs }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -471,9 +471,18 @@ class Repository
|
||||||
end
|
end
|
||||||
cache_method :root_ref
|
cache_method :root_ref
|
||||||
|
|
||||||
|
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/314
|
||||||
def exists?
|
def exists?
|
||||||
|
return false unless path_with_namespace
|
||||||
|
|
||||||
|
Gitlab::GitalyClient.migrate(:repository_exists) do |enabled|
|
||||||
|
if enabled
|
||||||
|
raw_repository.exists?
|
||||||
|
else
|
||||||
refs_directory_exists?
|
refs_directory_exists?
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
cache_method :exists?
|
cache_method :exists?
|
||||||
|
|
||||||
delegate :empty?, to: :raw_repository
|
delegate :empty?, to: :raw_repository
|
||||||
|
@ -1095,8 +1104,6 @@ class Repository
|
||||||
end
|
end
|
||||||
|
|
||||||
def refs_directory_exists?
|
def refs_directory_exists?
|
||||||
return false unless path_with_namespace
|
|
||||||
|
|
||||||
File.exist?(File.join(path_to_repo, 'refs'))
|
File.exist?(File.join(path_to_repo, 'refs'))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
class SystemNoteMetadata < ActiveRecord::Base
|
class SystemNoteMetadata < ActiveRecord::Base
|
||||||
ICON_TYPES = %w[
|
ICON_TYPES = %w[
|
||||||
commit description merge confidential visible label assignee cross_reference
|
commit description merge confidential visible label assignee cross_reference
|
||||||
title time_tracking branch milestone discussion task moved opened closed merged
|
title time_tracking branch milestone discussion task moved
|
||||||
|
opened closed merged duplicate
|
||||||
outdated
|
outdated
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
module Ci
|
module Ci
|
||||||
class BuildPolicy < CommitStatusPolicy
|
class BuildPolicy < CommitStatusPolicy
|
||||||
condition(:protected_action) do
|
condition(:protected_ref) do
|
||||||
next false unless @subject.action?
|
|
||||||
|
|
||||||
access = ::Gitlab::UserAccess.new(@user, project: @subject.project)
|
access = ::Gitlab::UserAccess.new(@user, project: @subject.project)
|
||||||
|
|
||||||
if @subject.tag?
|
if @subject.tag?
|
||||||
!access.can_create_tag?(@subject.ref)
|
!access.can_create_tag?(@subject.ref)
|
||||||
else
|
else
|
||||||
!access.can_merge_to_branch?(@subject.ref)
|
!access.can_update_branch?(@subject.ref)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
rule { protected_action }.prevent :update_build
|
rule { protected_ref }.prevent :update_build
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
module Ci
|
module Ci
|
||||||
class PipelinePolicy < BasePolicy
|
class PipelinePolicy < BasePolicy
|
||||||
delegate { @subject.project }
|
delegate { @subject.project }
|
||||||
|
|
||||||
|
condition(:protected_ref) do
|
||||||
|
access = ::Gitlab::UserAccess.new(@user, project: @subject.project)
|
||||||
|
|
||||||
|
if @subject.tag?
|
||||||
|
!access.can_create_tag?(@subject.ref)
|
||||||
|
else
|
||||||
|
!access.can_update_branch?(@subject.ref)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rule { protected_ref }.prevent :update_pipeline
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,7 +44,7 @@ class GlobalPolicy < BasePolicy
|
||||||
prevent :log_in
|
prevent :log_in
|
||||||
end
|
end
|
||||||
|
|
||||||
rule { ~restricted_public_level }.policy do
|
rule { admin | ~restricted_public_level }.policy do
|
||||||
enable :read_users_list
|
enable :read_users_list
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,8 @@ class BuildDetailsEntity < JobEntity
|
||||||
end
|
end
|
||||||
|
|
||||||
expose :path do |build|
|
expose :path do |build|
|
||||||
project_merge_request_path(project, build.merge_request)
|
project_merge_request_path(build.merge_request.project,
|
||||||
|
build.merge_request)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class DeployKeyEntity < Grape::Entity
|
||||||
expose :created_at
|
expose :created_at
|
||||||
expose :updated_at
|
expose :updated_at
|
||||||
expose :projects, using: ProjectEntity do |deploy_key|
|
expose :projects, using: ProjectEntity do |deploy_key|
|
||||||
deploy_key.projects.select { |project| options[:user].can?(:read_project, project) }
|
deploy_key.projects.without_deleted.select { |project| options[:user].can?(:read_project, project) }
|
||||||
end
|
end
|
||||||
expose :can_edit
|
expose :can_edit
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,41 @@ module Ci
|
||||||
pipeline_schedule: schedule
|
pipeline_schedule: schedule
|
||||||
)
|
)
|
||||||
|
|
||||||
|
result = validate(current_user || trigger_request.trigger.owner,
|
||||||
|
ignore_skip_ci: ignore_skip_ci,
|
||||||
|
save_on_errors: save_on_errors)
|
||||||
|
|
||||||
|
return result if result
|
||||||
|
|
||||||
|
Ci::Pipeline.transaction do
|
||||||
|
update_merge_requests_head_pipeline if pipeline.save
|
||||||
|
|
||||||
|
Ci::CreatePipelineStagesService
|
||||||
|
.new(project, current_user)
|
||||||
|
.execute(pipeline)
|
||||||
|
end
|
||||||
|
|
||||||
|
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
|
||||||
|
|
||||||
|
pipeline_created_counter.increment(source: source)
|
||||||
|
|
||||||
|
pipeline.tap(&:process!)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def validate(triggering_user, ignore_skip_ci:, save_on_errors:)
|
||||||
unless project.builds_enabled?
|
unless project.builds_enabled?
|
||||||
return error('Pipeline is disabled')
|
return error('Pipeline is disabled')
|
||||||
end
|
end
|
||||||
|
|
||||||
unless trigger_request || can?(current_user, :create_pipeline, project)
|
unless allowed_to_trigger_pipeline?(triggering_user)
|
||||||
|
if can?(triggering_user, :create_pipeline, project)
|
||||||
|
return error("Insufficient permissions for protected ref '#{ref}'")
|
||||||
|
else
|
||||||
return error('Insufficient permissions to create a new pipeline')
|
return error('Insufficient permissions to create a new pipeline')
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
unless branch? || tag?
|
unless branch? || tag?
|
||||||
return error('Reference not found')
|
return error('Reference not found')
|
||||||
|
@ -46,23 +74,28 @@ module Ci
|
||||||
unless pipeline.has_stage_seeds?
|
unless pipeline.has_stage_seeds?
|
||||||
return error('No stages / jobs for this pipeline.')
|
return error('No stages / jobs for this pipeline.')
|
||||||
end
|
end
|
||||||
|
|
||||||
Ci::Pipeline.transaction do
|
|
||||||
update_merge_requests_head_pipeline if pipeline.save
|
|
||||||
|
|
||||||
Ci::CreatePipelineStagesService
|
|
||||||
.new(project, current_user)
|
|
||||||
.execute(pipeline)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
cancel_pending_pipelines if project.auto_cancel_pending_pipelines?
|
def allowed_to_trigger_pipeline?(triggering_user)
|
||||||
|
if triggering_user
|
||||||
pipeline_created_counter.increment(source: source)
|
allowed_to_create?(triggering_user)
|
||||||
|
else # legacy triggers don't have a corresponding user
|
||||||
pipeline.tap(&:process!)
|
!project.protected_for?(ref)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def allowed_to_create?(triggering_user)
|
||||||
|
access = Gitlab::UserAccess.new(triggering_user, project: project)
|
||||||
|
|
||||||
|
can?(triggering_user, :create_pipeline, project) &&
|
||||||
|
if branch?
|
||||||
|
access.can_update_branch?(ref)
|
||||||
|
elsif tag?
|
||||||
|
access.can_create_tag?(ref)
|
||||||
|
else
|
||||||
|
true # Allow it for now and we'll reject when we check ref existence
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def update_merge_requests_head_pipeline
|
def update_merge_requests_head_pipeline
|
||||||
return unless pipeline.latest?
|
return unless pipeline.latest?
|
||||||
|
@ -113,15 +146,21 @@ module Ci
|
||||||
end
|
end
|
||||||
|
|
||||||
def branch?
|
def branch?
|
||||||
|
return @is_branch if defined?(@is_branch)
|
||||||
|
|
||||||
|
@is_branch =
|
||||||
project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref)
|
project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag?
|
def tag?
|
||||||
|
return @is_tag if defined?(@is_tag)
|
||||||
|
|
||||||
|
@is_tag =
|
||||||
project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref)
|
project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
def ref
|
def ref
|
||||||
Gitlab::Git.ref_name(origin_ref)
|
@ref ||= Gitlab::Git.ref_name(origin_ref)
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_sha?
|
def valid_sha?
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
module Ci
|
module Ci
|
||||||
class CreateTriggerRequestService
|
module CreateTriggerRequestService
|
||||||
def execute(project, trigger, ref, variables = nil)
|
Result = Struct.new(:trigger_request, :pipeline)
|
||||||
|
|
||||||
|
def self.execute(project, trigger, ref, variables = nil)
|
||||||
trigger_request = trigger.trigger_requests.create(variables: variables)
|
trigger_request = trigger.trigger_requests.create(variables: variables)
|
||||||
|
|
||||||
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref)
|
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref)
|
||||||
.execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
|
.execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
|
||||||
|
|
||||||
trigger_request if pipeline.persisted?
|
Result.new(trigger_request, pipeline)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -58,6 +58,7 @@ class IssuableBaseService < BaseService
|
||||||
params.delete(:assignee_ids)
|
params.delete(:assignee_ids)
|
||||||
params.delete(:assignee_id)
|
params.delete(:assignee_id)
|
||||||
params.delete(:due_date)
|
params.delete(:due_date)
|
||||||
|
params.delete(:canonical_issue_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
filter_assignee(issuable)
|
filter_assignee(issuable)
|
||||||
|
|
|
@ -7,6 +7,14 @@ module Issues
|
||||||
issue_data
|
issue_data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reopen_service
|
||||||
|
Issues::ReopenService
|
||||||
|
end
|
||||||
|
|
||||||
|
def close_service
|
||||||
|
Issues::CloseService
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_assignee_note(issue, old_assignees)
|
def create_assignee_note(issue, old_assignees)
|
||||||
|
|
24
app/services/issues/duplicate_service.rb
Normal file
24
app/services/issues/duplicate_service.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
module Issues
|
||||||
|
class DuplicateService < Issues::BaseService
|
||||||
|
def execute(duplicate_issue, canonical_issue)
|
||||||
|
return if canonical_issue == duplicate_issue
|
||||||
|
return unless can?(current_user, :update_issue, duplicate_issue)
|
||||||
|
return unless can?(current_user, :create_note, canonical_issue)
|
||||||
|
|
||||||
|
create_issue_duplicate_note(duplicate_issue, canonical_issue)
|
||||||
|
create_issue_canonical_note(canonical_issue, duplicate_issue)
|
||||||
|
|
||||||
|
close_service.new(project, current_user, {}).execute(duplicate_issue)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_issue_duplicate_note(duplicate_issue, canonical_issue)
|
||||||
|
SystemNoteService.mark_duplicate_issue(duplicate_issue, duplicate_issue.project, current_user, canonical_issue)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_issue_canonical_note(canonical_issue, duplicate_issue)
|
||||||
|
SystemNoteService.mark_canonical_issue_of_duplicate(canonical_issue, canonical_issue.project, current_user, duplicate_issue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,6 +5,7 @@ module Issues
|
||||||
def execute(issue)
|
def execute(issue)
|
||||||
handle_move_between_iids(issue)
|
handle_move_between_iids(issue)
|
||||||
filter_spam_check_params
|
filter_spam_check_params
|
||||||
|
change_issue_duplicate(issue)
|
||||||
update(issue)
|
update(issue)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -53,14 +54,6 @@ module Issues
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reopen_service
|
|
||||||
Issues::ReopenService
|
|
||||||
end
|
|
||||||
|
|
||||||
def close_service
|
|
||||||
Issues::CloseService
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_move_between_iids(issue)
|
def handle_move_between_iids(issue)
|
||||||
return unless params[:move_between_iids]
|
return unless params[:move_between_iids]
|
||||||
|
|
||||||
|
@ -72,6 +65,15 @@ module Issues
|
||||||
issue.move_between(issue_before, issue_after)
|
issue.move_between(issue_before, issue_after)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def change_issue_duplicate(issue)
|
||||||
|
canonical_issue_id = params.delete(:canonical_issue_id)
|
||||||
|
canonical_issue = IssuesFinder.new(current_user).find_by(id: canonical_issue_id)
|
||||||
|
|
||||||
|
if canonical_issue
|
||||||
|
Issues::DuplicateService.new(project, current_user).execute(issue, canonical_issue)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_issue_if_allowed(project, iid)
|
def get_issue_if_allowed(project, iid)
|
||||||
|
|
|
@ -15,24 +15,39 @@ module Projects
|
||||||
def execute
|
def execute
|
||||||
return false unless can?(current_user, :remove_project, project)
|
return false unless can?(current_user, :remove_project, project)
|
||||||
|
|
||||||
repo_path = project.path_with_namespace
|
|
||||||
wiki_path = repo_path + '.wiki'
|
|
||||||
|
|
||||||
# Flush the cache for both repositories. This has to be done _before_
|
# Flush the cache for both repositories. This has to be done _before_
|
||||||
# removing the physical repositories as some expiration code depends on
|
# removing the physical repositories as some expiration code depends on
|
||||||
# Git data (e.g. a list of branch names).
|
# Git data (e.g. a list of branch names).
|
||||||
flush_caches(project, wiki_path)
|
flush_caches(project)
|
||||||
|
|
||||||
Projects::UnlinkForkService.new(project, current_user).execute
|
Projects::UnlinkForkService.new(project, current_user).execute
|
||||||
|
|
||||||
Project.transaction do
|
attempt_destroy_transaction(project)
|
||||||
project.team.truncate
|
|
||||||
project.destroy!
|
|
||||||
|
|
||||||
unless remove_legacy_registry_tags
|
system_hook_service.execute_hooks_for(project, :destroy)
|
||||||
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
|
log_info("Project \"#{project.full_path}\" was removed")
|
||||||
|
|
||||||
|
true
|
||||||
|
rescue => error
|
||||||
|
attempt_rollback(project, error.message)
|
||||||
|
false
|
||||||
|
rescue Exception => error # rubocop:disable Lint/RescueException
|
||||||
|
# Project.transaction can raise Exception
|
||||||
|
attempt_rollback(project, error.message)
|
||||||
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def repo_path
|
||||||
|
project.path_with_namespace
|
||||||
|
end
|
||||||
|
|
||||||
|
def wiki_path
|
||||||
|
repo_path + '.wiki'
|
||||||
|
end
|
||||||
|
|
||||||
|
def trash_repositories!
|
||||||
unless remove_repository(repo_path)
|
unless remove_repository(repo_path)
|
||||||
raise_error('Failed to remove project repository. Please try again or contact administrator.')
|
raise_error('Failed to remove project repository. Please try again or contact administrator.')
|
||||||
end
|
end
|
||||||
|
@ -42,13 +57,6 @@ module Projects
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
log_info("Project \"#{project.path_with_namespace}\" was removed")
|
|
||||||
system_hook_service.execute_hooks_for(project, :destroy)
|
|
||||||
true
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def remove_repository(path)
|
def remove_repository(path)
|
||||||
# Skip repository removal. We use this flag when remove user or group
|
# Skip repository removal. We use this flag when remove user or group
|
||||||
return true if params[:skip_repo] == true
|
return true if params[:skip_repo] == true
|
||||||
|
@ -70,6 +78,26 @@ module Projects
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def attempt_rollback(project, message)
|
||||||
|
return unless project
|
||||||
|
|
||||||
|
project.update_attributes(delete_error: message, pending_delete: false)
|
||||||
|
log_error("Deletion failed on #{project.full_path} with the following message: #{message}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def attempt_destroy_transaction(project)
|
||||||
|
Project.transaction do
|
||||||
|
unless remove_legacy_registry_tags
|
||||||
|
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
|
||||||
|
end
|
||||||
|
|
||||||
|
trash_repositories!
|
||||||
|
|
||||||
|
project.team.truncate
|
||||||
|
project.destroy!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# This method makes sure that we correctly remove registry tags
|
# This method makes sure that we correctly remove registry tags
|
||||||
# for legacy image repository (when repository path equals project path).
|
# for legacy image repository (when repository path equals project path).
|
||||||
|
@ -96,7 +124,7 @@ module Projects
|
||||||
"#{path}+#{project.id}#{DELETED_FLAG}"
|
"#{path}+#{project.id}#{DELETED_FLAG}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def flush_caches(project, wiki_path)
|
def flush_caches(project)
|
||||||
project.repository.before_delete
|
project.repository.before_delete
|
||||||
|
|
||||||
Repository.new(wiki_path, project).before_delete
|
Repository.new(wiki_path, project).before_delete
|
||||||
|
|
|
@ -130,7 +130,11 @@ module Projects
|
||||||
end
|
end
|
||||||
|
|
||||||
def max_size
|
def max_size
|
||||||
current_application_settings.max_pages_size.megabytes || MAX_SIZE
|
max_pages_size = current_application_settings.max_pages_size.megabytes
|
||||||
|
|
||||||
|
return MAX_SIZE if max_pages_size.zero?
|
||||||
|
|
||||||
|
[max_pages_size, MAX_SIZE].min
|
||||||
end
|
end
|
||||||
|
|
||||||
def tmp_path
|
def tmp_path
|
||||||
|
|
|
@ -471,6 +471,24 @@ module QuickActions
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Mark this issue as a duplicate of another issue'
|
||||||
|
explanation do |duplicate_reference|
|
||||||
|
"Marks this issue as a duplicate of #{duplicate_reference}."
|
||||||
|
end
|
||||||
|
params '#issue'
|
||||||
|
condition do
|
||||||
|
issuable.is_a?(Issue) &&
|
||||||
|
issuable.persisted? &&
|
||||||
|
current_user.can?(:"update_#{issuable.to_ability_name}", issuable)
|
||||||
|
end
|
||||||
|
command :duplicate do |duplicate_param|
|
||||||
|
canonical_issue = extract_references(duplicate_param, :issue).first
|
||||||
|
|
||||||
|
if canonical_issue.present?
|
||||||
|
@updates[:canonical_issue_id] = canonical_issue.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def extract_users(params)
|
def extract_users(params)
|
||||||
return [] if params.nil?
|
return [] if params.nil?
|
||||||
|
|
||||||
|
|
|
@ -552,6 +552,44 @@ module SystemNoteService
|
||||||
create_note(NoteSummary.new(noteable, project, author, body, action: 'moved'))
|
create_note(NoteSummary.new(noteable, project, author, body, action: 'moved'))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Called when a Noteable has been marked as a duplicate of another Issue
|
||||||
|
#
|
||||||
|
# noteable - Noteable object
|
||||||
|
# project - Project owning noteable
|
||||||
|
# author - User performing the change
|
||||||
|
# canonical_issue - Issue that this is a duplicate of
|
||||||
|
#
|
||||||
|
# Example Note text:
|
||||||
|
#
|
||||||
|
# "marked this issue as a duplicate of #1234"
|
||||||
|
#
|
||||||
|
# "marked this issue as a duplicate of other_project#5678"
|
||||||
|
#
|
||||||
|
# Returns the created Note object
|
||||||
|
def mark_duplicate_issue(noteable, project, author, canonical_issue)
|
||||||
|
body = "marked this issue as a duplicate of #{canonical_issue.to_reference(project)}"
|
||||||
|
create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
|
||||||
|
end
|
||||||
|
|
||||||
|
# Called when a Noteable has been marked as the canonical Issue of a duplicate
|
||||||
|
#
|
||||||
|
# noteable - Noteable object
|
||||||
|
# project - Project owning noteable
|
||||||
|
# author - User performing the change
|
||||||
|
# duplicate_issue - Issue that was a duplicate of this
|
||||||
|
#
|
||||||
|
# Example Note text:
|
||||||
|
#
|
||||||
|
# "marked #1234 as a duplicate of this issue"
|
||||||
|
#
|
||||||
|
# "marked other_project#5678 as a duplicate of this issue"
|
||||||
|
#
|
||||||
|
# Returns the created Note object
|
||||||
|
def mark_canonical_issue_of_duplicate(noteable, project, author, duplicate_issue)
|
||||||
|
body = "marked #{duplicate_issue.to_reference(project)} as a duplicate of this issue"
|
||||||
|
create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def notes_for_mentioner(mentioner, noteable, notes)
|
def notes_for_mentioner(mentioner, noteable, notes)
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
.well-segment.well-centered
|
.well-segment.well-centered
|
||||||
= link_to admin_groups_path do
|
= link_to admin_groups_path do
|
||||||
%h3.text-center
|
%h3.text-center
|
||||||
Groups
|
Groups:
|
||||||
= number_with_delimiter(Group.count)
|
= number_with_delimiter(Group.count)
|
||||||
%hr
|
%hr
|
||||||
= link_to 'New group', new_admin_group_path, class: "btn btn-new"
|
= link_to 'New group', new_admin_group_path, class: "btn btn-new"
|
||||||
|
|
6
app/views/projects/_deletion_failed.html.haml
Normal file
6
app/views/projects/_deletion_failed.html.haml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
- project = local_assigns.fetch(:project)
|
||||||
|
- return unless project.delete_error.present?
|
||||||
|
|
||||||
|
.project-deletion-failed-message.alert.alert-warning
|
||||||
|
This project was scheduled for deletion, but failed with the following message:
|
||||||
|
= project.delete_error
|
8
app/views/projects/_flash_messages.html.haml
Normal file
8
app/views/projects/_flash_messages.html.haml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
- project = local_assigns.fetch(:project)
|
||||||
|
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
|
||||||
|
|
||||||
|
= content_for flash_message_container do
|
||||||
|
= render partial: 'deletion_failed', locals: { project: project }
|
||||||
|
- if current_user && can?(current_user, :download_code, project)
|
||||||
|
= render 'shared/no_ssh'
|
||||||
|
= render 'shared/no_password'
|
|
@ -1,10 +1,6 @@
|
||||||
- @no_container = true
|
- @no_container = true
|
||||||
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
|
|
||||||
|
|
||||||
= content_for flash_message_container do
|
= render partial: 'flash_messages', locals: { project: @project }
|
||||||
- if current_user && can?(current_user, :download_code, @project)
|
|
||||||
= render 'shared/no_ssh'
|
|
||||||
= render 'shared/no_password'
|
|
||||||
|
|
||||||
= render "projects/head"
|
= render "projects/head"
|
||||||
= render "home_panel"
|
= render "home_panel"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
- @no_container = true
|
- @no_container = true
|
||||||
- page_title "Labels"
|
- page_title "Labels"
|
||||||
- hide_class = ''
|
- hide_class = ''
|
||||||
|
- can_admin_label = can?(current_user, :admin_label, @project)
|
||||||
|
|
||||||
- if show_new_nav? && can?(current_user, :admin_label, @project)
|
- if show_new_nav? && can?(current_user, :admin_label, @project)
|
||||||
- content_for :breadcrumbs_extra do
|
- content_for :breadcrumbs_extra do
|
||||||
|
@ -12,15 +13,17 @@
|
||||||
%div{ class: container_class }
|
%div{ class: container_class }
|
||||||
.top-area.adjust
|
.top-area.adjust
|
||||||
.nav-text
|
.nav-text
|
||||||
Labels can be applied to issues and merge requests. Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.
|
Labels can be applied to issues and merge requests.
|
||||||
|
- if can_admin_label
|
||||||
|
Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.
|
||||||
|
|
||||||
|
- if can_admin_label
|
||||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||||
- if can?(current_user, :admin_label, @project)
|
|
||||||
= link_to new_project_label_path(@project), class: "btn btn-new" do
|
= link_to new_project_label_path(@project), class: "btn btn-new" do
|
||||||
New label
|
New label
|
||||||
|
|
||||||
.labels
|
.labels
|
||||||
- if can?(current_user, :admin_label, @project)
|
- if can_admin_label
|
||||||
-# Only show it in the first page
|
-# Only show it in the first page
|
||||||
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
|
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
|
||||||
.prioritized-labels{ class: ('hide' if hide) }
|
.prioritized-labels{ class: ('hide' if hide) }
|
||||||
|
@ -33,7 +36,7 @@
|
||||||
|
|
||||||
- if @labels.present?
|
- if @labels.present?
|
||||||
.other-labels
|
.other-labels
|
||||||
- if can?(current_user, :admin_label, @project)
|
- if can_admin_label
|
||||||
%h5{ class: ('hide' if hide) } Other Labels
|
%h5{ class: ('hide' if hide) } Other Labels
|
||||||
%ul.content-list.manage-labels-list.js-other-labels
|
%ul.content-list.manage-labels-list.js-other-labels
|
||||||
= render partial: 'shared/label', subject: @project, collection: @labels, as: :label
|
= render partial: 'shared/label', subject: @project, collection: @labels, as: :label
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form form-inline js-requires-input" } do |f|
|
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], url: project_new_merge_request_path(@project), method: :get, html: { class: "merge-request-form form-inline js-requires-input" } do |f|
|
||||||
.hide.alert.alert-danger.mr-compare-errors
|
.hide.alert.alert-danger.mr-compare-errors
|
||||||
.merge-request-branches.row
|
.merge-request-branches.js-merge-request-new-compare.row{ 'data-target-project-url': project_new_merge_request_update_branches_path(@source_project), 'data-source-branch-url': project_new_merge_request_branch_from_path(@source_project), 'data-target-branch-url': project_new_merge_request_branch_to_path(@source_project) }
|
||||||
.col-md-6
|
.col-md-6
|
||||||
.panel.panel-default.panel-new-merge-request
|
.panel.panel-default.panel-new-merge-request
|
||||||
.panel-heading
|
.panel-heading
|
||||||
|
@ -66,10 +66,3 @@
|
||||||
- if @merge_request.errors.any?
|
- if @merge_request.errors.any?
|
||||||
= form_errors(@merge_request)
|
= form_errors(@merge_request)
|
||||||
= f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn"
|
= f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn"
|
||||||
|
|
||||||
:javascript
|
|
||||||
new Compare({
|
|
||||||
targetProjectUrl: "#{project_new_merge_request_update_branches_path(@source_project)}",
|
|
||||||
sourceBranchUrl: "#{project_new_merge_request_branch_from_path(@source_project)}",
|
|
||||||
targetBranchUrl: "#{project_new_merge_request_branch_to_path(@source_project)}"
|
|
||||||
});
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
= f.hidden_field :target_project_id
|
= f.hidden_field :target_project_id
|
||||||
= f.hidden_field :target_branch
|
= f.hidden_field :target_branch
|
||||||
|
|
||||||
.mr-compare.merge-request
|
.mr-compare.merge-request.js-merge-request-new-submit{ 'data-mr-submit-action': "#{j params[:tab].presence || 'new'}" }
|
||||||
- if @commits.empty?
|
- if @commits.empty?
|
||||||
.commits-empty
|
.commits-empty
|
||||||
%h4
|
%h4
|
||||||
|
@ -50,8 +50,3 @@
|
||||||
|
|
||||||
.mr-loading-status
|
.mr-loading-status
|
||||||
= spinner
|
= spinner
|
||||||
|
|
||||||
:javascript
|
|
||||||
var merge_request = new MergeRequest({
|
|
||||||
action: "#{j params[:tab].presence || 'new'}",
|
|
||||||
});
|
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
- page_description @merge_request.description
|
- page_description @merge_request.description
|
||||||
- page_card_attributes @merge_request.card_attributes
|
- page_card_attributes @merge_request.card_attributes
|
||||||
- content_for :page_specific_javascripts do
|
- content_for :page_specific_javascripts do
|
||||||
= page_specific_javascript_bundle_tag('common_vue')
|
= webpack_bundle_tag('common_vue')
|
||||||
= page_specific_javascript_bundle_tag('diff_notes')
|
= webpack_bundle_tag('diff_notes')
|
||||||
|
|
||||||
.merge-request{ 'data-url' => merge_request_path(@merge_request, format: :json), 'data-project-path' => project_path(@merge_request.project) }
|
.merge-request{ 'data-mr-action': "#{j params[:tab].presence || 'show'}", 'data-url' => merge_request_path(@merge_request, format: :json), 'data-project-path' => project_path(@merge_request.project) }
|
||||||
= render "projects/merge_requests/mr_title"
|
= render "projects/merge_requests/mr_title"
|
||||||
|
|
||||||
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
|
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
|
||||||
|
@ -15,13 +15,13 @@
|
||||||
- if @merge_request.source_branch_exists?
|
- if @merge_request.source_branch_exists?
|
||||||
= render "projects/merge_requests/how_to_merge"
|
= render "projects/merge_requests/how_to_merge"
|
||||||
|
|
||||||
|
-# haml-lint:disable InlineJavaScript
|
||||||
:javascript
|
:javascript
|
||||||
window.gl.mrWidgetData = #{serialize_issuable(@merge_request)}
|
window.gl.mrWidgetData = #{serialize_issuable(@merge_request)}
|
||||||
|
|
||||||
#js-vue-mr-widget.mr-widget
|
#js-vue-mr-widget.mr-widget
|
||||||
|
|
||||||
- content_for :page_specific_javascripts do
|
- content_for :page_specific_javascripts do
|
||||||
= webpack_bundle_tag 'common_vue'
|
|
||||||
= webpack_bundle_tag 'vue_merge_request_widget'
|
= webpack_bundle_tag 'vue_merge_request_widget'
|
||||||
|
|
||||||
.content-block.content-block-small.emoji-list-container
|
.content-block.content-block-small.emoji-list-container
|
||||||
|
@ -88,10 +88,3 @@
|
||||||
= render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
|
= render "projects/commit/change", type: 'revert', commit: @merge_request.merge_commit, title: @merge_request.title
|
||||||
- if @merge_request.can_be_cherry_picked?
|
- if @merge_request.can_be_cherry_picked?
|
||||||
= render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit, title: @merge_request.title
|
= render "projects/commit/change", type: 'cherry-pick', commit: @merge_request.merge_commit, title: @merge_request.title
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function () {
|
|
||||||
window.mergeRequest = new MergeRequest({
|
|
||||||
action: "#{j params[:tab].presence || 'show'}",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
%div
|
%div
|
||||||
- if fogbugz_import_enabled?
|
- if fogbugz_import_enabled?
|
||||||
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
|
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
|
||||||
= icon('bug', text: 'Fogbugz')
|
= icon('bug', text: 'FogBugz')
|
||||||
%div
|
%div
|
||||||
- if gitea_import_enabled?
|
- if gitea_import_enabled?
|
||||||
= link_to new_import_gitea_url, class: 'btn import_gitea' do
|
= link_to new_import_gitea_url, class: 'btn import_gitea' do
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
- @no_container = true
|
- @no_container = true
|
||||||
- breadcrumb_title "Project"
|
- breadcrumb_title "Project"
|
||||||
- @content_class = "limit-container-width" unless fluid_layout
|
- @content_class = "limit-container-width" unless fluid_layout
|
||||||
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
|
|
||||||
|
|
||||||
= content_for :meta_tags do
|
= content_for :meta_tags do
|
||||||
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
|
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
|
||||||
|
|
||||||
= content_for flash_message_container do
|
= render partial: 'flash_messages', locals: { project: @project }
|
||||||
- if current_user && can?(current_user, :download_code, @project)
|
|
||||||
= render 'shared/no_ssh'
|
|
||||||
= render 'shared/no_password'
|
|
||||||
|
|
||||||
= render "projects/head"
|
= render "projects/head"
|
||||||
= render "projects/last_push"
|
= render "projects/last_push"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
- if @projects.any?
|
- if @projects.any?
|
||||||
.project-item-select-holder
|
.project-item-select-holder
|
||||||
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at' }, with_feature_enabled: local_assigns[:with_feature_enabled]
|
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled]
|
||||||
%a.btn.btn-new.new-project-item-select-button{ data: { relative_path: local_assigns[:path] } }
|
%a.btn.btn-new.new-project-item-select-button
|
||||||
= local_assigns[:label]
|
= local_assigns[:label]
|
||||||
= icon('caret-down')
|
= icon('caret-down')
|
||||||
|
|
3
app/views/shared/icons/_icon_clone.svg
Normal file
3
app/views/shared/icons/_icon_clone.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" viewBox="0 0 14 14">
|
||||||
|
<path d="M13 12.75v-8.5q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h8.5q0.102 0 0.176-0.074t0.074-0.176zM14 4.25v8.5q0 0.516-0.367 0.883t-0.883 0.367h-8.5q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883zM11 1.25v1.25h-1v-1.25q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h1.25v1h-1.25q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 735 B |
|
@ -4,5 +4,5 @@
|
||||||
= link_to user, title: user.name, class: "darken" do
|
= link_to user, title: user.name, class: "darken" do
|
||||||
= image_tag avatar_icon(user, 32), class: "avatar s32"
|
= image_tag avatar_icon(user, 32), class: "avatar s32"
|
||||||
%strong= truncate(user.name, length: 40)
|
%strong= truncate(user.name, length: 40)
|
||||||
%br
|
%div
|
||||||
%small.cgray= user.username
|
%small.cgray= user.username
|
||||||
|
|
|
@ -6,15 +6,12 @@ class PipelineScheduleWorker
|
||||||
Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now)
|
Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now)
|
||||||
.preload(:owner, :project).find_each do |schedule|
|
.preload(:owner, :project).find_each do |schedule|
|
||||||
begin
|
begin
|
||||||
unless schedule.runnable_by_owner?
|
pipeline = Ci::CreatePipelineService.new(schedule.project,
|
||||||
schedule.deactivate!
|
|
||||||
next
|
|
||||||
end
|
|
||||||
|
|
||||||
Ci::CreatePipelineService.new(schedule.project,
|
|
||||||
schedule.owner,
|
schedule.owner,
|
||||||
ref: schedule.ref)
|
ref: schedule.ref)
|
||||||
.execute(:schedule, save_on_errors: false, schedule: schedule)
|
.execute(:schedule, save_on_errors: false, schedule: schedule)
|
||||||
|
|
||||||
|
schedule.deactivate! unless pipeline.persisted?
|
||||||
rescue => e
|
rescue => e
|
||||||
Rails.logger.error "#{schedule.id}: Failed to create a scheduled pipeline: #{e.message}"
|
Rails.logger.error "#{schedule.id}: Failed to create a scheduled pipeline: #{e.message}"
|
||||||
ensure
|
ensure
|
||||||
|
|
|
@ -3,14 +3,11 @@ class ProjectDestroyWorker
|
||||||
include DedicatedSidekiqQueue
|
include DedicatedSidekiqQueue
|
||||||
|
|
||||||
def perform(project_id, user_id, params)
|
def perform(project_id, user_id, params)
|
||||||
begin
|
project = Project.find(project_id)
|
||||||
project = Project.unscoped.find(project_id)
|
|
||||||
rescue ActiveRecord::RecordNotFound
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
user = User.find(user_id)
|
user = User.find(user_id)
|
||||||
|
|
||||||
::Projects::DestroyService.new(project, user, params.symbolize_keys).execute
|
::Projects::DestroyService.new(project, user, params.symbolize_keys).execute
|
||||||
|
rescue ActiveRecord::RecordNotFound => error
|
||||||
|
logger.error("Failed to delete project (#{project_id}): #{error.message}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Declare related resources into V4 API entities
|
||||||
|
merge_request:
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Added /duplicate quick action to close a duplicate issue
|
||||||
|
merge_request: 12845
|
||||||
|
author: Ryan Scott
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Handle errors while a project is being deleted asynchronously.
|
||||||
|
merge_request: 11088
|
||||||
|
author:
|
4
changelogs/unreleased/2971-multiproject-grah-ce-port.yml
Normal file
4
changelogs/unreleased/2971-multiproject-grah-ce-port.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Fix vertical alignment in firefox and safari for pipeline mini graph
|
||||||
|
merge_request:
|
||||||
|
author:
|
5
changelogs/unreleased/30634-protected-pipeline.yml
Normal file
5
changelogs/unreleased/30634-protected-pipeline.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Disallow running the pipeline if ref is protected and user cannot merge the
|
||||||
|
branch or create the tag
|
||||||
|
merge_request: 11910
|
||||||
|
author:
|
4
changelogs/unreleased/31129-jira-project-key-elim.yml
Normal file
4
changelogs/unreleased/31129-jira-project-key-elim.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Remove project_key from the Jira configuration
|
||||||
|
merge_request: 12050
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add CSRF token verification to API
|
||||||
|
merge_request: 12154
|
||||||
|
author: Vitaliy @blackst0ne Klachkov
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Added link to the MR widget that directs to the monitoring dashboard
|
||||||
|
merge_request:
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Remove help message about prioritized labels for non-members
|
||||||
|
merge_request: 12912
|
||||||
|
author: Takuya Noguchi
|
4
changelogs/unreleased/35204-doc-api-ci-lint-typo.yml
Normal file
4
changelogs/unreleased/35204-doc-api-ci-lint-typo.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add link to doc/api/ci/lint.md
|
||||||
|
merge_request: 12914
|
||||||
|
author: Takuya Noguchi
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Pending delete projects should not show in deploy keys.
|
||||||
|
merge_request: 13088
|
||||||
|
author:
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix margins in the mini graph for pipeline in commits box
|
|
||||||
merge_request:
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix anonymous access to public projects in groups with pending invites
|
|
||||||
merge_request:
|
|
||||||
author:
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Fixes 500 error caused by pending delete projects in admin dashboard
|
||||||
|
merge_request: 13067
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Allow admin to read_users_list even if it's restricted
|
||||||
|
merge_request: 13066
|
||||||
|
author:
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Fix creating merge request diffs when diff contains bytes that are invalid
|
||||||
|
in UTF-8
|
||||||
|
merge_request:
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add instrumentation to MarkupHelper#link_to_gfm
|
||||||
|
merge_request: 13069
|
||||||
|
author:
|
4
changelogs/unreleased/bump-omniauth-ldap-gem-version.yml
Normal file
4
changelogs/unreleased/bump-omniauth-ldap-gem-version.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Prevent LDAP login callback from being called with a GET request
|
||||||
|
merge_request: 13059
|
||||||
|
author:
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix some invalid entries in PO files
|
|
||||||
merge_request: 13032
|
|
||||||
author:
|
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix cross site request protection when logging in as a regular user when LDAP
|
|
||||||
is enabled
|
|
||||||
merge_request: 13049
|
|
||||||
author:
|
|
5
changelogs/unreleased/bvl-free-unused-names.yml
Normal file
5
changelogs/unreleased/bvl-free-unused-names.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Free up some top level words, reject top level groups named like files in the
|
||||||
|
public folder
|
||||||
|
merge_request: 12932
|
||||||
|
author:
|
4
changelogs/unreleased/feature-backup-custom-path.yml
Normal file
4
changelogs/unreleased/feature-backup-custom-path.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Support custom directory in gitlab:backup:create task
|
||||||
|
merge_request: 12984
|
||||||
|
author: Markus Koller
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Fix job merge request link to a forked source project
|
||||||
|
merge_request: 12965
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Handle maximum pages artifacts size correctly
|
||||||
|
merge_request: 13072
|
||||||
|
author:
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix editing project with container images present
|
|
||||||
merge_request: 13028
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix pipeline_schedules pages throwing error 500 (when ref is empty)
|
|
||||||
merge_request: 12983
|
|
||||||
author:
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fixed issue boards sidebar close icon size
|
|
||||||
merge_request:
|
|
||||||
author:
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add LDAP SSL certificate verification option
|
||||||
|
merge_request:
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Improve redirect route query performance
|
||||||
|
merge_request: 13062
|
||||||
|
author:
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fixed duplicate new milestone buttons when new navigation is turned on
|
|
||||||
merge_request:
|
|
||||||
author:
|
|
4
changelogs/unreleased/new-navigation-custom-logo.yml
Normal file
4
changelogs/unreleased/new-navigation-custom-logo.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Fix sizing of custom header logo in new navigation
|
||||||
|
merge_request:
|
||||||
|
author:
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Ensure filesystem metrics test files are deleted
|
||||||
|
merge_request:
|
||||||
|
author:
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
title: Fix bug causing metrics files to be truncated
|
|
||||||
merge_request: 35420
|
|
||||||
author:
|
|
4
changelogs/unreleased/post-upload-pack-opt-out.yml
Normal file
4
changelogs/unreleased/post-upload-pack-opt-out.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Enable gitaly_post_upload_pack by default
|
||||||
|
merge_request: 13078
|
||||||
|
author:
|
5
changelogs/unreleased/rc-fix-branches-api-endpoint.yml
Normal file
5
changelogs/unreleased/rc-fix-branches-api-endpoint.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Fix the /projects/:id/repository/branches endpoint to handle dots in the branch
|
||||||
|
name when the project full patch contains a `/`
|
||||||
|
merge_request: 13115
|
||||||
|
author:
|
4
changelogs/unreleased/tc-issue-api-assignee.yml
Normal file
4
changelogs/unreleased/tc-issue-api-assignee.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
title: Add author_id & assignee_id param to /issues API
|
||||||
|
merge_request: 13004
|
||||||
|
author:
|
|
@ -228,7 +228,8 @@ production: &base
|
||||||
# ==========================
|
# ==========================
|
||||||
|
|
||||||
## LDAP settings
|
## LDAP settings
|
||||||
# You can inspect a sample of the LDAP users with login access by running:
|
# You can test connections and inspect a sample of the LDAP users with login
|
||||||
|
# access by running:
|
||||||
# bundle exec rake gitlab:ldap:check RAILS_ENV=production
|
# bundle exec rake gitlab:ldap:check RAILS_ENV=production
|
||||||
ldap:
|
ldap:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
@ -251,13 +252,45 @@ production: &base
|
||||||
# Example: 'Paris' or 'Acme, Ltd.'
|
# Example: 'Paris' or 'Acme, Ltd.'
|
||||||
label: 'LDAP'
|
label: 'LDAP'
|
||||||
|
|
||||||
|
# Example: 'ldap.mydomain.com'
|
||||||
host: '_your_ldap_server'
|
host: '_your_ldap_server'
|
||||||
port: 389
|
# This port is an example, it is sometimes different but it is always an integer and not a string
|
||||||
uid: 'sAMAccountName'
|
port: 389 # usually 636 for SSL
|
||||||
method: 'plain' # "tls" or "ssl" or "plain"
|
uid: 'sAMAccountName' # This should be the attribute, not the value that maps to uid.
|
||||||
|
|
||||||
|
# Examples: 'america\\momo' or 'CN=Gitlab Git,CN=Users,DC=mydomain,DC=com'
|
||||||
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
|
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
|
||||||
password: '_the_password_of_the_bind_user'
|
password: '_the_password_of_the_bind_user'
|
||||||
|
|
||||||
|
# Encryption method. The "method" key is deprecated in favor of
|
||||||
|
# "encryption".
|
||||||
|
#
|
||||||
|
# Examples: "start_tls" or "simple_tls" or "plain"
|
||||||
|
#
|
||||||
|
# Deprecated values: "tls" was replaced with "start_tls" and "ssl" was
|
||||||
|
# replaced with "simple_tls".
|
||||||
|
#
|
||||||
|
encryption: 'plain'
|
||||||
|
|
||||||
|
# Enables SSL certificate verification if encryption method is
|
||||||
|
# "start_tls" or "simple_tls". (Defaults to false for backward-
|
||||||
|
# compatibility)
|
||||||
|
verify_certificates: false
|
||||||
|
|
||||||
|
# Specifies the path to a file containing a PEM-format CA certificate,
|
||||||
|
# e.g. if you need to use an internal CA.
|
||||||
|
#
|
||||||
|
# Example: '/etc/ca.pem'
|
||||||
|
#
|
||||||
|
ca_cert: ''
|
||||||
|
|
||||||
|
# Specifies the SSL version for OpenSSL to use, if the OpenSSL default
|
||||||
|
# is not appropriate.
|
||||||
|
#
|
||||||
|
# Example: 'TLSv1_1'
|
||||||
|
#
|
||||||
|
ssl_version: ''
|
||||||
|
|
||||||
# Set a timeout, in seconds, for LDAP queries. This helps avoid blocking
|
# Set a timeout, in seconds, for LDAP queries. This helps avoid blocking
|
||||||
# a request if the LDAP server becomes unresponsive.
|
# a request if the LDAP server becomes unresponsive.
|
||||||
# A value of 0 means there is no timeout.
|
# A value of 0 means there is no timeout.
|
||||||
|
@ -286,17 +319,20 @@ production: &base
|
||||||
|
|
||||||
# Base where we can search for users
|
# Base where we can search for users
|
||||||
#
|
#
|
||||||
# Ex. ou=People,dc=gitlab,dc=example
|
# Ex. 'ou=People,dc=gitlab,dc=example' or 'DC=mydomain,DC=com'
|
||||||
#
|
#
|
||||||
base: ''
|
base: ''
|
||||||
|
|
||||||
# Filter LDAP users
|
# Filter LDAP users
|
||||||
#
|
#
|
||||||
# Format: RFC 4515 http://tools.ietf.org/search/rfc4515
|
# Format: RFC 4515 https://tools.ietf.org/search/rfc4515
|
||||||
# Ex. (employeeType=developer)
|
# Ex. (employeeType=developer)
|
||||||
#
|
#
|
||||||
# Note: GitLab does not support omniauth-ldap's custom filter syntax.
|
# Note: GitLab does not support omniauth-ldap's custom filter syntax.
|
||||||
#
|
#
|
||||||
|
# Example for getting only specific users:
|
||||||
|
# '(&(objectclass=user)(|(samaccountname=momo)(samaccountname=toto)))'
|
||||||
|
#
|
||||||
user_filter: ''
|
user_filter: ''
|
||||||
|
|
||||||
# LDAP attributes that GitLab will use to create an account for the LDAP user.
|
# LDAP attributes that GitLab will use to create an account for the LDAP user.
|
||||||
|
@ -674,7 +710,7 @@ test:
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 3890
|
port: 3890
|
||||||
uid: 'uid'
|
uid: 'uid'
|
||||||
method: 'plain' # "tls" or "ssl" or "plain"
|
encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
|
||||||
base: 'dc=example,dc=com'
|
base: 'dc=example,dc=com'
|
||||||
user_filter: ''
|
user_filter: ''
|
||||||
group_base: 'ou=groups,dc=example,dc=com'
|
group_base: 'ou=groups,dc=example,dc=com'
|
||||||
|
|
|
@ -145,6 +145,24 @@ if Settings.ldap['enabled'] || Rails.env.test?
|
||||||
server['attributes'] = {} if server['attributes'].nil?
|
server['attributes'] = {} if server['attributes'].nil?
|
||||||
server['provider_name'] ||= "ldap#{key}".downcase
|
server['provider_name'] ||= "ldap#{key}".downcase
|
||||||
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
|
server['provider_class'] = OmniAuth::Utils.camelize(server['provider_name'])
|
||||||
|
|
||||||
|
# For backwards compatibility
|
||||||
|
server['encryption'] ||= server['method']
|
||||||
|
server['encryption'] = 'simple_tls' if server['encryption'] == 'ssl'
|
||||||
|
server['encryption'] = 'start_tls' if server['encryption'] == 'tls'
|
||||||
|
|
||||||
|
# Certificates are not verified for backwards compatibility.
|
||||||
|
# This default should be flipped to true in 9.5.
|
||||||
|
if server['verify_certificates'].nil?
|
||||||
|
server['verify_certificates'] = false
|
||||||
|
|
||||||
|
message = <<-MSG.strip_heredoc
|
||||||
|
LDAP SSL certificate verification is disabled for backwards-compatibility.
|
||||||
|
Please add the "verify_certificates" option to gitlab.yml for each LDAP
|
||||||
|
server. Certificate verification will be enabled by default in GitLab 9.5.
|
||||||
|
MSG
|
||||||
|
Rails.logger.warn(message)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -441,10 +459,6 @@ Settings.backup['pg_schema'] = nil
|
||||||
Settings.backup['path'] = Settings.absolute(Settings.backup['path'] || "tmp/backups/")
|
Settings.backup['path'] = Settings.absolute(Settings.backup['path'] || "tmp/backups/")
|
||||||
Settings.backup['archive_permissions'] ||= 0600
|
Settings.backup['archive_permissions'] ||= 0600
|
||||||
Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
|
Settings.backup['upload'] ||= Settingslogic.new({ 'remote_directory' => nil, 'connection' => nil })
|
||||||
# Convert upload connection settings to use symbol keys, to make Fog happy
|
|
||||||
if Settings.backup['upload']['connection']
|
|
||||||
Settings.backup['upload']['connection'] = Hash[Settings.backup['upload']['connection'].map { |k, v| [k.to_sym, v] }]
|
|
||||||
end
|
|
||||||
Settings.backup['upload']['multipart_chunk_size'] ||= 104857600
|
Settings.backup['upload']['multipart_chunk_size'] ||= 104857600
|
||||||
Settings.backup['upload']['encryption'] ||= nil
|
Settings.backup['upload']['encryption'] ||= nil
|
||||||
Settings.backup['upload']['storage_class'] ||= nil
|
Settings.backup['upload']['storage_class'] ||= nil
|
||||||
|
|
|
@ -6,7 +6,7 @@ Prometheus::Client.configure do |config|
|
||||||
config.initial_mmap_file_size = 4 * 1024
|
config.initial_mmap_file_size = 4 * 1024
|
||||||
config.multiprocess_files_dir = ENV['prometheus_multiproc_dir']
|
config.multiprocess_files_dir = ENV['prometheus_multiproc_dir']
|
||||||
|
|
||||||
if Rails.env.development? && Rails.env.test?
|
if Rails.env.development? || Rails.env.test?
|
||||||
config.multiprocess_files_dir ||= Rails.root.join('tmp/prometheus_multiproc_dir')
|
config.multiprocess_files_dir ||= Rails.root.join('tmp/prometheus_multiproc_dir')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -114,6 +114,9 @@ def instrument_classes(instrumentation)
|
||||||
# This is a Rails scope so we have to instrument it manually.
|
# This is a Rails scope so we have to instrument it manually.
|
||||||
instrumentation.instrument_method(Project, :visible_to_user)
|
instrumentation.instrument_method(Project, :visible_to_user)
|
||||||
|
|
||||||
|
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/34509
|
||||||
|
instrumentation.instrument_method(MarkupHelper, :link_to_gfm)
|
||||||
|
|
||||||
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159
|
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159
|
||||||
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
|
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
|
||||||
end
|
end
|
||||||
|
|
35
config/initializers/grape_route_helpers_fix.rb
Normal file
35
config/initializers/grape_route_helpers_fix.rb
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
if defined?(GrapeRouteHelpers)
|
||||||
|
module GrapeRouteHelpers
|
||||||
|
class DecoratedRoute
|
||||||
|
# GrapeRouteHelpers gem tries to parse the versions
|
||||||
|
# from a string, not supporting Grape `version` array definition.
|
||||||
|
#
|
||||||
|
# Without the following fix, we get this on route helpers generation:
|
||||||
|
#
|
||||||
|
# => undefined method `scan' for ["v3", "v4"]
|
||||||
|
#
|
||||||
|
# 2.0.0 implementation of this method:
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# def route_versions
|
||||||
|
# version_pattern = /[^\[",\]\s]+/
|
||||||
|
# if route_version
|
||||||
|
# route_version.scan(version_pattern)
|
||||||
|
# else
|
||||||
|
# [nil]
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# ```
|
||||||
|
def route_versions
|
||||||
|
return [nil] if route_version.nil? || route_version.empty?
|
||||||
|
|
||||||
|
if route_version.is_a?(String)
|
||||||
|
version_pattern = /[^\[",\]\s]+/
|
||||||
|
route_version.scan(version_pattern)
|
||||||
|
else
|
||||||
|
route_version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,7 +16,7 @@ OmniAuth.config.allowed_request_methods = [:post]
|
||||||
# In case of auto sign-in, the GET method is used (users don't get to click on a button)
|
# In case of auto sign-in, the GET method is used (users don't get to click on a button)
|
||||||
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
|
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
|
||||||
OmniAuth.config.before_request_phase do |env|
|
OmniAuth.config.before_request_phase do |env|
|
||||||
OmniAuth::RequestForgeryProtection.call(env)
|
Gitlab::RequestForgeryProtection.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Gitlab.config.omniauth.enabled
|
if Gitlab.config.omniauth.enabled
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue