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
|
||||
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)
|
||||
|
||||
- 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:
|
||||
|
||||
- Type: ~"feature proposal", ~bug, ~customer, etc.
|
||||
- Subject: ~wiki, ~"container registry", ~ldap, ~api, etc.
|
||||
- Team: ~CI, ~Discussion, ~Edge, ~Frontend, ~Platform, etc.
|
||||
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
|
||||
- Team: ~CI, ~Discussion, ~Edge, ~Platform, etc.
|
||||
- Priority: ~Deliverable, ~Stretch
|
||||
|
||||
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
|
||||
[`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]
|
||||
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"`.
|
||||
|
||||
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 'rugged', '~> 0.25.1.1'
|
||||
gem 'grape-route-helpers', '~> 2.0.0'
|
||||
|
||||
gem 'faraday', '~> 0.12'
|
||||
|
||||
|
@ -60,7 +61,8 @@ gem 'browser', '~> 2.2'
|
|||
# LDAP Auth
|
||||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
# 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
|
||||
# Required manually in config/initializers/gollum.rb to control load order
|
||||
|
@ -164,7 +166,7 @@ gem 'rainbow', '~> 2.2'
|
|||
gem 'settingslogic', '~> 2.0.9'
|
||||
|
||||
# Linear-time regex library for untrusted regular expressions
|
||||
gem 're2', '~> 1.1.0'
|
||||
gem 're2', '~> 1.1.1'
|
||||
|
||||
# Misc
|
||||
|
||||
|
|
26
Gemfile.lock
26
Gemfile.lock
|
@ -288,11 +288,11 @@ GEM
|
|||
mime-types (>= 1.16, < 3)
|
||||
posix-spawn (~> 0.3)
|
||||
gitlab-markup (1.5.1)
|
||||
gitlab_omniauth-ldap (1.2.1)
|
||||
net-ldap (~> 0.9)
|
||||
omniauth (~> 1.0)
|
||||
pyu-ruby-sasl (~> 0.0.3.1)
|
||||
rubyntlm (~> 0.3)
|
||||
gitlab_omniauth-ldap (2.0.3)
|
||||
net-ldap (~> 0.16)
|
||||
omniauth (~> 1.3)
|
||||
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
|
||||
rubyntlm (~> 0.5)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
gollum-grit_adapter (1.0.1)
|
||||
|
@ -345,6 +345,10 @@ GEM
|
|||
grape-entity (0.6.0)
|
||||
activesupport
|
||||
multi_json (>= 1.3.2)
|
||||
grape-route-helpers (2.0.0)
|
||||
activesupport
|
||||
grape (~> 0.16, >= 0.16.0)
|
||||
rake
|
||||
grpc (1.4.0)
|
||||
google-protobuf (~> 3.1)
|
||||
googleauth (~> 0.5.1)
|
||||
|
@ -467,7 +471,7 @@ GEM
|
|||
mustermann-grape (1.0.0)
|
||||
mustermann (~> 1.0.0)
|
||||
mysql2 (0.4.5)
|
||||
net-ldap (0.12.1)
|
||||
net-ldap (0.16.0)
|
||||
netrc (0.11.0)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
|
@ -656,7 +660,7 @@ GEM
|
|||
debugger-ruby_core_source (~> 1.3)
|
||||
rdoc (4.2.2)
|
||||
json (~> 1.4)
|
||||
re2 (1.1.0)
|
||||
re2 (1.1.1)
|
||||
recaptcha (3.0.0)
|
||||
json
|
||||
recursive-open-struct (1.0.0)
|
||||
|
@ -740,7 +744,7 @@ GEM
|
|||
nokogiri (>= 1.5.10)
|
||||
ruby_parser (3.9.0)
|
||||
sexp_processor (~> 4.1)
|
||||
rubyntlm (0.5.2)
|
||||
rubyntlm (0.6.2)
|
||||
rubypants (0.2.0)
|
||||
rubyzip (1.2.1)
|
||||
rufus-scheduler (3.4.0)
|
||||
|
@ -974,13 +978,14 @@ DEPENDENCIES
|
|||
github-linguist (~> 4.7.0)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab-markup (~> 1.5.1)
|
||||
gitlab_omniauth-ldap (~> 1.2.1)
|
||||
gitlab_omniauth-ldap (~> 2.0.3)
|
||||
gollum-lib (~> 4.2)
|
||||
gollum-rugged_adapter (~> 0.4.4)
|
||||
gon (~> 6.1.0)
|
||||
google-api-client (~> 0.8.6)
|
||||
grape (~> 0.19.2)
|
||||
grape-entity (~> 0.6.0)
|
||||
grape-route-helpers (~> 2.0.0)
|
||||
haml_lint (~> 0.21.0)
|
||||
hamlit (~> 2.6.1)
|
||||
hashie-forbidden_attributes
|
||||
|
@ -1008,6 +1013,7 @@ DEPENDENCIES
|
|||
minitest (~> 5.7.0)
|
||||
mousetrap-rails (~> 1.4.6)
|
||||
mysql2 (~> 0.4.5)
|
||||
net-ldap
|
||||
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
||||
oauth2 (~> 1.4)
|
||||
octokit (~> 4.6.2)
|
||||
|
@ -1055,7 +1061,7 @@ DEPENDENCIES
|
|||
raindrops (~> 0.18)
|
||||
rblineprof (~> 0.3.6)
|
||||
rdoc (~> 4.2)
|
||||
re2 (~> 1.1.0)
|
||||
re2 (~> 1.1.1)
|
||||
recaptcha (~> 3.0)
|
||||
redcarpet (~> 3.4)
|
||||
redis (~> 3.2)
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
/* global NamespaceSelects */
|
||||
/* global Project */
|
||||
/* global ProjectAvatar */
|
||||
/* global MergeRequest */
|
||||
/* global Compare */
|
||||
/* global CompareAutocomplete */
|
||||
/* global ProjectNew */
|
||||
/* global ProjectShow */
|
||||
|
@ -228,6 +230,19 @@ import initIssuableSidebar from './init_issuable_sidebar';
|
|||
new gl.IssuableTemplateSelectors();
|
||||
break;
|
||||
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:edit':
|
||||
new gl.Diff();
|
||||
|
@ -267,8 +282,14 @@ import initIssuableSidebar from './init_issuable_sidebar';
|
|||
new gl.Diff();
|
||||
shortcut_handler = new ShortcutsIssuable(true);
|
||||
new ZenMode();
|
||||
|
||||
initIssuableSidebar();
|
||||
initNotes();
|
||||
|
||||
const mrShowNode = document.querySelector('.merge-request');
|
||||
window.mergeRequest = new MergeRequest({
|
||||
action: mrShowNode.dataset.mrAction,
|
||||
});
|
||||
break;
|
||||
case 'dashboard:activity':
|
||||
new gl.Activities();
|
||||
|
|
|
@ -3,10 +3,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
modal: true,
|
||||
show: false,
|
||||
});
|
||||
$('.how_to_merge_link').bind('click', () => {
|
||||
$('.how_to_merge_link').on('click', () => {
|
||||
modal.show();
|
||||
});
|
||||
$('.modal-header .close').bind('click', () => {
|
||||
$('.modal-header .close').on('click', () => {
|
||||
modal.hide();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -175,7 +175,7 @@ import Cookies from 'js-cookie';
|
|||
|
||||
getConflictsCountText() {
|
||||
const count = this.getConflictsCount();
|
||||
const text = count ? 'conflicts' : 'conflict';
|
||||
const text = count > 1 ? 'conflicts' : 'conflict';
|
||||
|
||||
return `${count} ${text}`;
|
||||
},
|
||||
|
|
|
@ -108,7 +108,8 @@ export default {
|
|||
</div>
|
||||
<mr-widget-memory-usage
|
||||
v-if="deployment.metrics_url"
|
||||
:metricsUrl="deployment.metrics_url"
|
||||
:metrics-url="deployment.metrics_url"
|
||||
:metrics-monitoring-url="deployment.metrics_monitoring_url"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,14 @@ import MRWidgetService from '../services/mr_widget_service';
|
|||
export default {
|
||||
name: 'MemoryUsage',
|
||||
props: {
|
||||
metricsUrl: { type: String, required: true },
|
||||
metricsUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
metricsMonitoringUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -124,7 +131,7 @@ export default {
|
|||
<p
|
||||
v-if="shouldShowMemoryGraph"
|
||||
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
|
||||
v-if="shouldShowLoadFailure"
|
||||
|
|
|
@ -21,6 +21,11 @@ header.navbar-gitlab-new {
|
|||
padding-right: 0;
|
||||
color: currentColor;
|
||||
|
||||
img {
|
||||
height: 28px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
> a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -211,6 +211,10 @@
|
|||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
&.affix-top .issuable-sidebar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.right-sidebar-expanded {
|
||||
width: $gutter_width;
|
||||
|
||||
|
|
|
@ -597,7 +597,7 @@
|
|||
}
|
||||
|
||||
// Dropdown button in mini pipeline graph
|
||||
.mini-pipeline-graph-dropdown-toggle {
|
||||
button.mini-pipeline-graph-dropdown-toggle {
|
||||
border-radius: 100px;
|
||||
background-color: $white-light;
|
||||
border-width: 1px;
|
||||
|
@ -608,6 +608,7 @@
|
|||
padding: 0;
|
||||
transition: all 0.2s linear;
|
||||
position: relative;
|
||||
vertical-align: middle;
|
||||
|
||||
> .fa.fa-caret-down {
|
||||
position: absolute;
|
||||
|
|
|
@ -76,11 +76,11 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
params.delete(:domain_blacklist_raw) if params[:domain_blacklist_file]
|
||||
|
||||
params.require(:application_setting).permit(
|
||||
application_setting_params_ce
|
||||
application_setting_params_attributes
|
||||
)
|
||||
end
|
||||
|
||||
def application_setting_params_ce
|
||||
def application_setting_params_attributes
|
||||
[
|
||||
:admin_notification_email,
|
||||
:after_sign_out_path,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Admin::DashboardController < Admin::ApplicationController
|
||||
def index
|
||||
@projects = Project.with_route.limit(10)
|
||||
@projects = Project.without_deleted.with_route.limit(10)
|
||||
@users = User.limit(10)
|
||||
@groups = Group.with_route.limit(10)
|
||||
end
|
||||
|
|
|
@ -22,6 +22,7 @@ class Projects::ApplicationController < ApplicationController
|
|||
|
||||
def project
|
||||
return @project if @project
|
||||
return nil unless params[:project_id] || params[:id]
|
||||
|
||||
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
|
||||
auth_proc = ->(project) { !project.pending_delete? }
|
||||
|
|
|
@ -223,12 +223,18 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
if can?(current_user, :read_environment, environment) && environment.has_metrics?
|
||||
metrics_project_environment_deployment_path(environment.project, environment, deployment)
|
||||
end
|
||||
|
||||
metrics_monitoring_url =
|
||||
if can?(current_user, :read_environment, environment)
|
||||
environment_metrics_path(environment)
|
||||
end
|
||||
|
||||
{
|
||||
id: environment.id,
|
||||
name: environment.name,
|
||||
url: project_environment_path(project, environment),
|
||||
metrics_url: metrics_url,
|
||||
metrics_monitoring_url: metrics_monitoring_url,
|
||||
stop_url: stop_url,
|
||||
external_url: environment.external_url,
|
||||
external_url_formatted: environment.formatted_external_url,
|
||||
|
|
|
@ -296,10 +296,10 @@ class ProjectsController < Projects::ApplicationController
|
|||
|
||||
def project_params
|
||||
params.require(:project)
|
||||
.permit(project_params_ce)
|
||||
.permit(project_params_attributes)
|
||||
end
|
||||
|
||||
def project_params_ce
|
||||
def project_params_attributes
|
||||
[
|
||||
:avatar,
|
||||
:build_allow_git_fetch,
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# group_id: integer
|
||||
# project_id: integer
|
||||
# milestone_title: string
|
||||
# author_id: integer
|
||||
# assignee_id: integer
|
||||
# search: string
|
||||
# label_name: string
|
||||
|
|
|
@ -18,7 +18,8 @@ module SystemNoteHelper
|
|||
'milestone' => 'icon_clock_o',
|
||||
'discussion' => 'icon_comment_o',
|
||||
'moved' => 'icon_arrow_circle_o_right',
|
||||
'outdated' => 'icon_edit'
|
||||
'outdated' => 'icon_edit',
|
||||
'duplicate' => 'icon_clone'
|
||||
}.freeze
|
||||
|
||||
def icon_for_system_note(note)
|
||||
|
|
|
@ -21,7 +21,7 @@ module Ci
|
|||
has_many :merge_requests, foreign_key: "head_pipeline_id"
|
||||
|
||||
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 :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'
|
||||
|
|
|
@ -40,10 +40,6 @@ module Ci
|
|||
update_attribute(:active, false)
|
||||
end
|
||||
|
||||
def runnable_by_owner?
|
||||
Ability.allowed?(owner, :create_pipeline, project)
|
||||
end
|
||||
|
||||
def set_next_run_at
|
||||
self.next_run_at = Gitlab::Ci::CronParser.new(cron, cron_timezone).next_time_from(Time.now)
|
||||
end
|
||||
|
|
|
@ -17,7 +17,13 @@ module ProtectedRef
|
|||
class_methods do
|
||||
def protected_ref_access_levels(*types)
|
||||
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}." }
|
||||
|
||||
|
@ -25,8 +31,8 @@ module ProtectedRef
|
|||
end
|
||||
end
|
||||
|
||||
def protected_ref_accessible_to?(ref, user, action:)
|
||||
access_levels_for_ref(ref, action: action).any? do |access_level|
|
||||
def protected_ref_accessible_to?(ref, user, action:, protected_refs: nil)
|
||||
access_levels_for_ref(ref, action: action, protected_refs: protected_refs).any? do |access_level|
|
||||
access_level.check_access(user)
|
||||
end
|
||||
end
|
||||
|
@ -37,8 +43,9 @@ module ProtectedRef
|
|||
end
|
||||
end
|
||||
|
||||
def access_levels_for_ref(ref, action:)
|
||||
self.matching(ref).map(&:"#{action}_access_levels").flatten
|
||||
def access_levels_for_ref(ref, action:, protected_refs: nil)
|
||||
self.matching(ref, protected_refs: protected_refs)
|
||||
.map(&:"#{action}_access_levels").flatten
|
||||
end
|
||||
|
||||
def matching(ref_name, protected_refs: nil)
|
||||
|
|
|
@ -236,10 +236,21 @@ class MergeRequestDiff < ActiveRecord::Base
|
|||
|
||||
def create_merge_request_diff_files(diffs)
|
||||
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,
|
||||
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
|
||||
|
||||
Gitlab::Database.bulk_insert('merge_request_diff_files', rows)
|
||||
|
@ -268,9 +279,7 @@ class MergeRequestDiff < ActiveRecord::Base
|
|||
st_diffs
|
||||
end
|
||||
elsif merge_request_diff_files.present?
|
||||
merge_request_diff_files
|
||||
.as_json(only: Gitlab::Git::Diff::SERIALIZE_KEYS)
|
||||
.map(&:with_indifferent_access)
|
||||
merge_request_diff_files.map(&:to_hash)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,4 +8,14 @@ class MergeRequestDiffFile < ActiveRecord::Base
|
|||
|
||||
encode_utf8(diff) if diff.respond_to?(:encoding)
|
||||
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
|
||||
|
|
|
@ -3,10 +3,8 @@ class JiraService < IssueTrackerService
|
|||
|
||||
validates :url, url: true, presence: true, if: :activated?
|
||||
validates :api_url, url: true, allow_blank: true
|
||||
validates :project_key, presence: true, if: :activated?
|
||||
|
||||
prop_accessor :username, :password, :url, :api_url, :project_key,
|
||||
:jira_issue_transition_id, :title, :description
|
||||
prop_accessor :username, :password, :url, :api_url, :jira_issue_transition_id, :title, :description
|
||||
|
||||
before_update :reset_password
|
||||
|
||||
|
@ -54,10 +52,6 @@ class JiraService < IssueTrackerService
|
|||
@client ||= JIRA::Client.new(options)
|
||||
end
|
||||
|
||||
def jira_project
|
||||
@jira_project ||= jira_request { client.Project.find(project_key) }
|
||||
end
|
||||
|
||||
def help
|
||||
"You need to configure JIRA before enabling this service. For more details
|
||||
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: '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: '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
|
||||
|
||||
# URLs to redirect from Gitlab issues pages to jira issue tracker
|
||||
def project_url
|
||||
"#{url}/issues/?jql=project=#{project_key}"
|
||||
end
|
||||
|
||||
def issues_url
|
||||
"#{url}/browse/:id"
|
||||
end
|
||||
|
@ -184,7 +172,7 @@ class JiraService < IssueTrackerService
|
|||
def test_settings
|
||||
return unless client_url.present?
|
||||
# Test settings by getting the project
|
||||
jira_request { jira_project.present? }
|
||||
jira_request { client.ServerInfo.all.attrs }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -471,8 +471,17 @@ class Repository
|
|||
end
|
||||
cache_method :root_ref
|
||||
|
||||
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/314
|
||||
def exists?
|
||||
refs_directory_exists?
|
||||
return false unless path_with_namespace
|
||||
|
||||
Gitlab::GitalyClient.migrate(:repository_exists) do |enabled|
|
||||
if enabled
|
||||
raw_repository.exists?
|
||||
else
|
||||
refs_directory_exists?
|
||||
end
|
||||
end
|
||||
end
|
||||
cache_method :exists?
|
||||
|
||||
|
@ -1095,8 +1104,6 @@ class Repository
|
|||
end
|
||||
|
||||
def refs_directory_exists?
|
||||
return false unless path_with_namespace
|
||||
|
||||
File.exist?(File.join(path_to_repo, 'refs'))
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
class SystemNoteMetadata < ActiveRecord::Base
|
||||
ICON_TYPES = %w[
|
||||
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
|
||||
].freeze
|
||||
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
module Ci
|
||||
class BuildPolicy < CommitStatusPolicy
|
||||
condition(:protected_action) do
|
||||
next false unless @subject.action?
|
||||
|
||||
condition(:protected_ref) do
|
||||
access = ::Gitlab::UserAccess.new(@user, project: @subject.project)
|
||||
|
||||
if @subject.tag?
|
||||
!access.can_create_tag?(@subject.ref)
|
||||
else
|
||||
!access.can_merge_to_branch?(@subject.ref)
|
||||
!access.can_update_branch?(@subject.ref)
|
||||
end
|
||||
end
|
||||
|
||||
rule { protected_action }.prevent :update_build
|
||||
rule { protected_ref }.prevent :update_build
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
module Ci
|
||||
class PipelinePolicy < BasePolicy
|
||||
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
|
||||
|
|
|
@ -44,7 +44,7 @@ class GlobalPolicy < BasePolicy
|
|||
prevent :log_in
|
||||
end
|
||||
|
||||
rule { ~restricted_public_level }.policy do
|
||||
rule { admin | ~restricted_public_level }.policy do
|
||||
enable :read_users_list
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,8 @@ class BuildDetailsEntity < JobEntity
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ class DeployKeyEntity < Grape::Entity
|
|||
expose :created_at
|
||||
expose :updated_at
|
||||
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
|
||||
expose :can_edit
|
||||
|
||||
|
|
|
@ -15,12 +15,40 @@ module Ci
|
|||
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?
|
||||
return error('Pipeline is disabled')
|
||||
end
|
||||
|
||||
unless trigger_request || can?(current_user, :create_pipeline, project)
|
||||
return error('Insufficient permissions to create a new pipeline')
|
||||
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')
|
||||
end
|
||||
end
|
||||
|
||||
unless branch? || tag?
|
||||
|
@ -46,23 +74,28 @@ module Ci
|
|||
unless pipeline.has_stage_seeds?
|
||||
return error('No stages / jobs for this pipeline.')
|
||||
end
|
||||
|
||||
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 allowed_to_trigger_pipeline?(triggering_user)
|
||||
if triggering_user
|
||||
allowed_to_create?(triggering_user)
|
||||
else # legacy triggers don't have a corresponding user
|
||||
!project.protected_for?(ref)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
return unless pipeline.latest?
|
||||
|
@ -113,15 +146,21 @@ module Ci
|
|||
end
|
||||
|
||||
def branch?
|
||||
project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref)
|
||||
return @is_branch if defined?(@is_branch)
|
||||
|
||||
@is_branch =
|
||||
project.repository.ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + ref)
|
||||
end
|
||||
|
||||
def tag?
|
||||
project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref)
|
||||
return @is_tag if defined?(@is_tag)
|
||||
|
||||
@is_tag =
|
||||
project.repository.ref_exists?(Gitlab::Git::TAG_REF_PREFIX + ref)
|
||||
end
|
||||
|
||||
def ref
|
||||
Gitlab::Git.ref_name(origin_ref)
|
||||
@ref ||= Gitlab::Git.ref_name(origin_ref)
|
||||
end
|
||||
|
||||
def valid_sha?
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
module Ci
|
||||
class CreateTriggerRequestService
|
||||
def execute(project, trigger, ref, variables = nil)
|
||||
module CreateTriggerRequestService
|
||||
Result = Struct.new(:trigger_request, :pipeline)
|
||||
|
||||
def self.execute(project, trigger, ref, variables = nil)
|
||||
trigger_request = trigger.trigger_requests.create(variables: variables)
|
||||
|
||||
pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref)
|
||||
.execute(:trigger, ignore_skip_ci: true, trigger_request: trigger_request)
|
||||
|
||||
trigger_request if pipeline.persisted?
|
||||
Result.new(trigger_request, pipeline)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -58,6 +58,7 @@ class IssuableBaseService < BaseService
|
|||
params.delete(:assignee_ids)
|
||||
params.delete(:assignee_id)
|
||||
params.delete(:due_date)
|
||||
params.delete(:canonical_issue_id)
|
||||
end
|
||||
|
||||
filter_assignee(issuable)
|
||||
|
|
|
@ -7,6 +7,14 @@ module Issues
|
|||
issue_data
|
||||
end
|
||||
|
||||
def reopen_service
|
||||
Issues::ReopenService
|
||||
end
|
||||
|
||||
def close_service
|
||||
Issues::CloseService
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
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)
|
||||
handle_move_between_iids(issue)
|
||||
filter_spam_check_params
|
||||
change_issue_duplicate(issue)
|
||||
update(issue)
|
||||
end
|
||||
|
||||
|
@ -53,14 +54,6 @@ module Issues
|
|||
end
|
||||
end
|
||||
|
||||
def reopen_service
|
||||
Issues::ReopenService
|
||||
end
|
||||
|
||||
def close_service
|
||||
Issues::CloseService
|
||||
end
|
||||
|
||||
def handle_move_between_iids(issue)
|
||||
return unless params[:move_between_iids]
|
||||
|
||||
|
@ -72,6 +65,15 @@ module Issues
|
|||
issue.move_between(issue_before, issue_after)
|
||||
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
|
||||
|
||||
def get_issue_if_allowed(project, iid)
|
||||
|
|
|
@ -15,40 +15,48 @@ module Projects
|
|||
def execute
|
||||
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_
|
||||
# removing the physical repositories as some expiration code depends on
|
||||
# Git data (e.g. a list of branch names).
|
||||
flush_caches(project, wiki_path)
|
||||
flush_caches(project)
|
||||
|
||||
Projects::UnlinkForkService.new(project, current_user).execute
|
||||
|
||||
Project.transaction do
|
||||
project.team.truncate
|
||||
project.destroy!
|
||||
attempt_destroy_transaction(project)
|
||||
|
||||
unless remove_legacy_registry_tags
|
||||
raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.')
|
||||
end
|
||||
|
||||
unless remove_repository(repo_path)
|
||||
raise_error('Failed to remove project repository. Please try again or contact administrator.')
|
||||
end
|
||||
|
||||
unless remove_repository(wiki_path)
|
||||
raise_error('Failed to remove wiki repository. Please try again or contact administrator.')
|
||||
end
|
||||
end
|
||||
|
||||
log_info("Project \"#{project.path_with_namespace}\" was removed")
|
||||
system_hook_service.execute_hooks_for(project, :destroy)
|
||||
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
|
||||
|
||||
private
|
||||
|
||||
def repo_path
|
||||
project.path_with_namespace
|
||||
end
|
||||
|
||||
def wiki_path
|
||||
repo_path + '.wiki'
|
||||
end
|
||||
|
||||
def trash_repositories!
|
||||
unless remove_repository(repo_path)
|
||||
raise_error('Failed to remove project repository. Please try again or contact administrator.')
|
||||
end
|
||||
|
||||
unless remove_repository(wiki_path)
|
||||
raise_error('Failed to remove wiki repository. Please try again or contact administrator.')
|
||||
end
|
||||
end
|
||||
|
||||
def remove_repository(path)
|
||||
# Skip repository removal. We use this flag when remove user or group
|
||||
return true if params[:skip_repo] == true
|
||||
|
@ -70,6 +78,26 @@ module Projects
|
|||
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
|
||||
# for legacy image repository (when repository path equals project path).
|
||||
|
@ -96,7 +124,7 @@ module Projects
|
|||
"#{path}+#{project.id}#{DELETED_FLAG}"
|
||||
end
|
||||
|
||||
def flush_caches(project, wiki_path)
|
||||
def flush_caches(project)
|
||||
project.repository.before_delete
|
||||
|
||||
Repository.new(wiki_path, project).before_delete
|
||||
|
|
|
@ -130,7 +130,11 @@ module Projects
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
def tmp_path
|
||||
|
|
|
@ -471,6 +471,24 @@ module QuickActions
|
|||
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)
|
||||
return [] if params.nil?
|
||||
|
||||
|
|
|
@ -552,6 +552,44 @@ module SystemNoteService
|
|||
create_note(NoteSummary.new(noteable, project, author, body, action: 'moved'))
|
||||
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
|
||||
|
||||
def notes_for_mentioner(mentioner, noteable, notes)
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
.well-segment.well-centered
|
||||
= link_to admin_groups_path do
|
||||
%h3.text-center
|
||||
Groups
|
||||
Groups:
|
||||
= number_with_delimiter(Group.count)
|
||||
%hr
|
||||
= 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
|
||||
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
|
||||
|
||||
= content_for flash_message_container do
|
||||
- if current_user && can?(current_user, :download_code, @project)
|
||||
= render 'shared/no_ssh'
|
||||
= render 'shared/no_password'
|
||||
= render partial: 'flash_messages', locals: { project: @project }
|
||||
|
||||
= render "projects/head"
|
||||
= render "home_panel"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
- @no_container = true
|
||||
- page_title "Labels"
|
||||
- hide_class = ''
|
||||
- can_admin_label = can?(current_user, :admin_label, @project)
|
||||
|
||||
- if show_new_nav? && can?(current_user, :admin_label, @project)
|
||||
- content_for :breadcrumbs_extra do
|
||||
|
@ -12,15 +13,17 @@
|
|||
%div{ class: container_class }
|
||||
.top-area.adjust
|
||||
.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.
|
||||
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
- if can?(current_user, :admin_label, @project)
|
||||
- if can_admin_label
|
||||
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
|
||||
= link_to new_project_label_path(@project), class: "btn btn-new" do
|
||||
New label
|
||||
|
||||
.labels
|
||||
- if can?(current_user, :admin_label, @project)
|
||||
- if can_admin_label
|
||||
-# Only show it in the first page
|
||||
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
|
||||
.prioritized-labels{ class: ('hide' if hide) }
|
||||
|
@ -33,7 +36,7 @@
|
|||
|
||||
- if @labels.present?
|
||||
.other-labels
|
||||
- if can?(current_user, :admin_label, @project)
|
||||
- if can_admin_label
|
||||
%h5{ class: ('hide' if hide) } Other Labels
|
||||
%ul.content-list.manage-labels-list.js-other-labels
|
||||
= 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|
|
||||
.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
|
||||
.panel.panel-default.panel-new-merge-request
|
||||
.panel-heading
|
||||
|
@ -66,10 +66,3 @@
|
|||
- if @merge_request.errors.any?
|
||||
= form_errors(@merge_request)
|
||||
= 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_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?
|
||||
.commits-empty
|
||||
%h4
|
||||
|
@ -50,8 +50,3 @@
|
|||
|
||||
.mr-loading-status
|
||||
= spinner
|
||||
|
||||
:javascript
|
||||
var merge_request = new MergeRequest({
|
||||
action: "#{j params[:tab].presence || 'new'}",
|
||||
});
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
- page_description @merge_request.description
|
||||
- page_card_attributes @merge_request.card_attributes
|
||||
- content_for :page_specific_javascripts do
|
||||
= page_specific_javascript_bundle_tag('common_vue')
|
||||
= page_specific_javascript_bundle_tag('diff_notes')
|
||||
= webpack_bundle_tag('common_vue')
|
||||
= 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"
|
||||
|
||||
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
|
||||
|
@ -15,13 +15,13 @@
|
|||
- if @merge_request.source_branch_exists?
|
||||
= render "projects/merge_requests/how_to_merge"
|
||||
|
||||
-# haml-lint:disable InlineJavaScript
|
||||
:javascript
|
||||
window.gl.mrWidgetData = #{serialize_issuable(@merge_request)}
|
||||
|
||||
#js-vue-mr-widget.mr-widget
|
||||
|
||||
- content_for :page_specific_javascripts do
|
||||
= webpack_bundle_tag 'common_vue'
|
||||
= webpack_bundle_tag 'vue_merge_request_widget'
|
||||
|
||||
.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
|
||||
- if @merge_request.can_be_cherry_picked?
|
||||
= 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
|
||||
- if fogbugz_import_enabled?
|
||||
= link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
|
||||
= icon('bug', text: 'Fogbugz')
|
||||
= icon('bug', text: 'FogBugz')
|
||||
%div
|
||||
- if gitea_import_enabled?
|
||||
= link_to new_import_gitea_url, class: 'btn import_gitea' do
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
- @no_container = true
|
||||
- breadcrumb_title "Project"
|
||||
- @content_class = "limit-container-width" unless fluid_layout
|
||||
- flash_message_container = show_new_nav? ? :new_global_flash : :flash_message
|
||||
|
||||
= content_for :meta_tags do
|
||||
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
|
||||
|
||||
= content_for flash_message_container do
|
||||
- if current_user && can?(current_user, :download_code, @project)
|
||||
= render 'shared/no_ssh'
|
||||
= render 'shared/no_password'
|
||||
= render partial: 'flash_messages', locals: { project: @project }
|
||||
|
||||
= render "projects/head"
|
||||
= render "projects/last_push"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
- if @projects.any?
|
||||
.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]
|
||||
%a.btn.btn-new.new-project-item-select-button{ data: { relative_path: local_assigns[:path] } }
|
||||
= 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
|
||||
= local_assigns[:label]
|
||||
= 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
|
||||
= image_tag avatar_icon(user, 32), class: "avatar s32"
|
||||
%strong= truncate(user.name, length: 40)
|
||||
%br
|
||||
%small.cgray= user.username
|
||||
%div
|
||||
%small.cgray= user.username
|
||||
|
|
|
@ -6,15 +6,12 @@ class PipelineScheduleWorker
|
|||
Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now)
|
||||
.preload(:owner, :project).find_each do |schedule|
|
||||
begin
|
||||
unless schedule.runnable_by_owner?
|
||||
schedule.deactivate!
|
||||
next
|
||||
end
|
||||
|
||||
Ci::CreatePipelineService.new(schedule.project,
|
||||
schedule.owner,
|
||||
ref: schedule.ref)
|
||||
pipeline = Ci::CreatePipelineService.new(schedule.project,
|
||||
schedule.owner,
|
||||
ref: schedule.ref)
|
||||
.execute(:schedule, save_on_errors: false, schedule: schedule)
|
||||
|
||||
schedule.deactivate! unless pipeline.persisted?
|
||||
rescue => e
|
||||
Rails.logger.error "#{schedule.id}: Failed to create a scheduled pipeline: #{e.message}"
|
||||
ensure
|
||||
|
|
|
@ -3,14 +3,11 @@ class ProjectDestroyWorker
|
|||
include DedicatedSidekiqQueue
|
||||
|
||||
def perform(project_id, user_id, params)
|
||||
begin
|
||||
project = Project.unscoped.find(project_id)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
return
|
||||
end
|
||||
|
||||
project = Project.find(project_id)
|
||||
user = User.find(user_id)
|
||||
|
||||
::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
|
||||
|
|
|
@ -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
|
||||
# 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
|
||||
ldap:
|
||||
enabled: false
|
||||
|
@ -251,13 +252,45 @@ production: &base
|
|||
# Example: 'Paris' or 'Acme, Ltd.'
|
||||
label: 'LDAP'
|
||||
|
||||
# Example: 'ldap.mydomain.com'
|
||||
host: '_your_ldap_server'
|
||||
port: 389
|
||||
uid: 'sAMAccountName'
|
||||
method: 'plain' # "tls" or "ssl" or "plain"
|
||||
# This port is an example, it is sometimes different but it is always an integer and not a string
|
||||
port: 389 # usually 636 for SSL
|
||||
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'
|
||||
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
|
||||
# a request if the LDAP server becomes unresponsive.
|
||||
# A value of 0 means there is no timeout.
|
||||
|
@ -286,17 +319,20 @@ production: &base
|
|||
|
||||
# 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: ''
|
||||
|
||||
# Filter LDAP users
|
||||
#
|
||||
# Format: RFC 4515 http://tools.ietf.org/search/rfc4515
|
||||
# Format: RFC 4515 https://tools.ietf.org/search/rfc4515
|
||||
# Ex. (employeeType=developer)
|
||||
#
|
||||
# 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: ''
|
||||
|
||||
# LDAP attributes that GitLab will use to create an account for the LDAP user.
|
||||
|
@ -674,7 +710,7 @@ test:
|
|||
host: 127.0.0.1
|
||||
port: 3890
|
||||
uid: 'uid'
|
||||
method: 'plain' # "tls" or "ssl" or "plain"
|
||||
encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
|
||||
base: 'dc=example,dc=com'
|
||||
user_filter: ''
|
||||
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['provider_name'] ||= "ldap#{key}".downcase
|
||||
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
|
||||
|
||||
|
@ -441,10 +459,6 @@ Settings.backup['pg_schema'] = nil
|
|||
Settings.backup['path'] = Settings.absolute(Settings.backup['path'] || "tmp/backups/")
|
||||
Settings.backup['archive_permissions'] ||= 0600
|
||||
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']['encryption'] ||= nil
|
||||
Settings.backup['upload']['storage_class'] ||= nil
|
||||
|
|
|
@ -6,7 +6,7 @@ Prometheus::Client.configure do |config|
|
|||
config.initial_mmap_file_size = 4 * 1024
|
||||
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')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -114,6 +114,9 @@ def instrument_classes(instrumentation)
|
|||
# This is a Rails scope so we have to instrument it manually.
|
||||
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
|
||||
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
|
||||
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)
|
||||
OmniAuth.config.allowed_request_methods << :get if Gitlab.config.omniauth.auto_sign_in_with_provider.present?
|
||||
OmniAuth.config.before_request_phase do |env|
|
||||
OmniAuth::RequestForgeryProtection.call(env)
|
||||
Gitlab::RequestForgeryProtection.call(env)
|
||||
end
|
||||
|
||||
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