Commit c285f350 authored by Rémy Coutable's avatar Rémy Coutable

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2017-07-26

# Conflicts:
#	Gemfile
#	Gemfile.lock
#	app/assets/stylesheets/pages/pipelines.scss
#	app/helpers/system_note_helper.rb
#	app/services/ci/create_pipeline_service.rb
#	app/services/system_note_service.rb
#	doc/api/issues.md
#	doc/articles/index.md
#	doc/integration/README.md
#	doc/user/project/quick_actions.md
#	lib/api/helpers/related_resources_helpers.rb
#	lib/api/triggers.rb
#	lib/api/v3/entities.rb
#	spec/controllers/admin/dashboard_controller_spec.rb
#	spec/features/issues/user_uses_slash_commands_spec.rb
#	spec/requests/api/triggers_spec.rb
#	spec/serializers/pipeline_serializer_spec.rb
#	spec/services/quick_actions/interpret_service_spec.rb
#	spec/support/api/milestones_shared_examples.rb
#	spec/support/stub_configuration.rb
[ci skip]
parents 248ddf26 1a2b92f7
...@@ -115,8 +115,8 @@ scheduling into milestones. Labelling is a task for everyone. ...@@ -115,8 +115,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
...@@ -279,7 +279,7 @@ For feature proposals for EE, open an issue on the ...@@ -279,7 +279,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
......
...@@ -65,7 +65,10 @@ gem 'browser', '~> 2.2' ...@@ -65,7 +65,10 @@ gem 'browser', '~> 2.2'
# 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', '~> 2.0.3', require: 'omniauth-ldap' gem 'gitlab_omniauth-ldap', '~> 2.0.3', require: 'omniauth-ldap'
<<<<<<< HEAD
gem 'net-ldap' gem 'net-ldap'
=======
>>>>>>> upstream/master
# 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
...@@ -176,7 +179,7 @@ gem 'rainbow', '~> 2.2' ...@@ -176,7 +179,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
...@@ -367,7 +370,7 @@ group :development, :test do ...@@ -367,7 +370,7 @@ group :development, :test do
end end
group :test do group :test do
gem 'shoulda-matchers', '~> 2.8.0', require: false gem 'shoulda-matchers', '~> 3.1.2', require: false
gem 'email_spec', '~> 1.6.0' gem 'email_spec', '~> 1.6.0'
gem 'json-schema', '~> 2.6.2' gem 'json-schema', '~> 2.6.2'
gem 'webmock', '~> 2.3.2' gem 'webmock', '~> 2.3.2'
......
...@@ -500,7 +500,10 @@ GEM ...@@ -500,7 +500,10 @@ GEM
mustermann (~> 1.0.0) mustermann (~> 1.0.0)
mysql2 (0.4.5) mysql2 (0.4.5)
net-ldap (0.16.0) net-ldap (0.16.0)
<<<<<<< HEAD
net-ntp (2.1.3) net-ntp (2.1.3)
=======
>>>>>>> upstream/master
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)
...@@ -689,7 +692,7 @@ GEM ...@@ -689,7 +692,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)
...@@ -807,8 +810,8 @@ GEM ...@@ -807,8 +810,8 @@ GEM
sexp_processor (4.9.0) sexp_processor (4.9.0)
sham_rack (1.3.6) sham_rack (1.3.6)
rack rack
shoulda-matchers (2.8.0) shoulda-matchers (3.1.2)
activesupport (>= 3.0.0) activesupport (>= 4.0.0)
sidekiq (5.0.4) sidekiq (5.0.4)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0) connection_pool (~> 2.2, >= 2.2.0)
...@@ -1020,7 +1023,10 @@ DEPENDENCIES ...@@ -1020,7 +1023,10 @@ DEPENDENCIES
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)
<<<<<<< HEAD
gssapi gssapi
=======
>>>>>>> upstream/master
grape-route-helpers (~> 2.0.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)
...@@ -1098,7 +1104,7 @@ DEPENDENCIES ...@@ -1098,7 +1104,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)
...@@ -1127,7 +1133,7 @@ DEPENDENCIES ...@@ -1127,7 +1133,7 @@ DEPENDENCIES
sentry-raven (~> 2.5.3) sentry-raven (~> 2.5.3)
settingslogic (~> 2.0.9) settingslogic (~> 2.0.9)
sham_rack (~> 1.3.6) sham_rack (~> 1.3.6)
shoulda-matchers (~> 2.8.0) shoulda-matchers (~> 3.1.2)
sidekiq (~> 5.0) sidekiq (~> 5.0)
sidekiq-cron (~> 0.6.0) sidekiq-cron (~> 0.6.0)
sidekiq-limit_fetch (~> 3.4) sidekiq-limit_fetch (~> 3.4)
......
...@@ -175,7 +175,7 @@ import Cookies from 'js-cookie'; ...@@ -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 { ...@@ -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'; ...@@ -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 { ...@@ -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"
......
...@@ -163,8 +163,18 @@ ...@@ -163,8 +163,18 @@
td.blame-commit { td.blame-commit {
padding: 5px 10px; padding: 5px 10px;
min-width: 400px; min-width: 400px;
max-width: 400px;
background: $gray-light; background: $gray-light;
border-left: 3px solid; border-left: 3px solid;
.commit-row-title {
display: flex;
}
.item-title {
flex: 1;
margin-right: 0.5em;
}
} }
@for $i from 0 through 5 { @for $i from 0 through 5 {
......
...@@ -21,6 +21,11 @@ header.navbar-gitlab-new { ...@@ -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;
......
...@@ -626,8 +626,12 @@ ...@@ -626,8 +626,12 @@
} }
// Dropdown button in mini pipeline graph // Dropdown button in mini pipeline graph
<<<<<<< HEAD
button.mini-pipeline-graph-dropdown-toggle, button.mini-pipeline-graph-dropdown-toggle,
a.linked-pipeline-mini-item { a.linked-pipeline-mini-item {
=======
button.mini-pipeline-graph-dropdown-toggle {
>>>>>>> upstream/master
border-radius: 100px; border-radius: 100px;
background-color: $white-light; background-color: $white-light;
border-width: 1px; border-width: 1px;
......
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)
@license = License.current @license = License.current
......
...@@ -227,11 +227,17 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -227,11 +227,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,
......
...@@ -19,11 +19,15 @@ module SystemNoteHelper ...@@ -19,11 +19,15 @@ module SystemNoteHelper
'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',
<<<<<<< HEAD
'duplicate' => 'icon_clone', 'duplicate' => 'icon_clone',
'approved' => 'icon_check', 'approved' => 'icon_check',
'unapproved' => 'icon_fa_close', 'unapproved' => 'icon_fa_close',
'relate' => 'icon_anchor', 'relate' => 'icon_anchor',
'unrelate' => 'icon_anchor_broken' 'unrelate' => 'icon_anchor_broken'
=======
'duplicate' => 'icon_clone'
>>>>>>> upstream/master
}.freeze }.freeze
def icon_for_system_note(note) def icon_for_system_note(note)
......
...@@ -33,7 +33,7 @@ module Ci ...@@ -33,7 +33,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 ...@@ -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
......
...@@ -31,8 +31,8 @@ module ProtectedRef ...@@ -31,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
...@@ -43,8 +43,9 @@ module ProtectedRef ...@@ -43,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)
......
...@@ -3,10 +3,8 @@ class JiraService < IssueTrackerService ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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
......
...@@ -478,9 +478,18 @@ class Repository ...@@ -478,9 +478,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
...@@ -1175,8 +1184,6 @@ class Repository ...@@ -1175,8 +1184,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
......
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
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 ...@@ -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 ...@@ -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 ...@@ -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,16 +15,49 @@ module Ci ...@@ -15,16 +15,49 @@ 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
<<<<<<< HEAD
unless project.mirror_trigger_builds? unless project.mirror_trigger_builds?
return error('Pipeline is disabled for mirror updates') if mirror_update return error('Pipeline is disabled for mirror updates') if mirror_update
end end
unless trigger_request || can?(current_user, :create_pipeline, project) unless trigger_request || can?(current_user, :create_pipeline, project)
return error('Insufficient permissions to create a new pipeline') 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
>>>>>>> upstream/master
end end
unless branch? || tag? unless branch? || tag?
...@@ -50,7 +83,9 @@ module Ci ...@@ -50,7 +83,9 @@ 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
end
<<<<<<< HEAD
_create_pipeline(source, &block) _create_pipeline(source, &block)
end end
...@@ -65,13 +100,27 @@ module Ci ...@@ -65,13 +100,27 @@ module Ci
Ci::CreatePipelineStagesService Ci::CreatePipelineStagesService
.new(project, current_user) .new(project, current_user)
.execute(pipeline) .execute(pipeline)
=======
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)
>>>>>>> upstream/master
end
end end
cancel_pending_pipelines if project.auto_cancel_pending_pipelines? def allowed_to_create?(triggering_user)
access = Gitlab::UserAccess.new(triggering_user, project: project)
pipeline_created_counter.increment(source: source)
pipeline.tap(&:process!) 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 end
def update_merge_requests_head_pipeline def update_merge_requests_head_pipeline
...@@ -123,15 +172,21 @@ module Ci ...@@ -123,15 +172,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?
......
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
...@@ -552,6 +552,7 @@ module SystemNoteService ...@@ -552,6 +552,7 @@ module SystemNoteService
create_note(NoteSummary.new(noteable, project, author, body, action: 'moved')) create_note(NoteSummary.new(noteable, project, author, body, action: 'moved'))
end end
<<<<<<< HEAD
# #
# noteable - Noteable object # noteable - Noteable object
# noteable_ref - Referenced noteable object # noteable_ref - Referenced noteable object
...@@ -606,6 +607,8 @@ module SystemNoteService ...@@ -606,6 +607,8 @@ module SystemNoteService
create_note(NoteSummary.new(noteable, noteable.project, user, body, action: 'unapproved')) create_note(NoteSummary.new(noteable, noteable.project, user, body, action: 'unapproved'))
end end
=======
>>>>>>> upstream/master
# Called when a Noteable has been marked as a duplicate of another Issue # Called when a Noteable has been marked as a duplicate of another Issue
# #
# noteable - Noteable object # noteable - Noteable object
......
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
.commit .commit
= author_avatar(commit, size: 36) = author_avatar(commit, size: 36)
.commit-row-title .commit-row-title
%strong %span.item-title.str-truncated-100
= link_to_gfm truncate(commit.title, length: 35), project_commit_path(@project, commit.id), class: "cdark" = link_to_gfm commit.title, project_commit_path(@project, commit.id), class: "cdark", title: commit.title
.pull-right .pull-right
= link_to commit.short_id, project_commit_path(@project, commit), class: "commit-sha" = link_to commit.short_id, project_commit_path(@project, commit), class: "commit-sha"
&nbsp; &nbsp;
......
- 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')
...@@ -6,15 +6,12 @@ class PipelineScheduleWorker ...@@ -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
......
---
title: Fix vertical alignment in firefox and safari for pipeline mini graph
merge_request:
author:
---
title: Disallow running the pipeline if ref is protected and user cannot merge the
branch or create the tag
merge_request: 11910
author:
---
title: Remove project_key from the Jira configuration
merge_request: 12050
author:
---
title: Added link to the MR widget that directs to the monitoring dashboard
merge_request:
author:
---
title: Use only CSS to truncate commit message in blame
merge_request: 12900
author: Takuya Noguchi
---
title: Add link to doc/api/ci/lint.md
merge_request: 12914
author: Takuya Noguchi
---
title: Pending delete projects should not show in deploy keys.
merge_request: 13088
author:
---
title: Fixes 500 error caused by pending delete projects in admin dashboard
merge_request: 13067
author:
---
title: Allow admin to read_users_list even if it's restricted
merge_request: 13066
author:
---
title: Add instrumentation to MarkupHelper#link_to_gfm
merge_request: 13069
author:
---
title: Free up some top level words, reject top level groups named like files in the
public folder
merge_request: 12932
author:
---
title: Fix job merge request link to a forked source project
merge_request: 12965
author:
---
title: Fix sizing of custom header logo in new navigation
merge_request:
author:
...@@ -136,6 +136,9 @@ def instrument_classes(instrumentation) ...@@ -136,6 +136,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
......
...@@ -11,15 +11,11 @@ self-hosted, free to use. Every feature available in GitLab CE is also available ...@@ -11,15 +11,11 @@ self-hosted, free to use. Every feature available in GitLab CE is also available
self-hosted, fully featured solution of GitLab, available under distinct [subscriptions](https://about.gitlab.com/products/): **GitLab Enterprise Edition Starter (EES)** and **GitLab Enterprise Edition Premium (EEP)**. self-hosted, fully featured solution of GitLab, available under distinct [subscriptions](https://about.gitlab.com/products/): **GitLab Enterprise Edition Starter (EES)** and **GitLab Enterprise Edition Premium (EEP)**.
- **GitLab.com**: SaaS GitLab solution, with [free and paid subscriptions](https://about.gitlab.com/gitlab-com/). GitLab.com is hosted by GitLab, Inc., and administrated by GitLab (users don't have access to admin settings). - **GitLab.com**: SaaS GitLab solution, with [free and paid subscriptions](https://about.gitlab.com/gitlab-com/). GitLab.com is hosted by GitLab, Inc., and administrated by GitLab (users don't have access to admin settings).
**GitLab EE** contains all features available in **GitLab CE**, > **GitLab EE** contains all features available in **GitLab CE**,
plus premium features available in each version: **Enterprise Edition Starter** plus premium features available in each version: **Enterprise Edition Starter**
(**EES**) and **Enterprise Edition Premium** (**EEP**). Everything available in (**EES**) and **Enterprise Edition Premium** (**EEP**). Everything available in
**EES** is also available in **EEP**. **EES** is also available in **EEP**.
**Note:** _We are unifying the documentation for CE and EE. To check if certain feature is
available in CE or EE, look for a note right below the page title containing the GitLab
version which introduced that feature._
---- ----
Shortcuts to GitLab's most visited docs: Shortcuts to GitLab's most visited docs:
...@@ -40,6 +36,7 @@ Shortcuts to GitLab's most visited docs: ...@@ -40,6 +36,7 @@ Shortcuts to GitLab's most visited docs:
### User account ### User account
- [User documentation](user/index.md)
- [Authentication](topics/authentication/index.md): Account security with two-factor authentication, setup your ssh keys and deploy keys for secure access to your projects. - [Authentication](topics/authentication/index.md): Account security with two-factor authentication, setup your ssh keys and deploy keys for secure access to your projects.
- [Profile settings](profile/README.md): Manage your profile settings, two factor authentication and more. - [Profile settings](profile/README.md): Manage your profile settings, two factor authentication and more.
- [User permissions](user/permissions.md): Learn what each role in a project (external/guest/reporter/developer/master/owner) can do. - [User permissions](user/permissions.md): Learn what each role in a project (external/guest/reporter/developer/master/owner) can do.
......
...@@ -465,23 +465,42 @@ on how to achieve that. ...@@ -465,23 +465,42 @@ on how to achieve that.
## Disable Container Registry but use GitLab as an auth endpoint ## Disable Container Registry but use GitLab as an auth endpoint
You can disable the embedded Container Registry to use an external one, but
still use GitLab as an auth endpoint.
**Omnibus GitLab** **Omnibus GitLab**
You can use GitLab as an auth endpoint and use a non-bundled Container Registry.
1. Open `/etc/gitlab/gitlab.rb` and set necessary configurations: 1. Open `/etc/gitlab/gitlab.rb` and set necessary configurations:
```ruby ```ruby
registry['enable'] = false
gitlab_rails['registry_enabled'] = true gitlab_rails['registry_enabled'] = true
gitlab_rails['registry_host'] = "registry.gitlab.example.com" gitlab_rails['registry_host'] = "registry.gitlab.example.com"
gitlab_rails['registry_port'] = "5005" gitlab_rails['registry_port'] = "5005"
gitlab_rails['registry_api_url'] = "http://localhost:5000" gitlab_rails['registry_api_url'] = "http://localhost:5000"
gitlab_rails['registry_key_path'] = "/var/opt/gitlab/gitlab-rails/certificate.key"
gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry" gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer" gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
``` ```
1. A certificate keypair is required for GitLab and the Container Registry to
communicate securely. By default omnibus-gitlab will generate one keypair,
which is saved to `/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key`.
When using an non-bundled Container Registry, you will need to supply a
custom certificate key. To do that, add the following to
`/etc/gitlab/gitlab.rb`
```ruby
gitlab_rails['registry_key_path'] = "/custom/path/to/registry-key.key"
# registry['internal_key'] should contain the contents of the custom key
# file. Line breaks in the key file should be marked using `\n` character
# Example:
registry['internal_key'] = "---BEGIN RSA PRIVATE KEY---\nMIIEpQIBAA\n"
```
**Note:** The file specified at `registry_key_path` gets populated with the
content specified by `internal_key`, each time reconfigure is executed. If
no file is specified, omnibus-gitlab will default it to
`/var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key` and will populate
it.
1. Save the file and [reconfigure GitLab][] for the changes to take effect. 1. Save the file and [reconfigure GitLab][] for the changes to take effect.
**Installations from source** **Installations from source**
......
...@@ -100,9 +100,12 @@ You can use the [alpha version of the document](alpha_database.md) to try it out ...@@ -100,9 +100,12 @@ You can use the [alpha version of the document](alpha_database.md) to try it out
Enter new password: Enter new password:
Enter it again: Enter it again:
``` ```
1. Exit from editing `template1` prompt by typing `\q` and Enter.
1. Enable the `pg_trgm` extension within the `gitlabhq_production` database:
1. Enable the `pg_trgm` extension:
``` ```
gitlab-psql -d gitlabhq_production
CREATE EXTENSION pg_trgm; CREATE EXTENSION pg_trgm;
# Output: # Output:
......
...@@ -47,3 +47,5 @@ Example responses: ...@@ -47,3 +47,5 @@ Example responses:
"error": "content is missing" "error": "content is missing"
} }
``` ```
[ce-5953]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5953
...@@ -360,7 +360,16 @@ Example response: ...@@ -360,7 +360,16 @@ Example response:
"due_date": null, "due_date": null,
"web_url": "http://example.com/example/example/issues/1", "web_url": "http://example.com/example/example/issues/1",
"confidential": false, "confidential": false,
<<<<<<< HEAD
"weight": null "weight": null
=======
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
}
>>>>>>> upstream/master
} }
``` ```
...@@ -424,7 +433,16 @@ Example response: ...@@ -424,7 +433,16 @@ Example response:
"due_date": null, "due_date": null,
"web_url": "http://example.com/example/example/issues/14", "web_url": "http://example.com/example/example/issues/14",
"confidential": false, "confidential": false,
<<<<<<< HEAD
"weight": null "weight": null
=======
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
}
>>>>>>> upstream/master
} }
``` ```
...@@ -489,7 +507,16 @@ Example response: ...@@ -489,7 +507,16 @@ Example response:
"due_date": "2016-07-22", "due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/15", "web_url": "http://example.com/example/example/issues/15",
"confidential": false, "confidential": false,
<<<<<<< HEAD
"weight": null "weight": null
=======
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
}
>>>>>>> upstream/master
} }
``` ```
...@@ -576,7 +603,16 @@ Example response: ...@@ -576,7 +603,16 @@ Example response:
"due_date": null, "due_date": null,
"web_url": "http://example.com/example/example/issues/11", "web_url": "http://example.com/example/example/issues/11",
"confidential": false, "confidential": false,
<<<<<<< HEAD
"weight": null "weight": null
=======
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
}
>>>>>>> upstream/master
} }
``` ```
...@@ -642,7 +678,16 @@ Example response: ...@@ -642,7 +678,16 @@ Example response:
"due_date": null, "due_date": null,
"web_url": "http://example.com/example/example/issues/11", "web_url": "http://example.com/example/example/issues/11",
"confidential": false, "confidential": false,
<<<<<<< HEAD
"weight": null "weight": null
=======
"_links": {
"self": "http://example.com/api/v4/projects/1/issues/2",
"notes": "http://example.com/api/v4/projects/1/issues/2/notes",
"award_emoji": "http://example.com/api/v4/projects/1/issues/2/award_emoji",
"project": "http://example.com/api/v4/projects/1"
}
>>>>>>> upstream/master
} }
``` ```
......
...@@ -100,7 +100,16 @@ Parameters: ...@@ -100,7 +100,16 @@ Parameters:
"repository_size": 1038090, "repository_size": 1038090,
"lfs_objects_size": 0, "lfs_objects_size": 0,
"job_artifacts_size": 0 "job_artifacts_size": 0
} },
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
},
}, },
{ {
"id": 6, "id": 6,
...@@ -170,6 +179,15 @@ Parameters: ...@@ -170,6 +179,15 @@ Parameters:
"repository_size": 2066080, "repository_size": 2066080,
"lfs_objects_size": 0, "lfs_objects_size": 0,
"job_artifacts_size": 0 "job_artifacts_size": 0
},
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
} }
} }
] ]
...@@ -259,6 +277,15 @@ Parameters: ...@@ -259,6 +277,15 @@ Parameters:
"repository_size": 1038090, "repository_size": 1038090,
"lfs_objects_size": 0, "lfs_objects_size": 0,
"job_artifacts_size": 0 "job_artifacts_size": 0
},
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
} }
}, },
{ {
...@@ -328,6 +355,15 @@ Parameters: ...@@ -328,6 +355,15 @@ Parameters:
"repository_size": 2066080, "repository_size": 2066080,
"lfs_objects_size": 0, "lfs_objects_size": 0,
"job_artifacts_size": 0 "job_artifacts_size": 0
},
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
} }
} }
] ]
...@@ -431,6 +467,15 @@ Parameters: ...@@ -431,6 +467,15 @@ Parameters:
"repository_size": 1038090, "repository_size": 1038090,
"lfs_objects_size": 0, "lfs_objects_size": 0,
"job_artifacts_size": 0 "job_artifacts_size": 0
},
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
} }
} }
``` ```
...@@ -669,7 +714,16 @@ Example response: ...@@ -669,7 +714,16 @@ Example response:
"shared_with_groups": [], "shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false "request_access_enabled": false,
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
}
} }
``` ```
...@@ -735,7 +789,16 @@ Example response: ...@@ -735,7 +789,16 @@ Example response:
"shared_with_groups": [], "shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false "request_access_enabled": false,
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
}
} }
``` ```
...@@ -819,7 +882,16 @@ Example response: ...@@ -819,7 +882,16 @@ Example response:
"shared_with_groups": [], "shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false "request_access_enabled": false,
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
}
} }
``` ```
...@@ -903,7 +975,16 @@ Example response: ...@@ -903,7 +975,16 @@ Example response:
"shared_with_groups": [], "shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false, "only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false, "only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false "request_access_enabled": false,
"_links": {
"self": "http://example.com/api/v4/projects",
"issues": "http://example.com/api/v4/projects/1/issues",
"merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
"repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
"labels": "http://example.com/api/v4/projects/1/labels",
"events": "http://example.com/api/v4/projects/1/events",
"members": "http://example.com/api/v4/projects/1/members"
}
} }
``` ```
......
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
Since GitLab 9.0, API V4 is the preferred version to be used. Since GitLab 9.0, API V4 is the preferred version to be used.
API V3 will be removed in GitLab 9.5, to be released on August 22, 2017. In the API V3 will be unsupported from GitLab 9.5, to be released on August
meantime, we advise you to make any necessary changes to applications that use 22, 2017. It will be removed in GitLab 9.5 or later. In the meantime, we advise
V3. The V3 API documentation is still [available](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/README.md). you to make any necessary changes to applications that use V3. The V3 API
documentation is still
[available](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-16-stable/doc/api/README.md).
Below are the changes made between V3 and V4. Below are the changes made between V3 and V4.
......
...@@ -11,7 +11,11 @@ They are written by members of the GitLab Team and by ...@@ -11,7 +11,11 @@ They are written by members of the GitLab Team and by
- **LDAP** - **LDAP**
- [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md) - [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md)
<<<<<<< HEAD
- [How to configure LDAP with GitLab EE](how_to_configure_ldap_gitlab_ee/index.md) - [How to configure LDAP with GitLab EE](how_to_configure_ldap_gitlab_ee/index.md)
=======
- [How to configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/)
>>>>>>> upstream/master
## Git ## Git
...@@ -24,3 +28,23 @@ They are written by members of the GitLab Team and by ...@@ -24,3 +28,23 @@ They are written by members of the GitLab Team and by
- [Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md) - [Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md)
- [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md) - [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md)
- [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md) - [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md)
- [Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/)
- [GitLab CI: Deployment & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
## Sofware development
- [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/)
- [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/)
- [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/)
- [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/)
- [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
## Build, test, and deploy with GitLab CI/CD
**Build, test, and deploy** the software you develop with **[GitLab CI/CD](../ci/README.md)**
- [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/)
- [Automated Debian Package Build with GitLab CI](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/)
- [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/)
- [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/)
- [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/)
...@@ -447,6 +447,7 @@ A forEach will cause side effects, it will be mutating the array being iterated. ...@@ -447,6 +447,7 @@ A forEach will cause side effects, it will be mutating the array being iterated.
1. `name` 1. `name`
1. `props` 1. `props`
1. `mixins` 1. `mixins`
1. `directives`
1. `data` 1. `data`
1. `components` 1. `components`
1. `computedProps` 1. `computedProps`
......
...@@ -5,21 +5,31 @@ trackers and external authentication. ...@@ -5,21 +5,31 @@ trackers and external authentication.
See the documentation below for details on how to configure these services. See the documentation below for details on how to configure these services.
- [JIRA](../user/project/integrations/jira.md) Integrate with the JIRA issue tracker - [Akismet](akismet.md) Configure Akismet to stop spam
- [Auth0 OmniAuth](auth0.md) Enable the Auth0 OmniAuth provider
- [Bitbucket](bitbucket.md) Import projects from Bitbucket.org and login to your GitLab instance with your
Bitbucket.org account
- [CAS](cas.md) Configure GitLab to sign in using CAS
- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc. - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
- [JIRA](../user/project/integrations/jira.md) Integrate with the JIRA issue tracker
- [Koding](../administration/integration/koding.md) Configure Koding to use IDE integration
- [LDAP](ldap.md) Set up sign in via LDAP - [LDAP](ldap.md) Set up sign in via LDAP
<<<<<<< HEAD
- [Jenkins](jenkins.md) Integrate with the Jenkins CI - [Jenkins](jenkins.md) Integrate with the Jenkins CI
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure and Authentiq ID - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure and Authentiq ID
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider - [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [CAS](cas.md) Configure GitLab to sign in using CAS - [CAS](cas.md) Configure GitLab to sign in using CAS
- [Kerberos](kerberos.md) Integrate with Kerberos - [Kerberos](kerberos.md) Integrate with Kerberos
=======
>>>>>>> upstream/master
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [OAuth2 provider](oauth_provider.md) OAuth2 application creation
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd, Azure and Authentiq ID
- [OpenID Connect](openid_connect_provider.md) Use GitLab as an identity provider - [OpenID Connect](openid_connect_provider.md) Use GitLab as an identity provider
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
- [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users
- [Akismet](akismet.md) Configure Akismet to stop spam
- [Koding](../administration/integration/koding.md) Configure Koding to use IDE integration
- [PlantUML](../administration/integration/plantuml.md) Configure PlantUML to use diagrams in AsciiDoc documents. - [PlantUML](../administration/integration/plantuml.md) Configure PlantUML to use diagrams in AsciiDoc documents.
- [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [Trello](trello_power_up.md) Integrate Trello with GitLab
> GitLab Enterprise Edition contains [advanced Jenkins support][jenkins]. > GitLab Enterprise Edition contains [advanced Jenkins support][jenkins].
......
# User documentation
Welcome to GitLab! We're glad to have you here!
As a GitLab user you'll have access to all the features
your [subscription](https://about.gitlab.com/products/)
includes, except [GitLab administrator](../README.md#administrator-documentation)
settings, unless you have admin privileges to install, configure,
and upgrade your GitLab instance.
For GitLab.com, admin privileges are restricted to the GitLab team.
If you run your own GitLab instance and are looking for the administration settings,
please refer to the [administration](../README.md#administrator-documentation)
documentation.
## Overview
GitLab is a fully integrated software development platform that enables you
and your team to work cohesively, faster, transparently, and effectively,
since the discussion of a new idea until taking that idea to production all
all the way through, from within the same platform.
Please check this page for an overview on [GitLab's features](https://about.gitlab.com/features/).
## Use cases
GitLab is a git-based platforms that integrates a great number of essential tools for software development and deployment, and project management:
- Code hosting in repositories with version control
- Track proposals for new implementations, bug reports, and feedback with a
fully featured [Issue Tracker](project/issues/index.md#issue-tracker)
- Organize and prioritize with [Issue Boards](project/issues/index.md#issue-boards)
- Code review in [Merge Requests](project/merge_requests/index.md) with live-preview changes per
branch with [Review Apps](../ci/review_apps/index.md)
- Build, test and deploy with built-in [Continuous Integration](../ci/README.md)
- Deploy your personal and professional static websites with [GitLab Pages](project/pages/index.md)
- Integrate with Docker with [GitLab Container Registry](project/container_registry.md)
- Track the development lifecycle with [GitLab Cycle Analytics](project/cycle_analytics.md)
With GitLab Enterprise Edition, you can also:
- Provide support with [Service Desk](https://docs.gitlab.com/ee/user/project/service_desk.html)
- Improve collaboration with
[Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/index.html#merge-request-approvals),
[Multiple Assignees for Issues](https://docs.gitlab.com/ee/user/project/issues/multiple_assignees_for_issues.html),
and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards)
- Create formal relashionships between issues with [Related Issues](https://docs.gitlab.com/ee/user/project/issues/related_issues.html)
- Use [Burndown Charts](https://docs.gitlab.com/ee/user/project/milestones/burndown_charts.html) to track progress during a sprint or while working on a new version of their software.
- Leverage [Elasticsearch](https://docs.gitlab.com/ee/integration/elasticsearch.html) with [Advanced Global Search](https://docs.gitlab.com/ee/user/search/advanced_global_search.html) and [Advanced Syntax Search](https://docs.gitlab.com/ee/user/search/advanced_search_syntax.html) for faster, more advanced code search across your entire GitLab instance
- [Authenticate users with Kerberos](https://docs.gitlab.com/ee/integration/kerberos.html)
- [Mirror a repository](https://docs.gitlab.com/ee/workflow/repository_mirroring.html) from elsewhere on your local server.
- [Export issues as CSV](https://docs.gitlab.com/ee/user/project/issues/csv_export.html)
- View your entire CI/CD pipeline involving more than one project with [Multiple-Project Pipeline Graphs](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
- [Lock files](https://docs.gitlab.com/ee/user/project/file_lock.html) to prevent conflicts
- View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](https://docs.gitlab.com/ee/user/project/deploy_boards.html)
- Leverage your continuous delivery method with [Canary Deployments](https://docs.gitlab.com/ee/user/project/canary_deployments.html)
You can also [integrate](project/integrations/project_services.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, JIRA, and a lot more.
### Articles
For a complete workflow use case please check [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario).
For more use cases please check our [Technical Articles](../articles/index.md).
## Projects
In GitLab, you can create projects for numerous reasons, such as, host
your code, use it as an issue tracker, collaborate on code, and continuously
build, test, and deploy your app with built-in GitLab CI/CD. Or, you can do
it all at once, from one single project.
### Issues
Explore the best of GitLab [Issues](project/issues/index.md).
### Merge Requests
Collanorate on code, gather reviews, live preview changes per branch, and
request approvals with [Merge Requests](project/merge_requests/index.md).
### Milestones
Work on multiple issues and merge requests towards the same target date
with [Milestones](project/milestones/index.md).
### GitLab Pages
Publish your static site directly from GitLab with [GitLab Pages](project/pages/index.md). You
can [build, test, and deploy any Static Site Generator](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) with Pages.
### Container Registry
Build and deploy Docker images with [GitLab Container Registry](project/container_registry.md).
## GitLab CI/CD
Use built-in [GitLab CI/CD](../ci/README.md) to test, build, and deploy your applications
directly from GitLab. No third-party integrations needed.
### Auto Deploy
Deploy your application out-of-the-box with [GitLab Auto Deploy](../ci/autodeploy/index.md).
### Review Apps
Live-preview the changes introduced by a merge request with [Review Apps](../ci/review_apps/index.md).
## Groups
With GitLab [Groups](group/index.md) you can assemble related projects together
and grant members access to several projects at once.
### Subgroups
Groups can also be nested in [subgroups](group/subgroups/index.md).
## Account
There is a lot you can customize and configure
to enjoy the best of GitLab.
Manage your user settings to change your personal info,
personal access tokens, authorized applications, integrations, etc.
### Authentication
Read through the [authentication](../topics/authentication/index.md) methods available in GitLab.
### Permissions
Learn the different set of [permissions](permissions.md) for user type (guest, reporter, developer, master, owner).
## Integrations
[Integrate GitLab](../integration/README.md) with your preferred tool,
such as Trello, JIRA, etc.
## Git and GitLab
Learn what is [Git](../topics/git/index.md) and its best practices.
## Discussions
In GitLab, you can comment and mention collaborators in issues,
merge requests, code snippets, and commits.
When performing inline reviews to implementations
to your codebase through merge requests you can
gather feedback through [resolvable discussions](discussions/index.md#resolvable-discussions).
## Todos
Never forget to reply to your collaborators. [GitLab Todos](../workflow/todos.md)
are a tool for working faster and more effectively with your team,
by listing all user or group mentions, as well as issues and merge
requests you're assigned to.
## Snippets
[Snippets](snippets.md) are code blocks that you want to store in GitLab, from which
you have quick access to. You can also gather feedback on them through
[discussions](#discussions).
## Webhooks
Configure [webhooks](project/integrations/webhooks.html) to listen for
specific events like pushes, issues or merge requests. GitLab will send a
POST request with data to the webhook URL.
## API
Automate GitLab via [API](../api/README.html).
...@@ -98,11 +98,11 @@ in the table below. ...@@ -98,11 +98,11 @@ in the table below.
| Field | Description | | Field | Description |
| ----- | ----------- | | ----- | ----------- |
| `Web URL` | The base URL to the JIRA instance web interface which is being linked to this GitLab project. E.g., `https://jira.example.com`. | | `Web URL` | The base URL to the JIRA instance web interface which is being linked to this GitLab project. E.g., `https://jira.example.com`. |
| `JIRA API URL` | The base URL to the JIRA instance API. E.g., `https://jira-api.example.com`. This is optional. If not entered, the Web URL value be used. | | `JIRA API URL` | The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., `https://jira-api.example.com`. |
| `Project key` | Put a JIRA project key (in uppercase), e.g. `MARS` in this field. This is only for testing the configuration settings. JIRA integration in GitLab works with _all_ JIRA projects in your JIRA instance. This field will be removed in a future release. | | `Project key` | Put a JIRA project key (in uppercase), e.g. `MARS` in this field. This is only for testing the configuration settings. JIRA integration in GitLab works with _all_ JIRA projects in your JIRA instance. This field will be removed in a future release. |
| `Username` | The user name created in [configuring JIRA step](#configuring-jira). | | `Username` | The user name created in [configuring JIRA step](#configuring-jira). |
| `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). | | `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). |
| `JIRA issue transition` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** | | `Transition ID` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** |
After saving the configuration, your GitLab project will be able to interact After saving the configuration, your GitLab project will be able to interact
with all JIRA projects in your JIRA instance. with all JIRA projects in your JIRA instance.
......
...@@ -71,9 +71,10 @@ The next time a pipeline is scheduled, your credentials will be used. ...@@ -71,9 +71,10 @@ The next time a pipeline is scheduled, your credentials will be used.
>**Note:** >**Note:**
When the owner of the schedule doesn't have the ability to create pipelines When the owner of the schedule doesn't have the ability to create pipelines
anymore, due to e.g., being blocked or removed from the project, the schedule anymore, due to e.g., being blocked or removed from the project, or lacking
is deactivated. Another user can take ownership and activate it, so the the permission to run on protected branches or tags. When this happened, the
schedule can be run again. schedule is deactivated. Another user can take ownership and activate it, so
the schedule can be run again.
## Advanced admin configuration ## Advanced admin configuration
......
...@@ -41,6 +41,9 @@ do. ...@@ -41,6 +41,9 @@ do.
| `/clear_weight` | Clears the issue weight | | `/clear_weight` | Clears the issue weight |
| `/board_move ~column` | Move issue to column on the board | | `/board_move ~column` | Move issue to column on the board |
| `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue | | `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue |
<<<<<<< HEAD
Note: In GitLab EES every issue can have more than one assignee, so commands `/assign`, `/unassign` and `/reassign` Note: In GitLab EES every issue can have more than one assignee, so commands `/assign`, `/unassign` and `/reassign`
support multiple assignees. support multiple assignees.
=======
>>>>>>> upstream/master
...@@ -175,7 +175,6 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps ...@@ -175,7 +175,6 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
fill_in 'JIRA API URL', with: 'http://jira.example/api' fill_in 'JIRA API URL', with: 'http://jira.example/api'
fill_in 'Username', with: 'gitlab' fill_in 'Username', with: 'gitlab'
fill_in 'Password', with: 'gitlab' fill_in 'Password', with: 'gitlab'
fill_in 'Project Key', with: 'GITLAB'
click_button 'Save' click_button 'Save'
end end
......
...@@ -13,7 +13,11 @@ module API ...@@ -13,7 +13,11 @@ module API
def expose_url(path) def expose_url(path)
url_options = Rails.application.routes.default_url_options url_options = Rails.application.routes.default_url_options
<<<<<<< HEAD
host, protocol, port = url_options.slice(:host, :protocol, :port).values host, protocol, port = url_options.slice(:host, :protocol, :port).values
=======
protocol, host, port = url_options.slice(:protocol, :host, :port).values
>>>>>>> upstream/master
URI::HTTP.build(scheme: protocol, host: host, port: port, path: path).to_s URI::HTTP.build(scheme: protocol, host: host, port: port, path: path).to_s
end end
......
...@@ -312,12 +312,6 @@ module API ...@@ -312,12 +312,6 @@ module API
type: String, type: String,
desc: 'The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., https://jira-api.example.com' desc: 'The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., https://jira-api.example.com'
}, },
{
required: true,
name: :project_key,
type: String,
desc: 'The short identifier for your JIRA project, all uppercase, e.g., PROJ'
},
{ {
required: false, required: false,
name: :username, name: :username,
......
...@@ -21,6 +21,7 @@ module API ...@@ -21,6 +21,7 @@ module API
render_api_error!('variables needs to be a map of key-valued strings', 400) render_api_error!('variables needs to be a map of key-valued strings', 400)
end end
<<<<<<< HEAD
project = find_project(params[:id]) project = find_project(params[:id])
not_found! unless project not_found! unless project
...@@ -31,6 +32,16 @@ module API ...@@ -31,6 +32,16 @@ module API
render_api_error!(result[:message], result[:http_status]) render_api_error!(result[:message], result[:http_status])
else else
present result[:pipeline], with: Entities::Pipeline present result[:pipeline], with: Entities::Pipeline
=======
# create request and trigger builds
result = Ci::CreateTriggerRequestService.execute(project, trigger, params[:ref].to_s, variables)
pipeline = result.pipeline
if pipeline.persisted?
present pipeline, with: Entities::Pipeline
else
render_validation_error!(pipeline)
>>>>>>> upstream/master
end end
end end
......
...@@ -294,7 +294,10 @@ module API ...@@ -294,7 +294,10 @@ module API
expose :upvotes, :downvotes expose :upvotes, :downvotes
expose :due_date expose :due_date
expose :confidential expose :confidential
<<<<<<< HEAD
expose :weight, if: ->(issue, _) { issue.supports_weight? } expose :weight, if: ->(issue, _) { issue.supports_weight? }
=======
>>>>>>> upstream/master
expose :web_url do |issue, options| expose :web_url do |issue, options|
Gitlab::UrlBuilder.build(issue) Gitlab::UrlBuilder.build(issue)
......
...@@ -28,12 +28,13 @@ module API ...@@ -28,12 +28,13 @@ module API
end end
# create request and trigger builds # create request and trigger builds
trigger_request = Ci::CreateTriggerRequestService.new.execute(project, trigger, params[:ref].to_s, variables) result = Ci::CreateTriggerRequestService.execute(project, trigger, params[:ref].to_s, variables)
if trigger_request pipeline = result.pipeline
present trigger_request, with: ::API::V3::Entities::TriggerRequest
if pipeline.persisted?
present result.trigger_request, with: ::API::V3::Entities::TriggerRequest
else else
errors = 'No builds created' render_validation_error!(pipeline)
render_api_error!(errors, 400)
end end
end end
......
...@@ -24,12 +24,13 @@ module Ci ...@@ -24,12 +24,13 @@ module Ci
end end
# create request and trigger builds # create request and trigger builds
trigger_request = Ci::CreateTriggerRequestService.new.execute(project, trigger, params[:ref], variables) result = Ci::CreateTriggerRequestService.execute(project, trigger, params[:ref], variables)
if trigger_request pipeline = result.pipeline
present trigger_request, with: Entities::TriggerRequest
if pipeline.persisted?
present result.trigger_request, with: Entities::TriggerRequest
else else
errors = 'No builds created' render_validation_error!(pipeline)
render_api_error!(errors, 400)
end end
end end
end end
......
...@@ -45,6 +45,8 @@ module Gitlab ...@@ -45,6 +45,8 @@ module Gitlab
:bare?, :bare?,
to: :rugged to: :rugged
delegate :exists?, to: :gitaly_repository_client
# Default branch in the repository # Default branch in the repository
def root_ref def root_ref
@root_ref ||= gitaly_migrate(:root_ref) do |is_enabled| @root_ref ||= gitaly_migrate(:root_ref) do |is_enabled|
...@@ -208,10 +210,6 @@ module Gitlab ...@@ -208,10 +210,6 @@ module Gitlab
!empty? !empty?
end end
def repo_exists?
!!rugged
end
# Discovers the default branch based on the repository's available branches # Discovers the default branch based on the repository's available branches
# #
# - If no branches are present, returns nil # - If no branches are present, returns nil
...@@ -815,6 +813,10 @@ module Gitlab ...@@ -815,6 +813,10 @@ module Gitlab
@gitaly_commit_client ||= Gitlab::GitalyClient::CommitService.new(self) @gitaly_commit_client ||= Gitlab::GitalyClient::CommitService.new(self)
end end
def gitaly_repository_client
@gitaly_repository_client ||= Gitlab::GitalyClient::RepositoryService.new(self)
end
private private
# Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'. # Gitaly note: JV: Trying to get rid of the 'filter' option so we can implement this with 'git'.
......
module Gitlab
module GitalyClient
class RepositoryService
def initialize(repository)
@repository = repository
@gitaly_repo = repository.gitaly_repository
end
def exists?
request = Gitaly::RepositoryExistsRequest.new(repository: @gitaly_repo)
GitalyClient.call(@repository.storage, :repository_service, :exists, request).exists
end
end
end
end
...@@ -14,42 +14,42 @@ module Gitlab ...@@ -14,42 +14,42 @@ module Gitlab
TOP_LEVEL_ROUTES = %w[ TOP_LEVEL_ROUTES = %w[
- -
.well-known .well-known
404.html
422.html
500.html
502.html
503.html
abuse_reports abuse_reports
admin admin
all
api api
apple-touch-icon-precomposed.png
apple-touch-icon.png
assets assets
autocomplete autocomplete
ci ci
dashboard dashboard
deploy.html
explore explore
favicon.ico
files files
groups groups
health_check health_check
help help
hooks
import import
invites invites
issues
jwt jwt
koding koding
member
merge_requests
new
notes
notification_settings notification_settings
oauth oauth
profile profile
projects projects
public public
repository
robots.txt robots.txt
s s
search search
sent_notifications sent_notifications
services slash-command-logo.png
snippets snippets
teams
u u
unicorn_test unicorn_test
unsubscribes unsubscribes
......
...@@ -37,8 +37,8 @@ module Gitlab ...@@ -37,8 +37,8 @@ module Gitlab
request_cache def can_create_tag?(ref) request_cache def can_create_tag?(ref)
return false unless can_access_git? return false unless can_access_git?
if ProtectedTag.protected?(project, ref) if protected?(ProtectedTag, project, ref)
project.protected_tags.protected_ref_accessible_to?(ref, user, action: :create) protected_tag_accessible_to?(ref, action: :create)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
end end
...@@ -47,20 +47,24 @@ module Gitlab ...@@ -47,20 +47,24 @@ module Gitlab
request_cache def can_delete_branch?(ref) request_cache def can_delete_branch?(ref)
return false unless can_access_git? return false unless can_access_git?
if ProtectedBranch.protected?(project, ref) if protected?(ProtectedBranch, project, ref)
user.can?(:delete_protected_branch, project) user.can?(:delete_protected_branch, project)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
end end
end end
def can_update_branch?(ref)
can_push_to_branch?(ref) || can_merge_to_branch?(ref)
end
request_cache def can_push_to_branch?(ref) request_cache def can_push_to_branch?(ref)
return false unless can_access_git? return false unless can_access_git?
if ProtectedBranch.protected?(project, ref) if protected?(ProtectedBranch, project, ref)
return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user) return true if project.empty_repo? && project.user_can_push_to_empty_repo?(user)
project.protected_branches.protected_ref_accessible_to?(ref, user, action: :push) protected_branch_accessible_to?(ref, action: :push)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
end end
...@@ -69,8 +73,8 @@ module Gitlab ...@@ -69,8 +73,8 @@ module Gitlab
request_cache def can_merge_to_branch?(ref) request_cache def can_merge_to_branch?(ref)
return false unless can_access_git? return false unless can_access_git?
if ProtectedBranch.protected?(project, ref) if protected?(ProtectedBranch, project, ref)
project.protected_branches.protected_ref_accessible_to?(ref, user, action: :merge) protected_branch_accessible_to?(ref, action: :merge)
else else
user.can?(:push_code, project) user.can?(:push_code, project)
end end
...@@ -87,5 +91,23 @@ module Gitlab ...@@ -87,5 +91,23 @@ module Gitlab
def can_access_git? def can_access_git?
user && user.can?(:access_git) user && user.can?(:access_git)
end end
def protected_branch_accessible_to?(ref, action:)
ProtectedBranch.protected_ref_accessible_to?(
ref, user,
action: action,
protected_refs: project.protected_branches)
end
def protected_tag_accessible_to?(ref, action:)
ProtectedTag.protected_ref_accessible_to?(
ref, user,
action: action,
protected_refs: project.protected_tags)
end
request_cache def protected?(kind, project, ref)
kind.protected?(project, ref)
end
end end
end end
# Андрей Витюк <andruwa13@gmail.com>, 2017. #zanata
# Huang Tao <htve@outlook.com>, 2017. #zanata # Huang Tao <htve@outlook.com>, 2017. #zanata
# Андрей Витюк <andruwa13@gmail.com>, 2017. #zanata
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gitlab 1.0.0\n" "Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-28 13:32+0200\n" "POT-Creation-Date: 2017-07-05 08:50-0500\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"PO-Revision-Date: 2017-07-12 09:05-0400\n"
"Last-Translator: Андрей Витюк <andruwa13@gmail.com>\n"
"Language-Team: Ukrainian (https://translate.zanata.org/project/view/GitLab)\n" "Language-Team: Ukrainian (https://translate.zanata.org/project/view/GitLab)\n"
"PO-Revision-Date: 2017-07-25 03:27-0400\n"
"Last-Translator: Андрей Витюк <andruwa13@gmail.com>\n"
"Language: uk\n" "Language: uk\n"
"X-Generator: Zanata 3.9.6\n" "X-Generator: Zanata 3.9.6\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
...@@ -57,7 +57,7 @@ msgid "Add Changelog" ...@@ -57,7 +57,7 @@ msgid "Add Changelog"
msgstr "Додати список змін (Changelog)" msgstr "Додати список змін (Changelog)"
msgid "Add Contribution guide" msgid "Add Contribution guide"
msgstr "Додати керівництво для контрибуторів" msgstr "Додати керівництво для контриб’юторів"
msgid "Add License" msgid "Add License"
msgstr "Додати ліцензію" msgstr "Додати ліцензію"
...@@ -209,7 +209,9 @@ msgstr[1] "Комміта" ...@@ -209,7 +209,9 @@ msgstr[1] "Комміта"
msgstr[2] "Коммітів" msgstr[2] "Коммітів"
msgid "Commit duration in minutes for last 30 commits" msgid "Commit duration in minutes for last 30 commits"
msgstr "Комміт тривалість у хвилинах за останні 30 коммітів" msgstr ""
"Тривалість коммітів протягом декількох хвилин на протязі 30 останніх "
"коммітів"
msgid "Commit message" msgid "Commit message"
msgstr "Комміт повідомлення" msgstr "Комміт повідомлення"
...@@ -236,10 +238,10 @@ msgid "Compare" ...@@ -236,10 +238,10 @@ msgid "Compare"
msgstr "Порівняти" msgstr "Порівняти"
msgid "Contribution guide" msgid "Contribution guide"
msgstr "Керівництво контрибуторів" msgstr "Керівництво контриб’юторів"
msgid "Contributors" msgid "Contributors"
msgstr "Контрибутори" msgstr "Контриб’ютори"
msgid "Copy URL to clipboard" msgid "Copy URL to clipboard"
msgstr "Скопіювати URL в буфер обміну" msgstr "Скопіювати URL в буфер обміну"
...@@ -352,16 +354,16 @@ msgid "Download" ...@@ -352,16 +354,16 @@ msgid "Download"
msgstr "Завантажити" msgstr "Завантажити"
msgid "Download tar" msgid "Download tar"
msgstr "Завантажити в форматі tar" msgstr "Завантажити tar"
msgid "Download tar.bz2" msgid "Download tar.bz2"
msgstr "Завантажити в форматі tar.bz2" msgstr "Завантажити tar.bz2"
msgid "Download tar.gz" msgid "Download tar.gz"
msgstr "Завантажити в форматі tar.gz" msgstr "Завантажити tar.gz"
msgid "Download zip" msgid "Download zip"
msgstr "Завантажити в форматі zip" msgstr "Завантажити zip"
msgid "DownloadArtifacts|Download" msgid "DownloadArtifacts|Download"
msgstr "Завантажити" msgstr "Завантажити"
...@@ -397,7 +399,7 @@ msgid "Failed to remove the pipeline schedule" ...@@ -397,7 +399,7 @@ msgid "Failed to remove the pipeline schedule"
msgstr "Не вдалося видалити розклад Конвеєра" msgstr "Не вдалося видалити розклад Конвеєра"
msgid "Files" msgid "Files"
msgstr "Файли" msgstr "Файлів"
msgid "Filter by commit message" msgid "Filter by commit message"
msgstr "Фільтрувати повідомлення коммітів" msgstr "Фільтрувати повідомлення коммітів"
...@@ -436,7 +438,7 @@ msgid "GoToYourFork|Fork" ...@@ -436,7 +438,7 @@ msgid "GoToYourFork|Fork"
msgstr "Форк" msgstr "Форк"
msgid "Home" msgid "Home"
msgstr "Початок" msgstr "Головна"
msgid "Housekeeping successfully started" msgid "Housekeeping successfully started"
msgstr "Очищення успішно розпочато" msgstr "Очищення успішно розпочато"
...@@ -451,13 +453,13 @@ msgid "Introducing Cycle Analytics" ...@@ -451,13 +453,13 @@ msgid "Introducing Cycle Analytics"
msgstr "Представляємо аналітику циклу" msgstr "Представляємо аналітику циклу"
msgid "Jobs for last month" msgid "Jobs for last month"
msgstr "Завдання за останній місяць" msgstr "Кількість завдань за останній місяць"
msgid "Jobs for last week" msgid "Jobs for last week"
msgstr "Завдання за останній тиждень" msgstr "Кількість завдань за останній тиждень"
msgid "Jobs for last year" msgid "Jobs for last year"
msgstr "Завдання за останній рік" msgstr "Кількість завдань за останній рік"
msgid "LFSStatus|Disabled" msgid "LFSStatus|Disabled"
msgstr "Вимкнено" msgstr "Вимкнено"
...@@ -508,7 +510,7 @@ msgid "New Issue" ...@@ -508,7 +510,7 @@ msgid "New Issue"
msgid_plural "New Issues" msgid_plural "New Issues"
msgstr[0] "Нова проблема" msgstr[0] "Нова проблема"
msgstr[1] "Нові проблеми" msgstr[1] "Нові проблеми"
msgstr[2] "Новах проблем" msgstr[2] "Нових проблем"
msgid "New Pipeline Schedule" msgid "New Pipeline Schedule"
msgstr "Новий розклад Конвеєра" msgstr "Новий розклад Конвеєра"
...@@ -654,6 +656,12 @@ msgstr "Всі" ...@@ -654,6 +656,12 @@ msgstr "Всі"
msgid "PipelineSchedules|Inactive" msgid "PipelineSchedules|Inactive"
msgstr "Неактивні" msgstr "Неактивні"
msgid "PipelineSchedules|Input variable key"
msgstr "Введіть ім'я змінної"
msgid "PipelineSchedules|Input variable value"
msgstr "Вхідні значення змінних"
msgid "PipelineSchedules|Next Run" msgid "PipelineSchedules|Next Run"
msgstr "Наступний запуск" msgstr "Наступний запуск"
...@@ -663,12 +671,18 @@ msgstr "Немає" ...@@ -663,12 +671,18 @@ msgstr "Немає"
msgid "PipelineSchedules|Provide a short description for this pipeline" msgid "PipelineSchedules|Provide a short description for this pipeline"
msgstr "Задайте короткий опис для цього Конвеєру" msgstr "Задайте короткий опис для цього Конвеєру"
msgid "PipelineSchedules|Remove variable row"
msgstr "Видалити змінні"
msgid "PipelineSchedules|Take ownership" msgid "PipelineSchedules|Take ownership"
msgstr "Стати власником" msgstr "Стати власником"
msgid "PipelineSchedules|Target" msgid "PipelineSchedules|Target"
msgstr "Ціль" msgstr "Ціль"
msgid "PipelineSchedules|Variables"
msgstr "Змінні"
msgid "PipelineSheduleIntervalPattern|Custom" msgid "PipelineSheduleIntervalPattern|Custom"
msgstr "Власні" msgstr "Власні"
...@@ -745,7 +759,7 @@ msgid "ProjectLifecycle|Stage" ...@@ -745,7 +759,7 @@ msgid "ProjectLifecycle|Stage"
msgstr "Етап" msgstr "Етап"
msgid "ProjectNetworkGraph|Graph" msgid "ProjectNetworkGraph|Graph"
msgstr "Графік" msgstr "Історія"
msgid "Read more" msgid "Read more"
msgstr "Докладніше" msgstr "Докладніше"
...@@ -840,7 +854,7 @@ msgid "Source code" ...@@ -840,7 +854,7 @@ msgid "Source code"
msgstr "Код" msgstr "Код"
msgid "StarProject|Star" msgid "StarProject|Star"
msgstr "Старт" msgstr "Підписатися"
msgid "Start a %{new_merge_request} with these changes" msgid "Start a %{new_merge_request} with these changes"
msgstr "Почати %{new_merge_request} з цих змін" msgstr "Почати %{new_merge_request} з цих змін"
...@@ -976,19 +990,19 @@ msgid "Timeago|%s minutes remaining" ...@@ -976,19 +990,19 @@ msgid "Timeago|%s minutes remaining"
msgstr "%s хвилини залишитися" msgstr "%s хвилини залишитися"
msgid "Timeago|%s months ago" msgid "Timeago|%s months ago"
msgstr "%s місяців тому" msgstr "%s місяці(в) тому"
msgid "Timeago|%s months remaining" msgid "Timeago|%s months remaining"
msgstr "%s місяці, що залишилися" msgstr "%s місяці(в), що залишилися"
msgid "Timeago|%s seconds remaining" msgid "Timeago|%s seconds remaining"
msgstr "%s секунд, що залишаються" msgstr "%s секунд, що залишаються"
msgid "Timeago|%s weeks ago" msgid "Timeago|%s weeks ago"
msgstr "%s тижнів тому" msgstr "%s тижні(в) тому"
msgid "Timeago|%s weeks remaining" msgid "Timeago|%s weeks remaining"
msgstr "%s тижнів залишилися" msgstr "%s тижні(в) залишилися"
msgid "Timeago|%s years ago" msgid "Timeago|%s years ago"
msgstr "%s років тому" msgstr "%s років тому"
...@@ -1018,7 +1032,7 @@ msgid "Timeago|Past due" ...@@ -1018,7 +1032,7 @@ msgid "Timeago|Past due"
msgstr "Прострочені" msgstr "Прострочені"
msgid "Timeago|a day ago" msgid "Timeago|a day ago"
msgstr "годин тому" msgstr "День тому"
msgid "Timeago|a month ago" msgid "Timeago|a month ago"
msgstr "місяць тому" msgstr "місяць тому"
...@@ -1042,28 +1056,28 @@ msgid "Timeago|about an hour ago" ...@@ -1042,28 +1056,28 @@ msgid "Timeago|about an hour ago"
msgstr "Близько години тому" msgstr "Близько години тому"
msgid "Timeago|in %s days" msgid "Timeago|in %s days"
msgstr "через %s днїв" msgstr "через %s дні(в)"
msgid "Timeago|in %s hours" msgid "Timeago|in %s hours"
msgstr "через %s години" msgstr "через %s годин(и)"
msgid "Timeago|in %s minutes" msgid "Timeago|in %s minutes"
msgstr "через %s хвилини" msgstr "через %s хвилин(и)"
msgid "Timeago|in %s months" msgid "Timeago|in %s months"
msgstr "через %s місяців" msgstr "через %s місяці(в)"
msgid "Timeago|in %s seconds" msgid "Timeago|in %s seconds"
msgstr "через %s секунд" msgstr "через %s секунд(и)"
msgid "Timeago|in %s weeks" msgid "Timeago|in %s weeks"
msgstr "через %s тижні" msgstr "через %s тижні(в)"
msgid "Timeago|in %s years" msgid "Timeago|in %s years"
msgstr "через %s років" msgstr "через %s роки(ів)"
msgid "Timeago|in 1 day" msgid "Timeago|in 1 day"
msgstr "через день" msgstr "через 1 день"
msgid "Timeago|in 1 hour" msgid "Timeago|in 1 hour"
msgstr "через годину" msgstr "через годину"
...@@ -1081,22 +1095,22 @@ msgid "Timeago|in 1 year" ...@@ -1081,22 +1095,22 @@ msgid "Timeago|in 1 year"
msgstr "через рік" msgstr "через рік"
msgid "Timeago|less than a minute ago" msgid "Timeago|less than a minute ago"
msgstr "менш хвилини тому" msgstr "менше хвилини тому"
msgid "Time|hr" msgid "Time|hr"
msgid_plural "Time|hrs" msgid_plural "Time|hrs"
msgstr[0] "Година" msgstr[0] "година"
msgstr[1] "Годині" msgstr[1] "години"
msgstr[2] "Годин" msgstr[2] "годин"
msgid "Time|min" msgid "Time|min"
msgid_plural "Time|mins" msgid_plural "Time|mins"
msgstr[0] "хвилина" msgstr[0] "хвилина"
msgstr[1] "хвилині" msgstr[1] "хвилини"
msgstr[2] "хвилин" msgstr[2] "хвилин"
msgid "Time|s" msgid "Time|s"
msgstr "секунда" msgstr "секунд(а)"
msgid "Total Time" msgid "Total Time"
msgstr "Загальний час" msgstr "Загальний час"
...@@ -1105,7 +1119,7 @@ msgid "Total test time for all commits/merges" ...@@ -1105,7 +1119,7 @@ msgid "Total test time for all commits/merges"
msgstr "Загальний час, щоб перевірити всі фіксації/злиття" msgstr "Загальний час, щоб перевірити всі фіксації/злиття"
msgid "Unstar" msgid "Unstar"
msgstr "Зняти позначку" msgstr "Відписатись"
msgid "Upload New File" msgid "Upload New File"
msgstr "Завантажити новий файл" msgstr "Завантажити новий файл"
...@@ -1117,7 +1131,7 @@ msgid "UploadLink|click to upload" ...@@ -1117,7 +1131,7 @@ msgid "UploadLink|click to upload"
msgstr "Натисніть, щоб завантажити" msgstr "Натисніть, щоб завантажити"
msgid "Use your global notification setting" msgid "Use your global notification setting"
msgstr "Використовуються глобальний налаштування повідомлень" msgstr "Використовуються глобальні налаштування повідомлень"
msgid "View open merge request" msgid "View open merge request"
msgstr "Перегляд відкритих запитів на злиття" msgstr "Перегляд відкритих запитів на злиття"
...@@ -1140,6 +1154,15 @@ msgstr "Ми не маємо достатньо даних для показу ...@@ -1140,6 +1154,15 @@ msgstr "Ми не маємо достатньо даних для показу
msgid "Withdraw Access Request" msgid "Withdraw Access Request"
msgstr "Скасувати запит доступу" msgstr "Скасувати запит доступу"
msgid ""
"You are going to remove %{group_name}.\n"
"Removed groups CANNOT be restored!\n"
"Are you ABSOLUTELY sure?"
msgstr ""
"Ви хочете видалити %{group_name}.\n"
"Видалені групи НЕ МОЖНА буду відновити!\n"
"Ви АБСОЛЮТНО впевнені?"
msgid "" msgid ""
"You are going to remove %{project_name_with_namespace}.\n" "You are going to remove %{project_name_with_namespace}.\n"
"Removed project CANNOT be restored!\n" "Removed project CANNOT be restored!\n"
......
...@@ -2,6 +2,7 @@ require 'spec_helper' ...@@ -2,6 +2,7 @@ require 'spec_helper'
describe Admin::DashboardController do describe Admin::DashboardController do
describe '#index' do describe '#index' do
<<<<<<< HEAD
it "allows an admin user to access the page" do it "allows an admin user to access the page" do
sign_in(create(:user, :admin)) sign_in(create(:user, :admin))
get :index get :index
...@@ -21,6 +22,22 @@ describe Admin::DashboardController do ...@@ -21,6 +22,22 @@ describe Admin::DashboardController do
get :index get :index
expect(response).to have_http_status(404) expect(response).to have_http_status(404)
=======
context 'with pending_delete projects' do
render_views
it 'does not retrieve projects that are pending deletion' do
sign_in(create(:admin))
project = create(:project)
pending_delete_project = create(:project, pending_delete: true)
get :index
expect(response.body).to match(project.name)
expect(response.body).not_to match(pending_delete_project.name)
end
>>>>>>> upstream/master
end end
end end
end end
...@@ -827,7 +827,7 @@ describe Projects::IssuesController do ...@@ -827,7 +827,7 @@ describe Projects::IssuesController do
delete :destroy, namespace_id: project.namespace, project_id: project, id: issue.iid delete :destroy, namespace_id: project.namespace, project_id: project, id: issue.iid
expect(response).to have_http_status(302) expect(response).to have_http_status(302)
expect(controller).to set_flash[:notice].to(/The issue was successfully deleted\./).now expect(controller).to set_flash[:notice].to(/The issue was successfully deleted\./)
end end
it 'delegates the update of the todos count cache to TodoService' do it 'delegates the update of the todos count cache to TodoService' do
......
...@@ -7,6 +7,10 @@ describe Projects::JobsController do ...@@ -7,6 +7,10 @@ describe Projects::JobsController do
let(:pipeline) { create(:ci_pipeline, project: project) } let(:pipeline) { create(:ci_pipeline, project: project) }
let(:user) { create(:user) } let(:user) { create(:user) }
before do
stub_not_protect_default_branch
end
describe 'GET index' do describe 'GET index' do
context 'when scope is pending' do context 'when scope is pending' do
before do before do
......
...@@ -440,7 +440,7 @@ describe Projects::MergeRequestsController do ...@@ -440,7 +440,7 @@ describe Projects::MergeRequestsController do
delete :destroy, namespace_id: project.namespace, project_id: project, id: merge_request.iid delete :destroy, namespace_id: project.namespace, project_id: project, id: merge_request.iid
expect(response).to have_http_status(302) expect(response).to have_http_status(302)
expect(controller).to set_flash[:notice].to(/The merge request was successfully deleted\./).now expect(controller).to set_flash[:notice].to(/The merge request was successfully deleted\./)
end end
it 'delegates the update of the todos count cache to TodoService' do it 'delegates the update of the todos count cache to TodoService' do
......
...@@ -8,6 +8,7 @@ describe Projects::PipelinesController do ...@@ -8,6 +8,7 @@ describe Projects::PipelinesController do
let(:feature) { ProjectFeature::DISABLED } let(:feature) { ProjectFeature::DISABLED }
before do before do
stub_not_protect_default_branch
project.add_developer(user) project.add_developer(user)
project.project_feature.update( project.project_feature.update(
builds_access_level: feature) builds_access_level: feature)
......
...@@ -23,7 +23,7 @@ describe SentNotificationsController, type: :controller do ...@@ -23,7 +23,7 @@ describe SentNotificationsController, type: :controller do
end end
it 'sets the flash message' do it 'sets the flash message' do
expect(controller).to set_flash[:notice].to(/unsubscribed/).now expect(controller).to set_flash[:notice].to(/unsubscribed/)
end end
it 'redirects to the login page' do it 'redirects to the login page' do
...@@ -83,7 +83,7 @@ describe SentNotificationsController, type: :controller do ...@@ -83,7 +83,7 @@ describe SentNotificationsController, type: :controller do
end end
it 'sets the flash message' do it 'sets the flash message' do
expect(controller).to set_flash[:notice].to(/unsubscribed/).now expect(controller).to set_flash[:notice].to(/unsubscribed/)
end end
it 'redirects to the issue page' do it 'redirects to the issue page' do
...@@ -109,7 +109,7 @@ describe SentNotificationsController, type: :controller do ...@@ -109,7 +109,7 @@ describe SentNotificationsController, type: :controller do
end end
it 'sets the flash message' do it 'sets the flash message' do
expect(controller).to set_flash[:notice].to(/unsubscribed/).now expect(controller).to set_flash[:notice].to(/unsubscribed/)
end end
it 'redirects to the merge request page' do it 'redirects to the merge request page' do
......
...@@ -78,5 +78,23 @@ RSpec.describe 'Dashboard Issues', feature: true do ...@@ -78,5 +78,23 @@ RSpec.describe 'Dashboard Issues', feature: true do
expect(page).not_to have_content(project_with_issues_disabled.name_with_namespace) expect(page).not_to have_content(project_with_issues_disabled.name_with_namespace)
end end
end end
it 'shows the new issue page', js: true do
Gitlab::Application.routes.default_url_options = {
host: Capybara.current_session.server.host,
port: Capybara.current_session.server.port,
protocol: 'http'
}
find('.new-project-item-select-button').trigger('click')
wait_for_requests
find('.select2-results li').click
expect(page).to have_current_path("/#{project.path_with_namespace}/issues/new")
page.within('#content-body') do
expect(page).to have_selector('.issue-form')
end
end
end end
end end
...@@ -119,6 +119,7 @@ feature 'Issues > User uses quick actions', feature: true, js: true do ...@@ -119,6 +119,7 @@ feature 'Issues > User uses quick actions', feature: true, js: true do
end end
end end
<<<<<<< HEAD
describe 'adding a weight from a note' do describe 'adding a weight from a note' do
let(:issue) { create(:issue, project: project) } let(:issue) { create(:issue, project: project) }
...@@ -195,6 +196,8 @@ feature 'Issues > User uses quick actions', feature: true, js: true do ...@@ -195,6 +196,8 @@ feature 'Issues > User uses quick actions', feature: true, js: true do
end end
end end
=======
>>>>>>> upstream/master
describe 'mark issue as duplicate' do describe 'mark issue as duplicate' do
let(:issue) { create(:issue, project: project) } let(:issue) { create(:issue, project: project) }
let(:original_issue) { create(:issue, project: project) } let(:original_issue) { create(:issue, project: project) }
......
...@@ -6,17 +6,12 @@ feature 'Setup Jira service', :feature, :js do ...@@ -6,17 +6,12 @@ feature 'Setup Jira service', :feature, :js do
let(:service) { project.create_jira_service } let(:service) { project.create_jira_service }
let(:url) { 'http://jira.example.com' } let(:url) { 'http://jira.example.com' }
let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' }
def stub_project_url
WebMock.stub_request(:get, 'http://jira.example.com/rest/api/2/project/GitLabProject')
.with(basic_auth: %w(username password))
end
def fill_form(active = true) def fill_form(active = true)
check 'Active' if active check 'Active' if active
fill_in 'service_url', with: url fill_in 'service_url', with: url
fill_in 'service_project_key', with: 'GitLabProject'
fill_in 'service_username', with: 'username' fill_in 'service_username', with: 'username'
fill_in 'service_password', with: 'password' fill_in 'service_password', with: 'password'
fill_in 'service_jira_issue_transition_id', with: '25' fill_in 'service_jira_issue_transition_id', with: '25'
...@@ -31,11 +26,10 @@ feature 'Setup Jira service', :feature, :js do ...@@ -31,11 +26,10 @@ feature 'Setup Jira service', :feature, :js do
describe 'user sets and activates Jira Service' do describe 'user sets and activates Jira Service' do
context 'when Jira connection test succeeds' do context 'when Jira connection test succeeds' do
before do
stub_project_url
end
it 'activates the JIRA service' do it 'activates the JIRA service' do
server_info = { key: 'value' }.to_json
WebMock.stub_request(:get, test_url).with(basic_auth: %w(username password)).to_return(body: server_info)
click_link('JIRA') click_link('JIRA')
fill_form fill_form
click_button('Test settings and save changes') click_button('Test settings and save changes')
...@@ -47,10 +41,6 @@ feature 'Setup Jira service', :feature, :js do ...@@ -47,10 +41,6 @@ feature 'Setup Jira service', :feature, :js do
end end
context 'when Jira connection test fails' do context 'when Jira connection test fails' do
before do
stub_project_url.to_return(status: 401)
end
it 'shows errors when some required fields are not filled in' do it 'shows errors when some required fields are not filled in' do
click_link('JIRA') click_link('JIRA')
...@@ -64,6 +54,9 @@ feature 'Setup Jira service', :feature, :js do ...@@ -64,6 +54,9 @@ feature 'Setup Jira service', :feature, :js do
end end
it 'activates the JIRA service' do it 'activates the JIRA service' do
WebMock.stub_request(:get, test_url).with(basic_auth: %w(username password))
.to_raise(JIRA::HTTPError.new(double(message: 'message')))
click_link('JIRA') click_link('JIRA')
fill_form fill_form
click_button('Test settings and save changes') click_button('Test settings and save changes')
......
...@@ -10,6 +10,7 @@ const deploymentMockData = [ ...@@ -10,6 +10,7 @@ const deploymentMockData = [
url: '/root/acets-review-apps/environments/15', url: '/root/acets-review-apps/environments/15',
stop_url: '/root/acets-review-apps/environments/15/stop', stop_url: '/root/acets-review-apps/environments/15/stop',
metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics', metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
external_url: 'http://diplo.', external_url: 'http://diplo.',
external_url_formatted: 'diplo.', external_url_formatted: 'diplo.',
deployed_at: '2017-03-22T22:44:42.258Z', deployed_at: '2017-03-22T22:44:42.258Z',
......
...@@ -3,6 +3,7 @@ import memoryUsageComponent from '~/vue_merge_request_widget/components/mr_widge ...@@ -3,6 +3,7 @@ import memoryUsageComponent from '~/vue_merge_request_widget/components/mr_widge
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service'; import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
const url = '/root/acets-review-apps/environments/15/deployments/1/metrics'; const url = '/root/acets-review-apps/environments/15/deployments/1/metrics';
const monitoringUrl = '/root/acets-review-apps/environments/15/metrics';
const metricsMockData = { const metricsMockData = {
success: true, success: true,
...@@ -39,6 +40,7 @@ const createComponent = () => { ...@@ -39,6 +40,7 @@ const createComponent = () => {
el: document.createElement('div'), el: document.createElement('div'),
propsData: { propsData: {
metricsUrl: url, metricsUrl: url,
metricsMonitoringUrl: monitoringUrl,
memoryMetrics: [], memoryMetrics: [],
deploymentTime: 0, deploymentTime: 0,
hasMetrics: false, hasMetrics: false,
......
...@@ -48,7 +48,9 @@ describe Gitlab::Ci::Status::Build::Cancelable do ...@@ -48,7 +48,9 @@ describe Gitlab::Ci::Status::Build::Cancelable do
describe '#has_action?' do describe '#has_action?' do
context 'when user is allowed to update build' do context 'when user is allowed to update build' do
before do before do
build.project.team << [user, :developer] stub_not_protect_default_branch
build.project.add_developer(user)
end end
it { is_expected.to have_action } it { is_expected.to have_action }
......
...@@ -7,7 +7,9 @@ describe Gitlab::Ci::Status::Build::Factory do ...@@ -7,7 +7,9 @@ describe Gitlab::Ci::Status::Build::Factory do
let(:factory) { described_class.new(build, user) } let(:factory) { described_class.new(build, user) }
before do before do
project.team << [user, :developer] stub_not_protect_default_branch
project.add_developer(user)
end end
context 'when build is successful' do context 'when build is successful' do
...@@ -225,19 +227,19 @@ describe Gitlab::Ci::Status::Build::Factory do ...@@ -225,19 +227,19 @@ describe Gitlab::Ci::Status::Build::Factory do
end end
context 'when user has ability to play action' do context 'when user has ability to play action' do
before do
project.add_developer(user)
create(:protected_branch, :developers_can_merge,
name: build.ref, project: project)
end
it 'fabricates status that has action' do it 'fabricates status that has action' do
expect(status).to have_action expect(status).to have_action
end end
end end
context 'when user does not have ability to play action' do context 'when user does not have ability to play action' do
before do
allow(build.project).to receive(:empty_repo?).and_return(false)
create(:protected_branch, :no_one_can_push,
name: build.ref, project: build.project)
end
it 'fabricates status that has no action' do it 'fabricates status that has no action' do
expect(status).not_to have_action expect(status).not_to have_action
end end
...@@ -262,6 +264,13 @@ describe Gitlab::Ci::Status::Build::Factory do ...@@ -262,6 +264,13 @@ describe Gitlab::Ci::Status::Build::Factory do
end end
context 'when user is not allowed to execute manual action' do context 'when user is not allowed to execute manual action' do
before do
allow(build.project).to receive(:empty_repo?).and_return(false)
create(:protected_branch, :no_one_can_push,
name: build.ref, project: build.project)
end
it 'fabricates status with correct details' do it 'fabricates status with correct details' do
expect(status.text).to eq 'manual' expect(status.text).to eq 'manual'
expect(status.group).to eq 'manual' expect(status.group).to eq 'manual'
......
...@@ -48,7 +48,9 @@ describe Gitlab::Ci::Status::Build::Retryable do ...@@ -48,7 +48,9 @@ describe Gitlab::Ci::Status::Build::Retryable do
describe '#has_action?' do describe '#has_action?' do
context 'when user is allowed to update build' do context 'when user is allowed to update build' do
before do before do
build.project.team << [user, :developer] stub_not_protect_default_branch
build.project.add_developer(user)
end end
it { is_expected.to have_action } it { is_expected.to have_action }
......
...@@ -20,7 +20,9 @@ describe Gitlab::Ci::Status::Build::Stop do ...@@ -20,7 +20,9 @@ describe Gitlab::Ci::Status::Build::Stop do
describe '#has_action?' do describe '#has_action?' do
context 'when user is allowed to update build' do context 'when user is allowed to update build' do
before do before do
build.project.team << [user, :developer] stub_not_protect_default_branch
build.project.add_developer(user)
end end
it { is_expected.to have_action } it { is_expected.to have_action }
......
require 'spec_helper'
describe Gitlab::GitalyClient::RepositoryService do
set(:project) { create(:empty_project) }
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.path_with_namespace + '.git' }
let(:client) { described_class.new(project.repository) }
describe '#exists?' do
it 'sends an exists message' do
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:exists)
.with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
.and_call_original
client.exists?
end
end
end
...@@ -36,9 +36,12 @@ describe Gitlab::PathRegex, lib: true do ...@@ -36,9 +36,12 @@ describe Gitlab::PathRegex, lib: true do
described_class::PROJECT_WILDCARD_ROUTES.include?(path.split('/').first) described_class::PROJECT_WILDCARD_ROUTES.include?(path.split('/').first)
end end
def failure_message(missing_words, constant_name, migration_helper) def failure_message(constant_name, migration_helper, missing_words: [], additional_words: [])
missing_words = Array(missing_words) missing_words = Array(missing_words)
<<-MSG additional_words = Array(additional_words)
message = ""
if missing_words.any?
message += <<-MISSING
Found new routes that could cause conflicts with existing namespaced routes Found new routes that could cause conflicts with existing namespaced routes
for groups or projects. for groups or projects.
...@@ -51,7 +54,18 @@ describe Gitlab::PathRegex, lib: true do ...@@ -51,7 +54,18 @@ describe Gitlab::PathRegex, lib: true do
Make sure to make a note of the renamed records in the release blog post. Make sure to make a note of the renamed records in the release blog post.
MSG MISSING
end
if additional_words.any?
message += <<-ADDITIONAL
Why are <#{additional_words.join(', ')}> in `#{constant_name}`?
If they are really required, update these specs to reflect that.
ADDITIONAL
end
message
end end
let(:all_routes) do let(:all_routes) do
...@@ -68,9 +82,23 @@ describe Gitlab::PathRegex, lib: true do ...@@ -68,9 +82,23 @@ describe Gitlab::PathRegex, lib: true do
let(:routes_not_starting_in_wildcard) { routes_without_format.select { |p| p !~ %r{^/[:*]} } } let(:routes_not_starting_in_wildcard) { routes_without_format.select { |p| p !~ %r{^/[:*]} } }
let(:top_level_words) do let(:top_level_words) do
routes_not_starting_in_wildcard.map do |route| words = routes_not_starting_in_wildcard.map do |route|
route.split('/')[1] route.split('/')[1]
end.compact.uniq end.compact.uniq
words + ee_top_level_words + files_in_public + Array(API::API.prefix.to_s)
end
let(:ee_top_level_words) do
['unsubscribes']
end
let(:files_in_public) do
git = Gitlab.config.git.bin_path
`cd #{Rails.root} && #{git} ls-files public`
.split("\n")
.map { |entry| entry.gsub('public/', '') }
.uniq
end end
# All routes that start with a namespaced path, that have 1 or more # All routes that start with a namespaced path, that have 1 or more
...@@ -115,18 +143,29 @@ describe Gitlab::PathRegex, lib: true do ...@@ -115,18 +143,29 @@ describe Gitlab::PathRegex, lib: true do
let(:paths_after_group_id) do let(:paths_after_group_id) do
group_routes.map do |route| group_routes.map do |route|
route.gsub(STARTING_WITH_GROUP, '').split('/').first route.gsub(STARTING_WITH_GROUP, '').split('/').first
end.uniq end.uniq + ee_paths_after_group_id
end
let(:ee_paths_after_group_id) do
%w(analytics
ldap
ldap_group_links
notification_setting
audit_events
pipeline_quota hooks)
end end
describe 'TOP_LEVEL_ROUTES' do describe 'TOP_LEVEL_ROUTES' do
it 'includes all the top level namespaces' do it 'includes all the top level namespaces' do
failure_block = lambda do failure_block = lambda do
missing_words = top_level_words - described_class::TOP_LEVEL_ROUTES missing_words = top_level_words - described_class::TOP_LEVEL_ROUTES
failure_message(missing_words, 'TOP_LEVEL_ROUTES', 'rename_root_paths') additional_words = described_class::TOP_LEVEL_ROUTES - top_level_words
failure_message('TOP_LEVEL_ROUTES', 'rename_root_paths',
missing_words: missing_words, additional_words: additional_words)
end end
expect(described_class::TOP_LEVEL_ROUTES) expect(described_class::TOP_LEVEL_ROUTES)
.to include(*top_level_words), failure_block .to contain_exactly(*top_level_words), failure_block
end end
end end
...@@ -134,11 +173,13 @@ describe Gitlab::PathRegex, lib: true do ...@@ -134,11 +173,13 @@ describe Gitlab::PathRegex, lib: true do
it "don't contain a second wildcard" do it "don't contain a second wildcard" do
failure_block = lambda do failure_block = lambda do
missing_words = paths_after_group_id - described_class::GROUP_ROUTES missing_words = paths_after_group_id - described_class::GROUP_ROUTES
failure_message(missing_words, 'GROUP_ROUTES', 'rename_child_paths') additional_words = described_class::GROUP_ROUTES - paths_after_group_id
failure_message('GROUP_ROUTES', 'rename_child_paths',
missing_words: missing_words, additional_words: additional_words)
end end
expect(described_class::GROUP_ROUTES) expect(described_class::GROUP_ROUTES)
.to include(*paths_after_group_id), failure_block .to contain_exactly(*paths_after_group_id), failure_block
end end
end end
...@@ -147,7 +188,7 @@ describe Gitlab::PathRegex, lib: true do ...@@ -147,7 +188,7 @@ describe Gitlab::PathRegex, lib: true do
aggregate_failures do aggregate_failures do
all_wildcard_paths.each do |path| all_wildcard_paths.each do |path|
expect(wildcards_include?(path)) expect(wildcards_include?(path))
.to be(true), failure_message(path, 'PROJECT_WILDCARD_ROUTES', 'rename_wildcard_paths') .to be(true), failure_message('PROJECT_WILDCARD_ROUTES', 'rename_wildcard_paths', missing_words: path)
end end
end end
end end
......
...@@ -738,6 +738,8 @@ describe Ci::Pipeline, models: true do ...@@ -738,6 +738,8 @@ describe Ci::Pipeline, models: true do
context 'on failure and build retry' do context 'on failure and build retry' do
before do before do
stub_not_protect_default_branch
build.drop build.drop
project.add_developer(user) project.add_developer(user)
...@@ -1003,6 +1005,8 @@ describe Ci::Pipeline, models: true do ...@@ -1003,6 +1005,8 @@ describe Ci::Pipeline, models: true do
let(:latest_status) { pipeline.statuses.latest.pluck(:status) } let(:latest_status) { pipeline.statuses.latest.pluck(:status) }
before do before do
stub_not_protect_default_branch
project.add_developer(user) project.add_developer(user)
end end
......
...@@ -13,12 +13,6 @@ describe List do ...@@ -13,12 +13,6 @@ describe List do
it { is_expected.to validate_presence_of(:position) } it { is_expected.to validate_presence_of(:position) }
it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than_or_equal_to(0) } it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than_or_equal_to(0) }
it 'validates uniqueness of label scoped to board_id' do
create(:list)
expect(subject).to validate_uniqueness_of(:label_id).scoped_to(:board_id)
end
context 'when list_type is set to closed' do context 'when list_type is set to closed' do
subject { described_class.new(list_type: :closed) } subject { described_class.new(list_type: :closed) }
......
...@@ -11,7 +11,14 @@ RSpec.describe NotificationSetting, type: :model do ...@@ -11,7 +11,14 @@ RSpec.describe NotificationSetting, type: :model do
it { is_expected.to validate_presence_of(:user) } it { is_expected.to validate_presence_of(:user) }
it { is_expected.to validate_presence_of(:level) } it { is_expected.to validate_presence_of(:level) }
it { is_expected.to validate_uniqueness_of(:user_id).scoped_to([:source_id, :source_type]).with_message(/already exists in source/) }
describe 'user_id' do
before do
subject.user = create(:user)
end
it { is_expected.to validate_uniqueness_of(:user_id).scoped_to([:source_type, :source_id]).with_message(/already exists in source/) }
end
context "events" do context "events" do
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -11,7 +11,7 @@ describe PagesDomain, models: true do ...@@ -11,7 +11,7 @@ describe PagesDomain, models: true do
context 'is unique' do context 'is unique' do
let(:domain) { 'my.domain.com' } let(:domain) { 'my.domain.com' }
it { is_expected.to validate_uniqueness_of(:domain) } it { is_expected.to validate_uniqueness_of(:domain).case_insensitive }
end end
{ {
......
...@@ -15,7 +15,6 @@ describe JiraService, models: true do ...@@ -15,7 +15,6 @@ describe JiraService, models: true do
end end
it { is_expected.to validate_presence_of(:url) } it { is_expected.to validate_presence_of(:url) }
it { is_expected.to validate_presence_of(:project_key) }
it_behaves_like 'issue tracker service URL attribute', :url it_behaves_like 'issue tracker service URL attribute', :url
end end
...@@ -34,7 +33,6 @@ describe JiraService, models: true do ...@@ -34,7 +33,6 @@ describe JiraService, models: true do
active: true, active: true,
username: 'username', username: 'username',
password: 'test', password: 'test',
project_key: 'TEST',
jira_issue_transition_id: 24, jira_issue_transition_id: 24,
url: 'http://jira.test.com' url: 'http://jira.test.com'
) )
...@@ -88,7 +86,6 @@ describe JiraService, models: true do ...@@ -88,7 +86,6 @@ describe JiraService, models: true do
url: 'http://jira.example.com', url: 'http://jira.example.com',
username: 'gitlab_jira_username', username: 'gitlab_jira_username',
password: 'gitlab_jira_password', password: 'gitlab_jira_password',
project_key: 'GitLabProject',
jira_issue_transition_id: "custom-id" jira_issue_transition_id: "custom-id"
) )
...@@ -196,15 +193,14 @@ describe JiraService, models: true do ...@@ -196,15 +193,14 @@ describe JiraService, models: true do
project: create(:project), project: create(:project),
url: 'http://jira.example.com', url: 'http://jira.example.com',
username: 'jira_username', username: 'jira_username',
password: 'jira_password', password: 'jira_password'
project_key: 'GitLabProject'
) )
end end
def test_settings(api_url) def test_settings(api_url)
project_url = "http://#{api_url}/rest/api/2/project/GitLabProject" test_url = "http://#{api_url}/rest/api/2/serverInfo"
WebMock.stub_request(:get, project_url).with(basic_auth: %w(jira_username jira_password)) WebMock.stub_request(:get, test_url).with(basic_auth: %w(jira_username jira_password)).to_return(body: { url: 'http://url' }.to_json )
jira_service.test_settings jira_service.test_settings
end end
......
...@@ -11,7 +11,7 @@ describe RedirectRoute, models: true do ...@@ -11,7 +11,7 @@ describe RedirectRoute, models: true do
describe 'validations' do describe 'validations' do
it { is_expected.to validate_presence_of(:source) } it { is_expected.to validate_presence_of(:source) }
it { is_expected.to validate_presence_of(:path) } it { is_expected.to validate_presence_of(:path) }
it { is_expected.to validate_uniqueness_of(:path) } it { is_expected.to validate_uniqueness_of(:path).case_insensitive }
end end
describe '.matching_path_and_descendants' do describe '.matching_path_and_descendants' do
......
...@@ -956,21 +956,25 @@ describe Repository, models: true do ...@@ -956,21 +956,25 @@ describe Repository, models: true do
end end
end end
describe '#exists?' do shared_examples 'repo exists check' do
it 'returns true when a repository exists' do it 'returns true when a repository exists' do
expect(repository.exists?).to eq(true) expect(repository.exists?).to eq(true)
end end
it 'returns false when a repository does not exist' do it 'returns false if no full path can be constructed' do
allow(repository).to receive(:refs_directory_exists?).and_return(false) allow(repository).to receive(:path_with_namespace).and_return(nil)
expect(repository.exists?).to eq(false) expect(repository.exists?).to eq(false)
end end
end
it 'returns false when there is no namespace' do describe '#exists?' do
allow(repository).to receive(:path_with_namespace).and_return(nil) context 'when repository_exists is disabled' do
it_behaves_like 'repo exists check'
end
expect(repository.exists?).to eq(false) context 'when repository_exists is enabled', skip_gitaly_mock: true do
it_behaves_like 'repo exists check'
end end
end end
......
...@@ -15,7 +15,7 @@ describe Route, models: true do ...@@ -15,7 +15,7 @@ describe Route, models: true do
it { is_expected.to validate_presence_of(:source) } it { is_expected.to validate_presence_of(:source) }
it { is_expected.to validate_presence_of(:path) } it { is_expected.to validate_presence_of(:path) }
it { is_expected.to validate_uniqueness_of(:path) } it { is_expected.to validate_uniqueness_of(:path).case_insensitive }
end end
describe 'callbacks' do describe 'callbacks' do
......
...@@ -123,7 +123,9 @@ describe User, models: true do ...@@ -123,7 +123,9 @@ describe User, models: true do
end end
it 'validates uniqueness' do it 'validates uniqueness' do
expect(subject).to validate_uniqueness_of(:username).case_insensitive user = build(:user)
expect(user).to validate_uniqueness_of(:username).case_insensitive
end end
end end
......
...@@ -96,17 +96,18 @@ describe Ci::BuildPolicy, :models do ...@@ -96,17 +96,18 @@ describe Ci::BuildPolicy, :models do
end end
end end
describe 'rules for manual actions' do describe 'rules for protected ref' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:build) { create(:ci_build, ref: 'some-ref', pipeline: pipeline) }
before do before do
project.add_developer(user) project.add_developer(user)
end end
shared_examples 'protected ref' do context 'when no one can push or merge to the branch' do
context 'when build is a manual action' do before do
let(:build) do create(:protected_branch, :no_one_can_push,
create(:ci_build, :manual, ref: 'some-ref', pipeline: pipeline) name: build.ref, project: project)
end end
it 'does not include ability to update build' do it 'does not include ability to update build' do
...@@ -114,46 +115,34 @@ describe Ci::BuildPolicy, :models do ...@@ -114,46 +115,34 @@ describe Ci::BuildPolicy, :models do
end end
end end
context 'when build is not a manual action' do context 'when developers can push to the branch' do
let(:build) do before do
create(:ci_build, ref: 'some-ref', pipeline: pipeline) create(:protected_branch, :developers_can_merge,
name: build.ref, project: project)
end end
it 'includes ability to update build' do it 'includes ability to update build' do
expect(policy).to be_allowed :update_build expect(policy).to be_allowed :update_build
end end
end end
end
context 'when build is against a protected branch' do context 'when no one can create the tag' do
before do
create(:protected_branch, :no_one_can_push,
name: 'some-ref', project: project)
end
it_behaves_like 'protected ref'
end
context 'when build is against a protected tag' do
before do before do
create(:protected_tag, :no_one_can_create, create(:protected_tag, :no_one_can_create,
name: 'some-ref', project: project) name: build.ref, project: project)
build.update(tag: true) build.update(tag: true)
end end
it_behaves_like 'protected ref' it 'does not include ability to update build' do
expect(policy).to be_disallowed :update_build
end
end end
context 'when build is against a protected tag but it is not a tag' do context 'when no one can create the tag but it is not a tag' do
before do before do
create(:protected_tag, :no_one_can_create, create(:protected_tag, :no_one_can_create,
name: 'some-ref', project: project) name: build.ref, project: project)
end
context 'when build is a manual action' do
let(:build) do
create(:ci_build, :manual, ref: 'some-ref', pipeline: pipeline)
end end
it 'includes ability to update build' do it 'includes ability to update build' do
...@@ -161,24 +150,5 @@ describe Ci::BuildPolicy, :models do ...@@ -161,24 +150,5 @@ describe Ci::BuildPolicy, :models do
end end
end end
end end
context 'when branch build is assigned to is not protected' do
context 'when build is a manual action' do
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
it 'includes ability to update build' do
expect(policy).to be_allowed :update_build
end
end
context 'when build is not a manual action' do
let(:build) { create(:ci_build, pipeline: pipeline) }
it 'includes ability to update build' do
expect(policy).to be_allowed :update_build
end
end
end
end
end end
end end
require 'spec_helper'
describe Ci::PipelinePolicy, :models do
let(:user) { create(:user) }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:policy) do
described_class.new(user, pipeline)
end
describe 'rules' do
describe 'rules for protected ref' do
let(:project) { create(:project) }
before do
project.add_developer(user)
end
context 'when no one can push or merge to the branch' do
before do
create(:protected_branch, :no_one_can_push,
name: pipeline.ref, project: project)
end
it 'does not include ability to update pipeline' do
expect(policy).to be_disallowed :update_pipeline
end
end
context 'when developers can push to the branch' do
before do
create(:protected_branch, :developers_can_merge,
name: pipeline.ref, project: project)
end
it 'includes ability to update pipeline' do
expect(policy).to be_allowed :update_pipeline
end
end
context 'when no one can create the tag' do
before do
create(:protected_tag, :no_one_can_create,
name: pipeline.ref, project: project)
pipeline.update(tag: true)
end
it 'does not include ability to update pipeline' do
expect(policy).to be_disallowed :update_pipeline
end
end
context 'when no one can create the tag but it is not a tag' do
before do
create(:protected_tag, :no_one_can_create,
name: pipeline.ref, project: project)
end
it 'includes ability to update pipeline' do
expect(policy).to be_allowed :update_pipeline
end
end
end
end
end
...@@ -30,5 +30,25 @@ describe GlobalPolicy, models: true do ...@@ -30,5 +30,25 @@ describe GlobalPolicy, models: true do
it { is_expected.to be_allowed(:read_users_list) } it { is_expected.to be_allowed(:read_users_list) }
end end
end end
context "for an admin" do
let(:current_user) { create(:admin) }
context "when the public level is restricted" do
before do
stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
end
it { is_expected.to be_allowed(:read_users_list) }
end
context "when the public level is not restricted" do
before do
stub_application_setting(restricted_visibility_levels: [])
end
it { is_expected.to be_allowed(:read_users_list) }
end
end
end end
end end
This diff is collapsed.
...@@ -55,7 +55,12 @@ describe API::Triggers do ...@@ -55,7 +55,12 @@ describe API::Triggers do
post api("/projects/#{project.id}/trigger/pipeline"), options.merge(ref: 'other-branch') post api("/projects/#{project.id}/trigger/pipeline"), options.merge(ref: 'other-branch')
expect(response).to have_http_status(400) expect(response).to have_http_status(400)
<<<<<<< HEAD
expect(json_response['message']).to eq('base' => ["Reference not found"]) expect(json_response['message']).to eq('base' => ["Reference not found"])
=======
expect(json_response['message']['base'])
.to contain_exactly('Reference not found')
>>>>>>> upstream/master
end end
context 'Validates variables' do context 'Validates variables' do
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment