summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMayra Cabrera <mcabrera@gitlab.com>2018-06-26 17:39:22 +0000
committerMayra Cabrera <mcabrera@gitlab.com>2018-06-26 17:39:22 +0000
commit005ad8a11ec3a04afa0715675850d90b6d1c8388 (patch)
treeca4c7f4d36190f2b1867542a192ef82e991b3a2e
parentbf968f8a3fd4f969e06e0588407ac04a14cfd7dd (diff)
parent496f49b7c778721ff0e4be96d1365f12cffb2769 (diff)
downloadgitlab-ce-005ad8a11ec3a04afa0715675850d90b6d1c8388.tar.gz
Merge branch '11-0-stable-patch-2' into '11-0-stable'
Prepare 11.0.2 release See merge request gitlab-org/gitlab-ce!20139
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss13
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss1
-rw-r--r--app/assets/stylesheets/framework/header.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss1
-rw-r--r--app/assets/stylesheets/pages/notes.scss8
-rw-r--r--app/controllers/sessions_controller.rb31
-rw-r--r--app/mailers/emails/merge_requests.rb2
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/clusters/applications/prometheus.rb3
-rw-r--r--app/models/concerns/sortable.rb4
-rw-r--r--app/models/merge_request.rb15
-rw-r--r--app/models/project_auto_devops.rb4
-rw-r--r--app/presenters/merge_request_presenter.rb11
-rw-r--r--app/views/devise/sessions/_new_base.html.haml4
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml4
-rw-r--r--app/views/notify/merge_request_unmergeable_email.html.haml6
-rw-r--r--app/views/notify/merge_request_unmergeable_email.text.haml5
-rw-r--r--changelogs/unreleased/48126-fix-prometheus-installation.yml5
-rw-r--r--changelogs/unreleased/48269-wiki-page-returns-error-code-502.yml5
-rw-r--r--changelogs/unreleased/48339-sorting-by-name-on-explore-projects-page-renders-a-500-error-when-logged-in.yml5
-rw-r--r--changelogs/unreleased/6591-dont-load-omniauth-if-not-enabled.yml5
-rw-r--r--changelogs/unreleased/6598-notify-only-open-unmergeable-mr.yml5
-rw-r--r--changelogs/unreleased/bvl-dont-generate-mo.yml5
-rw-r--r--changelogs/unreleased/enforce-variable-value-to-be-a-string.yml5
-rw-r--r--changelogs/unreleased/fix-alert-btn.yml5
-rw-r--r--changelogs/unreleased/fix-favicon-cross-origin.yml5
-rw-r--r--changelogs/unreleased/mk-rake-task-verify-remote-files.yml5
-rw-r--r--config/initializers/devise.rb4
-rw-r--r--config/karma.config.js1
-rw-r--r--config/webpack.config.js6
-rw-r--r--doc/administration/raketasks/check.md7
-rw-r--r--doc/api/runners.md12
-rw-r--r--doc/development/query_recorder.md1
-rw-r--r--doc/install/installation.md10
-rw-r--r--doc/install/kubernetes/gitlab_chart.md137
-rw-r--r--doc/install/kubernetes/index.md51
-rw-r--r--doc/install/kubernetes/preparation/connect.md31
-rw-r--r--doc/install/kubernetes/preparation/eks.md44
-rw-r--r--doc/install/kubernetes/preparation/networking.md36
-rw-r--r--doc/install/kubernetes/preparation/rbac.md16
-rw-r--r--doc/install/kubernetes/preparation/tiller.md94
-rw-r--r--doc/install/kubernetes/preparation/tools_installation.md19
-rw-r--r--doc/integration/recaptcha.md19
-rw-r--r--doc/topics/autodevops/img/auto_monitoring.pngbin69473 -> 26675 bytes
-rw-r--r--doc/topics/autodevops/img/guide_choose_gke.pngbin0 -> 7895 bytes
-rw-r--r--doc/topics/autodevops/img/guide_cluster_apps.pngbin0 -> 28667 bytes
-rw-r--r--doc/topics/autodevops/img/guide_connect_cluster.pngbin38724 -> 15225 bytes
-rw-r--r--doc/topics/autodevops/img/guide_create_cluster.pngbin0 -> 18915 bytes
-rw-r--r--doc/topics/autodevops/img/guide_create_project.pngbin0 -> 17704 bytes
-rw-r--r--doc/topics/autodevops/img/guide_enable_autodevops.pngbin0 -> 27763 bytes
-rw-r--r--doc/topics/autodevops/img/guide_environments.pngbin0 -> 8570 bytes
-rw-r--r--doc/topics/autodevops/img/guide_environments_metrics.pngbin0 -> 10231 bytes
-rw-r--r--doc/topics/autodevops/img/guide_first_pipeline.pngbin0 -> 10350 bytes
-rw-r--r--doc/topics/autodevops/img/guide_gitlab_gke_details.pngbin0 -> 22677 bytes
-rw-r--r--doc/topics/autodevops/img/guide_gke_apis_after.pngbin0 -> 26811 bytes
-rw-r--r--doc/topics/autodevops/img/guide_gke_apis_before.pngbin0 -> 14882 bytes
-rw-r--r--doc/topics/autodevops/img/guide_google_auth.pngbin0 -> 12729 bytes
-rw-r--r--doc/topics/autodevops/img/guide_google_signin.pngbin0 -> 14343 bytes
-rw-r--r--doc/topics/autodevops/img/guide_ide_commit.pngbin0 -> 22035 bytes
-rw-r--r--doc/topics/autodevops/img/guide_integration.pngbin44263 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/guide_merge_request.pngbin0 -> 31157 bytes
-rw-r--r--doc/topics/autodevops/img/guide_merge_request_ide.pngbin0 -> 35052 bytes
-rw-r--r--doc/topics/autodevops/img/guide_merge_request_review_app.pngbin0 -> 25596 bytes
-rw-r--r--doc/topics/autodevops/img/guide_pipeline_stages.pngbin0 -> 12557 bytes
-rw-r--r--doc/topics/autodevops/img/guide_project_landing_page.pngbin0 -> 19227 bytes
-rw-r--r--doc/topics/autodevops/img/guide_project_template.pngbin0 -> 14699 bytes
-rw-r--r--doc/topics/autodevops/img/guide_secret.pngbin16233 -> 0 bytes
-rw-r--r--doc/topics/autodevops/img/rollout_staging_disabled.pngbin13837 -> 13834 bytes
-rw-r--r--doc/topics/autodevops/img/rollout_staging_enabled.pngbin17306 -> 17299 bytes
-rw-r--r--doc/topics/autodevops/img/staging_enabled.pngbin17929 -> 17922 bytes
-rw-r--r--doc/topics/autodevops/index.md33
-rw-r--r--doc/topics/autodevops/quick_start_guide.md347
-rw-r--r--doc/update/10.8-to-11.0.md12
-rw-r--r--doc/user/project/clusters/index.md89
-rw-r--r--doc/workflow/notifications.md2
-rw-r--r--doc/workflow/todos.md2
-rw-r--r--lib/backup/repository.rb2
-rw-r--r--lib/banzai/filter/gollum_tags_filter.rb6
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb3
-rw-r--r--lib/gitlab/favicon.rb20
-rw-r--r--lib/gitlab/git/repository.rb6
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb11
-rw-r--r--lib/gitlab/verify/batch_verifier.rb59
-rw-r--r--lib/gitlab/verify/job_artifacts.rb10
-rw-r--r--lib/gitlab/verify/lfs_objects.rb12
-rw-r--r--lib/gitlab/verify/rake_task.rb2
-rw-r--r--lib/gitlab/verify/uploads.rb12
-rw-r--r--lib/tasks/gettext.rake1
-rw-r--r--qa/qa.rb13
-rw-r--r--qa/qa/factory/repository/project_push.rb34
-rw-r--r--qa/qa/factory/repository/push.rb22
-rw-r--r--qa/qa/factory/repository/wiki_push.rb32
-rw-r--r--qa/qa/factory/resource/branch.rb4
-rw-r--r--qa/qa/factory/resource/merge_request.rb4
-rw-r--r--qa/qa/factory/resource/wiki.rb25
-rw-r--r--qa/qa/page/menu/side.rb7
-rw-r--r--qa/qa/page/project/show.rb41
-rw-r--r--qa/qa/page/project/wiki/edit.rb27
-rw-r--r--qa/qa/page/project/wiki/new.rb45
-rw-r--r--qa/qa/page/project/wiki/show.rb19
-rw-r--r--qa/qa/page/shared/clone_panel.rb50
-rw-r--r--qa/qa/specs/features/merge_request/rebase_spec.rb2
-rw-r--r--qa/qa/specs/features/merge_request/squash_spec.rb2
-rw-r--r--qa/qa/specs/features/project/activity_spec.rb2
-rw-r--r--qa/qa/specs/features/project/auto_devops_spec.rb2
-rw-r--r--qa/qa/specs/features/project/deploy_key_clone_spec.rb2
-rw-r--r--qa/qa/specs/features/project/pipelines_spec.rb2
-rw-r--r--qa/qa/specs/features/project/wikis_spec.rb45
-rw-r--r--qa/qa/specs/features/repository/protected_branches_spec.rb26
-rw-r--r--qa/qa/specs/features/repository/push_spec.rb2
-rw-r--r--spec/controllers/sessions_controller_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb64
-rw-r--r--spec/lib/gitlab/ci/variables/collection_spec.rb12
-rw-r--r--spec/lib/gitlab/favicon_spec.rb15
-rw-r--r--spec/lib/gitlab/kubernetes/helm/api_spec.rb8
-rw-r--r--spec/lib/gitlab/kubernetes/helm/install_command_spec.rb62
-rw-r--r--spec/lib/gitlab/verify/job_artifacts_spec.rb29
-rw-r--r--spec/lib/gitlab/verify/lfs_objects_spec.rb25
-rw-r--r--spec/lib/gitlab/verify/uploads_spec.rb56
-rw-r--r--spec/mailers/notify_spec.rb8
-rw-r--r--spec/models/ci/build_spec.rb6
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb1
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb1
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb1
-rw-r--r--spec/models/clusters/applications/runner_spec.rb1
-rw-r--r--spec/models/concerns/sortable_spec.rb18
-rw-r--r--spec/models/merge_request_spec.rb62
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb35
-rw-r--r--spec/views/devise/shared/_signin_box.html.haml_spec.rb1
130 files changed, 1644 insertions, 497 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 512238e139a..7f4c1320264 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -873,7 +873,7 @@ GEM
activesupport (>= 4.2)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
- sprockets (3.7.1)
+ sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.1)
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index 391db0f0603..67469c133cd 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -89,11 +89,6 @@ a {
color: $gl-link-color;
}
-a:not(.btn):focus,
-a:not(.btn):active {
- text-decoration: underline;
-}
-
hr {
overflow: hidden;
}
@@ -178,6 +173,12 @@ table {
display: none;
}
+h3.popover-header {
+ // Default bootstrap popovers use <h3>
+ // which we default to having a top margin
+ margin-top: 0;
+}
+
// Add to .label so that old system notes that are saved to the db
// will still receive the correct styling
.badge,
@@ -300,7 +301,7 @@ pre code {
color: $white-light;
h4,
- a,
+ a:not(.btn),
.alert-link {
color: $white-light;
}
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index cccd1a6d942..9cbaaa5dc8d 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -193,7 +193,6 @@
&:focus {
background: $link-active-background;
color: $gl-text-color;
- text-decoration: none;
}
}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index db59c91e375..2fa71b23314 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -558,7 +558,7 @@
background: $white-light;
border-bottom: 1px solid $white-normal;
- .center-logo {
+ .mx-auto {
margin: 8px 0;
text-align: center;
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index f06c9dcdf8c..e888063461e 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -61,6 +61,7 @@
.diff-line-num {
width: 50px;
+ position: relative;
a {
transition: none;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 299eda53140..6e44fca7a1b 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -624,20 +624,18 @@ ul.notes {
.line_holder .is-over:not(.no-comment-btn) {
.add-diff-note {
opacity: 1;
+ z-index: 101;
}
}
.add-diff-note {
@include btn-comment-icon;
opacity: 0;
- margin-top: -2px;
margin-left: -55px;
position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
z-index: 10;
-
- .new & {
- margin-top: -10px;
- }
}
.discussion-body,
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 1a339f76d26..7aa277b3614 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -3,21 +3,27 @@ class SessionsController < Devise::SessionsController
include AuthenticatesWithTwoFactor
include Devise::Controllers::Rememberable
include Recaptcha::ClientHelper
+ include Recaptcha::Verify
skip_before_action :check_two_factor_requirement, only: [:destroy]
prepend_before_action :check_initial_setup, only: [:new]
prepend_before_action :authenticate_with_two_factor,
if: :two_factor_enabled?, only: [:create]
+ prepend_before_action :check_captcha, only: [:create]
prepend_before_action :store_redirect_uri, only: [:new]
+ prepend_before_action :ldap_servers, only: [:new, :create]
before_action :auto_sign_in_with_provider, only: [:new]
before_action :load_recaptcha
after_action :log_failed_login, only: [:new], if: :failed_login?
+ helper_method :captcha_enabled?
+
+ CAPTCHA_HEADER = 'X-GitLab-Show-Login-Captcha'.freeze
+
def new
set_minimum_password_length
- @ldap_servers = Gitlab::Auth::LDAP::Config.available_servers
super
end
@@ -46,6 +52,25 @@ class SessionsController < Devise::SessionsController
private
+ def captcha_enabled?
+ request.headers[CAPTCHA_HEADER] && Gitlab::Recaptcha.enabled?
+ end
+
+ # From https://github.com/plataformatec/devise/wiki/How-To:-Use-Recaptcha-with-Devise#devisepasswordscontroller
+ def check_captcha
+ return unless user_params[:password].present?
+ return unless captcha_enabled?
+ return unless Gitlab::Recaptcha.load_configurations!
+
+ unless verify_recaptcha
+ self.resource = resource_class.new
+ flash[:alert] = 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
+ flash.delete :recaptcha_error
+
+ respond_with_navigational(resource) { render :new }
+ end
+ end
+
def log_failed_login
Gitlab::AppLogger.info("Failed Login: username=#{user_params[:login]} ip=#{request.remote_ip}")
end
@@ -152,6 +177,10 @@ class SessionsController < Devise::SessionsController
Gitlab::Recaptcha.load_configurations!
end
+ def ldap_servers
+ @ldap_servers ||= Gitlab::Auth::LDAP::Config.available_servers
+ end
+
def authentication_method
if user_params[:otp_attempt]
"two-factor"
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 5ba3a4a322c..70509e9066d 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -59,8 +59,6 @@ module Emails
def merge_request_unmergeable_email(recipient_id, merge_request_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
- @reasons = MergeRequestPresenter.new(@merge_request, current_user: current_user).unmergeable_reasons
-
mail_answer_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, recipient_id, reason))
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index eecd86349e4..cf0803675dd 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -557,9 +557,9 @@ module Ci
.append(key: 'CI_PIPELINE_IID', value: iid.to_s)
.append(key: 'CI_CONFIG_PATH', value: ci_yaml_file_path)
.append(key: 'CI_PIPELINE_SOURCE', value: source.to_s)
- .append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message)
- .append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title)
- .append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description)
+ .append(key: 'CI_COMMIT_MESSAGE', value: git_commit_message.to_s)
+ .append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
+ .append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
end
def queued_duration
diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb
index c702c4ee807..48137c2ed68 100644
--- a/app/models/clusters/applications/prometheus.rb
+++ b/app/models/clusters/applications/prometheus.rb
@@ -3,7 +3,7 @@ module Clusters
class Prometheus < ActiveRecord::Base
include PrometheusAdapter
- VERSION = "2.0.0".freeze
+ VERSION = '6.7.3'.freeze
self.table_name = 'clusters_applications_prometheus'
@@ -37,6 +37,7 @@ module Clusters
Gitlab::Kubernetes::Helm::InstallCommand.new(
name,
chart: chart,
+ version: version,
values: values
)
end
diff --git a/app/models/concerns/sortable.rb b/app/models/concerns/sortable.rb
index db7254c27e0..cb76ae971d4 100644
--- a/app/models/concerns/sortable.rb
+++ b/app/models/concerns/sortable.rb
@@ -12,8 +12,8 @@ module Sortable
scope :order_created_asc, -> { reorder(created_at: :asc) }
scope :order_updated_desc, -> { reorder(updated_at: :desc) }
scope :order_updated_asc, -> { reorder(updated_at: :asc) }
- scope :order_name_asc, -> { reorder("lower(name) asc") }
- scope :order_name_desc, -> { reorder("lower(name) desc") }
+ scope :order_name_asc, -> { reorder(Arel::Nodes::Ascending.new(arel_table[:name].lower)) }
+ scope :order_name_desc, -> { reorder(Arel::Nodes::Descending.new(arel_table[:name].lower)) }
end
module ClassMethods
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 324065c1162..91e6d391986 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -128,8 +128,15 @@ class MergeRequest < ActiveRecord::Base
end
after_transition unchecked: :cannot_be_merged do |merge_request, transition|
- NotificationService.new.merge_request_unmergeable(merge_request)
- TodoService.new.merge_request_became_unmergeable(merge_request)
+ begin
+ if merge_request.notify_conflict?
+ NotificationService.new.merge_request_unmergeable(merge_request)
+ TodoService.new.merge_request_became_unmergeable(merge_request)
+ end
+ rescue Gitlab::Git::CommandError
+ # Checking mergeability can trigger exception, e.g. non-utf8
+ # We ignore this type of errors.
+ end
end
def check_state?(merge_status)
@@ -706,6 +713,10 @@ class MergeRequest < ActiveRecord::Base
should_remove_source_branch? || force_remove_source_branch?
end
+ def notify_conflict?
+ (opened? || locked?) && !project.repository.can_be_merged?(diff_head_sha, target_branch)
+ end
+
def related_notes
# Fetch comments only from last 100 commits
commits_for_notes_limit = 100
diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb
index d7d6aaceb27..faa831b1949 100644
--- a/app/models/project_auto_devops.rb
+++ b/app/models/project_auto_devops.rb
@@ -29,8 +29,8 @@ class ProjectAutoDevops < ActiveRecord::Base
end
if manual?
- variables.append(key: 'STAGING_ENABLED', value: 1)
- variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: 1)
+ variables.append(key: 'STAGING_ENABLED', value: '1')
+ variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: '1')
end
end
end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 8d466c33510..eb54ab2cda6 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -20,17 +20,6 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
end
- def unmergeable_reasons
- strong_memoize(:unmergeable_reasons) do
- reasons = []
- reasons << "no commits" if merge_request.has_no_commits?
- reasons << "source branch is missing" unless merge_request.source_branch_exists?
- reasons << "target branch is missing" unless merge_request.target_branch_exists?
- reasons << "has merge conflicts" unless merge_request.project.repository.can_be_merged?(merge_request.diff_head_sha, merge_request.target_branch)
- reasons
- end
- end
-
def cancel_merge_when_pipeline_succeeds_path
if can_cancel_merge_when_pipeline_succeeds?(current_user)
cancel_merge_when_pipeline_succeeds_project_merge_request_path(project, merge_request)
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index c45d2214592..0ee563ac066 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -12,5 +12,9 @@
%span Remember me
.float-right.forgot-password
= link_to "Forgot your password?", new_password_path(:user)
+ %div
+ - if captcha_enabled?
+ = recaptcha_tags
+
.submit-container.move-submit-down
= f.submit "Sign in", class: "btn btn-save"
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index 087af61235b..58c585a29ff 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -3,8 +3,8 @@
%li.nav-item
= link_to "Crowd", "#crowd", class: 'nav-link active', 'data-toggle' => 'tab'
- @ldap_servers.each_with_index do |server, i|
- %li.nav-item{ class: active_when(i.zero? && !crowd_enabled?) }
- = link_to server['label'], "##{server['provider_name']}", class: 'nav-link', 'data-toggle' => 'tab'
+ %li.nav-item
+ = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i.zero? && !crowd_enabled?)}", 'data-toggle' => 'tab'
- if password_authentication_enabled_for_web?
%li.nav-item
= link_to 'Standard', '#login-pane', class: 'nav-link', 'data-toggle' => 'tab'
diff --git a/app/views/notify/merge_request_unmergeable_email.html.haml b/app/views/notify/merge_request_unmergeable_email.html.haml
index 578fa1fbce7..7ec0c1ef390 100644
--- a/app/views/notify/merge_request_unmergeable_email.html.haml
+++ b/app/views/notify/merge_request_unmergeable_email.html.haml
@@ -1,6 +1,2 @@
%p
- Merge Request #{link_to @merge_request.to_reference, project_merge_request_url(@merge_request.target_project, @merge_request)} can no longer be merged due to the following #{'reason'.pluralize(@reasons.count)}:
-
- %ul
- - @reasons.each do |reason|
- %li= reason
+ Merge Request #{link_to @merge_request.to_reference, project_merge_request_url(@merge_request.target_project, @merge_request)} can no longer be merged due to conflict.
diff --git a/app/views/notify/merge_request_unmergeable_email.text.haml b/app/views/notify/merge_request_unmergeable_email.text.haml
index e4f9f1bf5e7..dcdd6db69d6 100644
--- a/app/views/notify/merge_request_unmergeable_email.text.haml
+++ b/app/views/notify/merge_request_unmergeable_email.text.haml
@@ -1,7 +1,4 @@
-Merge Request #{@merge_request.to_reference} can no longer be merged due to the following #{'reason'.pluralize(@reasons.count)}:
-
-- @reasons.each do |reason|
- * #{reason}
+Merge Request #{@merge_request.to_reference} can no longer be merged due to conflict.
Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)}
diff --git a/changelogs/unreleased/48126-fix-prometheus-installation.yml b/changelogs/unreleased/48126-fix-prometheus-installation.yml
new file mode 100644
index 00000000000..e6ab9c46fbf
--- /dev/null
+++ b/changelogs/unreleased/48126-fix-prometheus-installation.yml
@@ -0,0 +1,5 @@
+---
+title: Specify chart version when installing applications on Clusters
+merge_request: 20010
+author:
+type: fixed
diff --git a/changelogs/unreleased/48269-wiki-page-returns-error-code-502.yml b/changelogs/unreleased/48269-wiki-page-returns-error-code-502.yml
new file mode 100644
index 00000000000..d3830e5b8c6
--- /dev/null
+++ b/changelogs/unreleased/48269-wiki-page-returns-error-code-502.yml
@@ -0,0 +1,5 @@
+---
+title: Remove performance bottleneck preventing large wiki pages from displaying
+merge_request: 20174
+author:
+type: performance
diff --git a/changelogs/unreleased/48339-sorting-by-name-on-explore-projects-page-renders-a-500-error-when-logged-in.yml b/changelogs/unreleased/48339-sorting-by-name-on-explore-projects-page-renders-a-500-error-when-logged-in.yml
new file mode 100644
index 00000000000..933d82b57c5
--- /dev/null
+++ b/changelogs/unreleased/48339-sorting-by-name-on-explore-projects-page-renders-a-500-error-when-logged-in.yml
@@ -0,0 +1,5 @@
+---
+title: Fix sorting by name on explore projects page
+merge_request: 20162
+author:
+type: fixed
diff --git a/changelogs/unreleased/6591-dont-load-omniauth-if-not-enabled.yml b/changelogs/unreleased/6591-dont-load-omniauth-if-not-enabled.yml
new file mode 100644
index 00000000000..dd1c7e6955d
--- /dev/null
+++ b/changelogs/unreleased/6591-dont-load-omniauth-if-not-enabled.yml
@@ -0,0 +1,5 @@
+---
+title: Only load Omniauth if enabled
+merge_request: 20132
+author:
+type: fixed
diff --git a/changelogs/unreleased/6598-notify-only-open-unmergeable-mr.yml b/changelogs/unreleased/6598-notify-only-open-unmergeable-mr.yml
new file mode 100644
index 00000000000..ae92c20fa1a
--- /dev/null
+++ b/changelogs/unreleased/6598-notify-only-open-unmergeable-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Notify conflict for only open merge request
+merge_request: 20125
+author:
+type: fixed
diff --git a/changelogs/unreleased/bvl-dont-generate-mo.yml b/changelogs/unreleased/bvl-dont-generate-mo.yml
new file mode 100644
index 00000000000..19b8e873849
--- /dev/null
+++ b/changelogs/unreleased/bvl-dont-generate-mo.yml
@@ -0,0 +1,5 @@
+---
+title: Fix invalid fuzzy translations being generated during installation
+merge_request: 20048
+author:
+type: fixed
diff --git a/changelogs/unreleased/enforce-variable-value-to-be-a-string.yml b/changelogs/unreleased/enforce-variable-value-to-be-a-string.yml
new file mode 100644
index 00000000000..e2a932ee5bb
--- /dev/null
+++ b/changelogs/unreleased/enforce-variable-value-to-be-a-string.yml
@@ -0,0 +1,5 @@
+---
+title: Fix incremental rollouts for Auto DevOps
+merge_request: 20061
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-alert-btn.yml b/changelogs/unreleased/fix-alert-btn.yml
new file mode 100644
index 00000000000..d8bf561f05a
--- /dev/null
+++ b/changelogs/unreleased/fix-alert-btn.yml
@@ -0,0 +1,5 @@
+---
+title: Fix alert button styling so that they don't show up white
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-favicon-cross-origin.yml b/changelogs/unreleased/fix-favicon-cross-origin.yml
new file mode 100644
index 00000000000..3317781e222
--- /dev/null
+++ b/changelogs/unreleased/fix-favicon-cross-origin.yml
@@ -0,0 +1,5 @@
+---
+title: Serve favicon image always from the main GitLab domain to avoid issues with CORS
+merge_request: 19810
+author: Alexis Reigel
+type: fixed
diff --git a/changelogs/unreleased/mk-rake-task-verify-remote-files.yml b/changelogs/unreleased/mk-rake-task-verify-remote-files.yml
new file mode 100644
index 00000000000..772aa11d89b
--- /dev/null
+++ b/changelogs/unreleased/mk-rake-task-verify-remote-files.yml
@@ -0,0 +1,5 @@
+---
+title: Add support for verifying remote uploads, artifacts, and LFS objects in check rake tasks
+merge_request: 19501
+author:
+type: added
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 362b9cc9a88..d051b699102 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -219,5 +219,7 @@ Devise.setup do |config|
end
end
- Gitlab::OmniauthInitializer.new(config).execute(Gitlab.config.omniauth.providers)
+ if Gitlab.config.omniauth.enabled
+ Gitlab::OmniauthInitializer.new(config).execute(Gitlab.config.omniauth.providers)
+ end
end
diff --git a/config/karma.config.js b/config/karma.config.js
index 28a688797d9..84810332dc2 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -15,6 +15,7 @@ function fatalError(message) {
// disable problematic options
webpackConfig.entry = undefined;
webpackConfig.mode = 'development';
+webpackConfig.optimization.nodeEnv = false;
webpackConfig.optimization.runtimeChunk = false;
webpackConfig.optimization.splitChunks = false;
diff --git a/config/webpack.config.js b/config/webpack.config.js
index b1e378f6c27..583f05f2fb7 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -16,10 +16,13 @@ const DEV_SERVER_PORT = parseInt(process.env.DEV_SERVER_PORT, 10) || 3808;
const DEV_SERVER_LIVERELOAD = IS_DEV_SERVER && process.env.DEV_SERVER_LIVERELOAD !== 'false';
const WEBPACK_REPORT = process.env.WEBPACK_REPORT;
const NO_COMPRESSION = process.env.NO_COMPRESSION;
+const NO_SOURCEMAPS = process.env.NO_SOURCEMAPS;
const VUE_VERSION = require('vue/package.json').version;
const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
+const devtool = IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map';
+
let autoEntriesCount = 0;
let watchAutoEntries = [];
const defaultEntries = ['./main'];
@@ -171,7 +174,6 @@ module.exports = {
},
optimization: {
- nodeEnv: false,
runtimeChunk: 'single',
splitChunks: {
maxInitialRequests: 4,
@@ -286,7 +288,7 @@ module.exports = {
inline: DEV_SERVER_LIVERELOAD,
},
- devtool: IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map',
+ devtool: NO_SOURCEMAPS ? false : devtool,
// sqljs requires fs
node: { fs: 'empty' },
diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md
index 7d34d35e7d1..2649bf61d74 100644
--- a/doc/administration/raketasks/check.md
+++ b/doc/administration/raketasks/check.md
@@ -78,9 +78,10 @@ Example output:
## Uploaded Files Integrity
-Various types of file can be uploaded to a GitLab installation by users.
-Checksums are generated and stored in the database upon upload, and integrity
-checks using those checksums can be run. These checks also detect missing files.
+Various types of files can be uploaded to a GitLab installation by users.
+These integrity checks can detect missing files. Additionally, for locally
+stored files, checksums are generated and stored in the database upon upload,
+and these checks will verify them against current files.
Currently, integrity checks are supported for the following types of file:
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 3ca07ce9795..ac814bbf19a 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -30,6 +30,7 @@ Example response:
"description": "test-1-20150125",
"id": 6,
"is_shared": false,
+ "ip_address": "127.0.0.1",
"name": null,
"online": true,
"status": "online"
@@ -38,6 +39,7 @@ Example response:
"active": true,
"description": "test-2-20150125",
"id": 8,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"name": null,
"online": false,
@@ -72,6 +74,7 @@ Example response:
"active": true,
"description": "shared-runner-1",
"id": 1,
+ "ip_address": "127.0.0.1",
"is_shared": true,
"name": null,
"online": true,
@@ -81,6 +84,7 @@ Example response:
"active": true,
"description": "shared-runner-2",
"id": 3,
+ "ip_address": "127.0.0.1",
"is_shared": true,
"name": null,
"online": false
@@ -90,6 +94,7 @@ Example response:
"active": true,
"description": "test-1-20150125",
"id": 6,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"name": null,
"online": true
@@ -99,6 +104,7 @@ Example response:
"active": true,
"description": "test-2-20150125",
"id": 8,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"name": null,
"online": false,
@@ -131,6 +137,7 @@ Example response:
"architecture": null,
"description": "test-1-20150125",
"id": 6,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"contacted_at": "2016-01-25T16:39:48.066Z",
"name": null,
@@ -189,6 +196,7 @@ Example response:
"architecture": null,
"description": "test-1-20150125-test",
"id": 6,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"contacted_at": "2016-01-25T16:39:48.066Z",
"name": null,
@@ -257,6 +265,7 @@ Example response:
[
{
"id": 2,
+ "ip_address": "127.0.0.1",
"status": "running",
"stage": "test",
"name": "test",
@@ -345,6 +354,7 @@ Example response:
"active": true,
"description": "test-2-20150125",
"id": 8,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"name": null,
"online": false,
@@ -354,6 +364,7 @@ Example response:
"active": true,
"description": "development_runner",
"id": 5,
+ "ip_address": "127.0.0.1",
"is_shared": true,
"name": null,
"online": true
@@ -386,6 +397,7 @@ Example response:
"active": true,
"description": "test-2016-02-01",
"id": 9,
+ "ip_address": "127.0.0.1",
"is_shared": false,
"name": null,
"online": true,
diff --git a/doc/development/query_recorder.md b/doc/development/query_recorder.md
index 61e5e1afede..2167ed57428 100644
--- a/doc/development/query_recorder.md
+++ b/doc/development/query_recorder.md
@@ -28,6 +28,7 @@ By default, QueryRecorder will ignore cached queries in the count. However, it m
all queries to avoid introducing an N+1 query that may be masked by the statement cache. To do this,
pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher:
+```
it "avoids N+1 database queries" do
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }.count
create_list(:issue, 5)
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 6cd1fb4c2d7..ef415246583 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -154,12 +154,12 @@ page](https://golang.org/dl).
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-
- curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
- echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
+
+ curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
+ echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
- rm go1.8.3.linux-amd64.tar.gz
+ rm go1.10.3.linux-amd64.tar.gz
## 4. Node
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 429519a92e1..48f3df1925a 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -1,6 +1,137 @@
# GitLab Helm Chart
-> **Note:** This chart is currently in alpha.
+> **Note:** The chart is currently **beta**, if you encounter any problems please [open an issue](https://gitlab.com/charts/gitlab/issues/new).
-The cloud native `gitlab` chart is the next generation Helm chart, currently in alpha, and will replace the [`gitlab-omnibus`](gitlab_omnibus.md) chart. It will support large deployments with horizontal scaling of individual GitLab components.
+For more information on available GitLab Helm Charts, please see our [overview](index.md#chart-overview).
-Installation instructions and known issues during alpha are available at the [project page](https://gitlab.com/charts/gitlab/). \ No newline at end of file
+## Introduction
+
+The `gitlab` chart is the best way to operate GitLab on Kubernetes. This chart contains all the required components to get started, and can scale to large deployments.
+
+The default deployment includes:
+
+- Core GitLab components: Unicorn, Shell, Workhorse, Registry, Sidekiq, and Gitaly
+- Optional dependencies: Postgres, Redis, Minio
+- An auto-scaling, unprivileged [GitLab Runner](https://docs.gitlab.com/runner/) using the Kubernetes executor
+- Automatically provisioned SSL via [Let's Encrypt](https://letsencrypt.org/).
+
+### Limitations
+
+Some features and functions are not currently available in the beta release:
+* [GitLab Pages](../../user/project/pages/)
+* [Reply by email](../../administration/reply_by_email.html)
+* [Project templates](../../gitlab-basics/create-project.html)
+* [Project import/export](../../user/project/settings/import_export.html)
+* [Geo](https://docs.gitlab.com/ee/administration/geo/replication/)
+
+Currently out of scope:
+* [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/)
+* [MySQL support](https://docs.gitlab.com/omnibus/settings/database.html#using-a-mysql-database-management-server-enterprise-edition-only)
+
+## Prerequisites
+
+In order to deploy GitLab on Kubernetes, a few prerequisites are required.
+
+1. `helm` and `kubectl` [installed on your computer](preparation/tools_installation.md).
+1. A Kubernetes cluster, version 1.8 or higher. 6vCPU and 16GB of RAM is recommended.
+ * [Google GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/creating-a-container-cluster)
+ * [Amazon EKS](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html)
+ * [Microsoft AKS](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough-portal)
+1. A [wildcard DNS entry and external IP address](preparation/networking.md)
+1. [Authenticate and connect](preparation/connect.md) to the cluster
+1. Configure and initialize [Helm Tiller](preparation/tiller.md).
+
+## Configuring and Installing GitLab
+
+> **Note**: For deployments to Amazon EKS, there are [additional configuration requirements](preparation/eks.md).
+
+For simple deployments, running all services within Kubernetes, only three parameters are required:
+- `global.hosts.domain`: the [base domain](preparation/networking.md) of the wildcard host entry. For example, `mycompany.io` if the wild card entry is `*.mycompany.io`.
+- `global.hosts.externalIP`: the [external IP](preparation/networking.md) which the wildcard DNS resolves to.
+- `certmanager-issuer.email`: Email address to use when requesting new SSL certificates from Let's Encrypt.
+
+For enterprise deployments, or to utilize advanced settings, please use the instructions in the [`gitlab` chart project](https://gitlab.com/charts/gitlab) for the most up to date directions.
+- [External Postgres, Redis, and other dependencies](https://gitlab.com/charts/gitlab/tree/master/doc/advanced)
+- [Persistence settings](https://gitlab.com/charts/gitlab/blob/master/doc/installation/storage.md)
+- [Manual TLS certificates](https://gitlab.com/charts/gitlab/blob/master/doc/installation/tls.md)
+- [Manual secret creation](https://gitlab.com/charts/gitlab/blob/master/doc/installation/secrets.md)
+
+For additional configuration options, consult the [full list of settings](https://gitlab.com/charts/gitlab/blob/master/doc/installation/command-line-options.md).
+
+## Installing GitLab using the Helm Chart
+
+Once you have all of your configuration options collected, we can get any dependencies and
+run helm. In this example, we've named our helm release "gitlab".
+
+```
+helm repo add gitlab https://charts.gitlab.io/
+helm update
+helm upgrade --install gitlab gitlab/gitlab \
+ --timeout 600 \
+ --set global.hosts.domain=example.local \
+ --set global.hosts.externalIP=10.10.10.10 \
+ --set certmanager-issuer.email=me@example.local
+```
+
+### Monitoring the Deployment
+
+This will output the list of resources installed once the deployment finishes which may take 5-10 minutes.
+
+The status of the deployment can be checked by running `helm status gitlab` which can also be done while
+the deployment is taking place if you run the command in another terminal.
+
+### Initial login
+
+You can access the GitLab instance by visiting the domain name beginning with `gitlab.` followed by the domain specified during installation. From the example above, the URL would be `https://gitlab.example.local`.
+
+If you manually created the secret for initial root password, you
+can use that to sign in as `root` user. If not, Gitlab automatically
+created a random password for `root` user. This can be extracted by the
+following command (replace `<name>` by name of the release - which is `gitlab`
+if you used the command above).
+
+```
+kubectl get secret <name>-gitlab-initial-root-password -ojsonpath={.data.password} | base64 --decode
+```
+
+## Outgoing email
+
+By default outgoing email is disabled. To enable it, provide details for your SMTP server
+using the `global.smtp` and `global.email` settings. You can find details for these settings in the
+[command line options](https://gitlab.com/charts/gitlab/blob/master/doc/installation/command-line-options.md#email-configuration).
+
+If your SMTP server requires authentication make sure to read the section on providing
+your password in the [secrets documentation](https://gitlab.com/charts/gitlab/blob/master/doc/installation/secrets.md#smtp-password).
+You can disable authentication settings with `--set global.smtp.authentication=""`.
+
+If your Kubernetes cluster is on GKE, be aware that smtp [ports 25, 465, and 587
+are blocked](https://cloud.google.com/compute/docs/tutorials/sending-mail/#using_standard_email_ports).
+
+## Deploying the Community Edition
+
+To deploy the Community Edition, include these options in your `helm install` command:
+
+```shell
+--set gitlab.migrations.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-rails-ce
+--set gitlab.sidekiq.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-sidekiq-ce
+--set gitlab.unicorn.image.repository=registry.gitlab.com/gitlab-org/build/cng/gitlab-unicorn-ce
+```
+
+## Updating GitLab using the Helm Chart
+
+Once your GitLab Chart is installed, configuration changes and chart updates
+should be done using `helm upgrade`:
+
+```bash
+helm upgrade -f values.yaml gitlab gitlab/gitlab
+```
+
+## Uninstalling GitLab using the Helm Chart
+
+To uninstall the GitLab Chart, run the following:
+
+```bash
+helm delete gitlab
+```
+
+[kube-srv]: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
+[storageclass]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#storageclasses
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
index aeaa739edab..6419a9dcb69 100644
--- a/doc/install/kubernetes/index.md
+++ b/doc/install/kubernetes/index.md
@@ -4,7 +4,7 @@ description: 'Read through the different methods to deploy GitLab on Kubernetes.
# Installing GitLab on Kubernetes
-> **Note**: These charts have been tested on Google Kubernetes Engine and Azure Container Service. Other Kubernetes installations may work as well, if not please [open an issue](https://gitlab.com/charts/charts.gitlab.io/issues).
+> **Note**: These charts have been tested on Google Kubernetes Engine. Other Kubernetes installations may work as well, if not please [open an issue](https://gitlab.com/charts/issues).
The easiest method to deploy GitLab on [Kubernetes](https://kubernetes.io/) is
to take advantage of GitLab's Helm charts. [Helm] is a package
@@ -14,51 +14,44 @@ should be deployed, upgraded, and configured.
## Chart Overview
-* **[GitLab-Omnibus](gitlab_omnibus.md)**: The best way to run GitLab on Kubernetes today, suited for small deployments. The chart is in beta and will be deprecated by the [cloud native GitLab chart](#cloud-native-gitlab-chart).
-* **[Cloud Native GitLab Chart](https://gitlab.com/charts/gitlab/blob/master/README.md)**: The next generation GitLab chart, currently in alpha. Will support large deployments with horizontal scaling of individual GitLab components.
+* **[GitLab Chart](gitlab_chart.html)**: The recommended GitLab chart, currently in beta. Supports large deployments with horizontal scaling of individual GitLab components, and does not require NFS.
+* **[GitLab Runner Chart](gitlab_runner_chart.md)**: For deploying just the GitLab Runner.
* Other Charts
- * [GitLab Runner Chart](gitlab_runner_chart.md): For deploying just the GitLab Runner.
+ * [GitLab-Omnibus](gitlab_omnibus.md): Chart based on the Omnibus GitLab linux package, only suitable for small deployments. The chart will be deprecated by the [GitLab chart](#gitlab-chart) when it is GA.
* [Community Contributed Charts](#community-contributed-charts): Community contributed charts, deprecated by the official GitLab chart.
-## GitLab-Omnibus Chart (Recommended)
+## GitLab Chart
-> **Note**: This chart is in beta while [additional features](https://gitlab.com/charts/charts.gitlab.io/issues/68) are being added.
+> **Note**: This chart is **beta**, while we work on the [remaining items for GA](https://gitlab.com/groups/charts/-/epics/15).
-This chart is the best available way to operate GitLab on Kubernetes. It deploys and configures nearly all features of GitLab, including: a [Runner](https://docs.gitlab.com/runner/), [Container Registry](../../user/project/container_registry.html#gitlab-container-registry), [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/), [automatic SSL](https://github.com/kubernetes/charts/tree/master/stable/kube-lego), and a [load balancer](https://github.com/kubernetes/ingress/tree/master/controllers/nginx). It is based on our [GitLab Omnibus Docker Images](https://docs.gitlab.com/omnibus/docker/README.html).
+The best way to operate GitLab on Kubernetes. This chart contains all the required components to get started, and can scale to large deployments.
-Once the [cloud native GitLab chart](#cloud-native-gitlab-chart) is ready for production use, this chart will be deprecated. Due to the difficulty in supporting upgrades to the new architecture, migrating will require exporting data out of this instance and importing it into the new deployment.
-
-Learn more about the [gitlab-omnibus chart](gitlab_omnibus.md).
-
-## Cloud Native GitLab Chart
-
-GitLab is working towards building a [cloud native GitLab chart](https://gitlab.com/charts/gitlab/blob/master/README.md). A key part of this effort is to isolate each service into its [own Docker container and Helm chart](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/2420), rather than utilizing the all-in-one container image of the [current chart](#gitlab-omnibus-chart-recommended).
-
-By offering individual containers and charts, we will be able to provide a number of benefits:
-* Easier horizontal scaling of each service,
-* Smaller, more efficient images,
-* Potential for rolling updates and canaries within a service,
+This chart offers a number of benefits:
+* Horizontal scaling of individual components
+* No requirement for shared storage to scale
+* Containers do not need `root` permissions
+* Automatic SSL with Let's Encrypt
* and plenty more.
-Presently this chart is available in alpha for testing, and not recommended for production use.
+Learn more about the [GitLab chart here](gitlab_chart.md) and [here [Video]](https://youtu.be/Z6jWR8Z8dv8).
-Learn more about the [cloud native GitLab chart here ](https://gitlab.com/charts/gitlab/blob/master/README.md) and [here [Video]](https://youtu.be/Z6jWR8Z8dv8).
+## GitLab Runner Chart
-## Other Charts
+If you already have a GitLab instance running, inside or outside of Kubernetes, and you'd like to leverage the Runner's [Kubernetes capabilities](https://docs.gitlab.com/runner/executors/kubernetes.html), it can be deployed with the GitLab Runner chart.
-### GitLab Runner Chart
+Learn more about [gitlab-runner chart](gitlab_runner_chart.md).
-If you already have a GitLab instance running, inside or outside of Kubernetes, and you'd like to leverage the Runner's [Kubernetes capabilities](https://docs.gitlab.com/runner/executors/kubernetes.html), it can be deployed with the GitLab Runner chart.
+## Other Charts
-Learn more about [gitlab-runner chart.](gitlab_runner_chart.md)
+### GitLab-Omnibus Chart
-### Advanced GitLab Installation
+> **Note**: This chart is beta, and **will be deprecated** when the [`gitlab`](#gitlab-chart) chart is GA.
-If advanced configuration of GitLab is required, the beta [gitlab](gitlab_chart.md) chart can be used which deploys the core GitLab service along with optional Postgres and Redis. It offers extensive configuration, but offers limited functionality out-of-the-box; it's lacking Pages support, the container registry, and Mattermost. It requires deep knowledge of Kubernetes and Helm to use.
+It deploys and configures nearly all features of GitLab, including: a [Runner](https://docs.gitlab.com/runner/), [Container Registry](../../user/project/container_registry.html#gitlab-container-registry), [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/), [automatic SSL](https://github.com/kubernetes/charts/tree/master/stable/kube-lego), and a [load balancer](https://github.com/kubernetes/ingress/tree/master/controllers/nginx). It is based on our [GitLab Omnibus Docker Images](https://docs.gitlab.com/omnibus/docker/README.html).
-This chart will be deprecated and replaced by the [gitlab-omnibus](gitlab_omnibus.md) chart, once it supports [additional configuration options](https://gitlab.com/charts/charts.gitlab.io/issues/68). It's beta quality, and since it is not actively under development, it will never be GA.
+Once the [GitLab chart](#gitlab-chart) is GA, this chart will be deprecated. Migrating to the `gitlab` chart will require exporting data out of this instance and importing it into a new deployment.
-Learn more about the [gitlab chart.](gitlab_chart.md)
+Learn more about the [gitlab-omnibus chart](gitlab_omnibus.md).
### Community Contributed Charts
diff --git a/doc/install/kubernetes/preparation/connect.md b/doc/install/kubernetes/preparation/connect.md
new file mode 100644
index 00000000000..fb633c456f5
--- /dev/null
+++ b/doc/install/kubernetes/preparation/connect.md
@@ -0,0 +1,31 @@
+# Connecting your computer to a cluster
+
+In order to deploy software and settings to a cluster, you must connect and authenticate to it.
+
+* [GKE cluster](#connect-to-gke-cluster)
+* [EKS cluster](#connect-to-eks-cluster)
+* [Local minikube cluster](#connect-to-local-minikube-cluster)
+
+## Connect to GKE cluster
+
+The command for connection to the cluster can be obtained from the [Google Cloud Platform Console](https://console.cloud.google.com/kubernetes/list) by the individual cluster.
+
+Look for the **Connect** button in the clusters list page.
+
+**Or**
+
+Use the command below, filling in your cluster's informtion:
+
+```
+gcloud container clusters get-credentials <cluster-name> --zone <zone> --project <project-id>
+```
+
+## Connect to EKS cluster
+
+For the most up to date instructions, follow the Amazon EKS documentation on [connecting to a cluster](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#eks-configure-kubectl).
+
+## Connect to local minikube cluster
+
+If you are doing local development, you can use `minikube` as your
+local cluster. If `kubectl cluster-info` is not showing `minikube` as the current
+cluster, use `kubectl config set-cluster minikube` to set the active cluster.
diff --git a/doc/install/kubernetes/preparation/eks.md b/doc/install/kubernetes/preparation/eks.md
new file mode 100644
index 00000000000..c40177c4302
--- /dev/null
+++ b/doc/install/kubernetes/preparation/eks.md
@@ -0,0 +1,44 @@
+# Running GitLab on EKS
+
+There are a few nuances to Amazon EKS which are important to be aware of, when deploying GitLab.
+
+## Persistent volume management
+
+There are two methods to manage volume claims on Kubernetes:
+1. Manually creating each persistent volume (recommended on EKS)
+1. Utilizing dynamic provisioning to automatically create the persistent volumes
+
+### Manual provisioning of volumes (Recommended)
+
+Manually creating the volumes allows you to control the zone of each volume, as well as all other details supported by the underlying storage.
+
+Follow our documentation on [manually creating persistent volumes](https://gitlab.com/charts/gitlab/blob/master/doc/installation/storage.md#manually-creating-static-volumes).
+
+### Dynamic provisioning of volumes
+
+Dynamic provisioning utilizes a Kubernetes provisioner, like `aws-ebs`, to automatically create persistent volumes to fulfill each claim.
+
+With EKS, there are a few important details to keep in mind:
+
+1. Clusters are required to span multiple AZ's
+1. Kubernetes volume provisioners create volumes across zones without regard to which pod they belong to. This leads to scenarios where a pod with multiple volumes being unable to start due to the volumes being in different zones.
+1. There is no default Storage Class.
+
+The easiest way to solve this and still utilize dynamic provisioning is to utilize, or create, a Storage Class that is locked to a specific zone.
+
+> **Note**: Restricting volumes to specific zone will cause GitLab and any other application using this Storage Class to only reside in that zone. For multiple zone support, utilize [manually provisioned volumes](#manual-provisioning-of-volumes).
+
+To create the storage class, download and edit Amazon EKS's [sample Storage Class](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html) and add the following parameter:
+
+```yaml
+parameters:
+ zone: <desired-zone>
+```
+
+Then [specify the Storage Class](https://gitlab.com/charts/gitlab/blob/master/doc/installation/storage.md#using-a-custom-storage-class) name when deploying GitLab.
+
+## External access to GitLab
+
+By default, GitLab will an deploy an ingress which will create an associated Elastic Load Balancer. Since the DNS names of ELB's cannot be known ahead of time, it is difficult to utilize Let's Encrypt to automatically provision HTTPS certificates.
+
+We recommend [using your own certificates](https://gitlab.com/charts/gitlab/blob/master/doc/installation/tls.md#option-2-use-your-own-wildcard-certificate), and then mapping your desired DNS name to the created ELB using a CNAME record.
diff --git a/doc/install/kubernetes/preparation/networking.md b/doc/install/kubernetes/preparation/networking.md
new file mode 100644
index 00000000000..b157cf31aa9
--- /dev/null
+++ b/doc/install/kubernetes/preparation/networking.md
@@ -0,0 +1,36 @@
+# Networking Prerequisites
+
+> **Note**: Amazon EKS utilizes Elastic Load Balancers, which are addressed by DNS name and cannot be known ahead of time. Skip this section.
+
+The `gitlab` chart configures a GitLab server and Kubernetes cluster which can support dynamic [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/index.html), as well as services like the integrated [Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html).
+
+To support the GitLab services and dynamic environments, a wildcard DNS entry is required which resolves to the external IP.
+
+## External IP
+
+To provision an external IP on GCP and Azure, simply request a new address from the Networking section. Ensure that the region matches the region your container cluster is created in. Note, it is important that the IP is not assigned at this point in time. It will be automatically assigned once the Helm chart is installed, to the Load Balancer.
+
+Set `global.hosts.externalIP` to this IP address when [deploying GitLab](../gitlab_chart.md#configuring-and-installing-gitlab).
+
+Then, create a [wildcard DNS record](#wildcard-dns-entry) which resolves to this IP address.
+
+### Creating an external IP on GCP
+
+When creating the external IP, it is critical to create it in the same region as your cluster. Otherwise, the IP address will fail to bind to the Load Balancer.
+
+1. Open the [web console](https://console.cloud.google.com)
+1. In the sidebar, browse to `VPC Network > External IP addresses`
+1. Click `Reserve static address`
+1. Choose `Regional` and select the region of your cluster
+1. Leave `Attached to` blank, as it will be automatically assigned during deployment
+
+## Wildcard DNS entry
+
+Now that an external IP address has been allocated, ensure that the wildcard DNS entry you would like to use resolves to this IP. Typically this would be an `A record` for `*`, resolving to the external IP above.
+
+Please consult the documentation for your DNS service for more information on creating DNS records:
+
+* [Google Domains](https://support.google.com/domains/answer/3290350?hl=en)
+* [GoDaddy](https://www.godaddy.com/help/add-an-a-record-19238)
+
+Set `global.hosts.domain` to this DNS name when [deploying GitLab](../gitlab_chart.md#configuring-and-installing-gitlab).
diff --git a/doc/install/kubernetes/preparation/rbac.md b/doc/install/kubernetes/preparation/rbac.md
new file mode 100644
index 00000000000..240893526d3
--- /dev/null
+++ b/doc/install/kubernetes/preparation/rbac.md
@@ -0,0 +1,16 @@
+# Role Based Access Control
+
+Until Kubernetes 1.7, there were no permissions within a cluster. With the launch of 1.7, there is now a role based access control system ([RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)) which determines what services can perform actions within a cluster.
+
+RBAC affects a few different aspects of GitLab:
+* [Installation of GitLab using Helm](tiller.md#preparing-for-helm-with-rbac)
+* Prometheus monitoring
+* GitLab Runner
+
+## Checking that RBAC is enabled
+
+Try listing the current cluster roles, if it fails then `RBAC` is disabled
+
+This command will output `false` if `RBAC` is disabled and `true` otherwise
+
+`kubectl get clusterroles > /dev/null 2>&1 && echo true || echo false`
diff --git a/doc/install/kubernetes/preparation/tiller.md b/doc/install/kubernetes/preparation/tiller.md
new file mode 100644
index 00000000000..c92f8258e41
--- /dev/null
+++ b/doc/install/kubernetes/preparation/tiller.md
@@ -0,0 +1,94 @@
+# Configuring and initializing Helm Tiller
+
+To make use of Helm, you must have a [Kubernetes][k8s-io] cluster. Ensure you can access your cluster using `kubectl`.
+
+Helm consists of two parts, the `helm` client and a `tiller` server inside Kubernetes.
+
+> **Note**: If you are not able to run tiller in your cluster, for example on OpenShift, it is possible to use [tiller locally](#local-tiller) and avoid deploying it into the cluster. This should only be used when Tiller cannot be normally deployed.
+
+## Initialize Helm and Tiller
+
+Tiller is deployed into the cluster and interacts with the Kubernetes API to deploy your applications. If role based access control (RBAC) is enabled, Tiller will need to be [granted permissions](#preparing-for-helm-with-rbac) to allow it to talk to the Kubernetes API.
+
+If RBAC is not enabled, skip to [initalizing Helm](#initialize-helm).
+
+If you are not sure whether RBAC is enabled in your cluster, or to learn more, read through our [RBAC documentation](rbac.md).
+
+## Preparing for Helm with RBAC
+
+Helm's Tiller will need to be granted permissions to perform operations. These instructions grant cluster wide permissions, however for more advanced deployments [permissions can be restricted to a single namespace](https://docs.helm.sh/using_helm/#example-deploy-tiller-in-a-namespace-restricted-to-deploying-resources-only-in-that-namespace). To grant access to the cluster, we will create a new `tiller` service account and bind it to the `cluster-admin` role.
+
+Create a file `rbac-config.yaml` with the following contents:
+
+```yaml
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: tiller
+ namespace: kube-system
+---
+apiVersion: rbac.authorization.k8s.io/v1beta1
+kind: ClusterRoleBinding
+metadata:
+ name: tiller
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+ - kind: ServiceAccount
+ name: tiller
+ namespace: kube-system
+```
+
+Next we need to connect to the cluster and upload the RBAC config.
+
+### Upload the RBAC config
+
+Some clusters require authentication to use `kubectl` to create the Tiller roles.
+
+#### Upload the RBAC config as an admin user (GKE)
+
+For GKE, you need to grab the admin credentials:
+
+```
+gcloud container clusters describe <cluster-name> --zone <zone> --project <project-id> --format='value(masterAuth.password)'
+```
+
+This command will output the admin password. We need the password to authenticate with `kubectl` and create the role.
+
+```
+kubectl --username=admin --password=xxxxxxxxxxxxxx create -f rbac-config.yaml
+```
+
+#### Upload the RBAC config (Other clusters)
+
+For other clusters like Amazon EKS, you can directly upload the RBAC configuration.
+
+kubectl create -f rbac-config.yaml
+
+## Initialize Helm
+
+Deploy Helm Tiller with a service account
+
+```
+helm init --service-account tiller
+```
+
+If your cluster
+previously had Helm/Tiller installed, run the following to ensure that the deployed version of Tiller matches the local Helm version:
+
+```
+helm init --upgrade --service-account tiller
+```
+
+### Patching Helm Tiller for EKS
+
+Helm Tiller requires a flag to be enabled to work properly on EKS:
+
+`kubectl -n kube-system patch deployment tiller-deploy -p '{"spec": {"template": {"spec": {"automountServiceAccountToken": true}}}}'`
+
+[helm]: https://helm.sh
+[helm-using]: https://docs.helm.sh/using_helm
+[k8s-io]: https://kubernetes.io/
+[gcp-k8s]: https://console.cloud.google.com/kubernetes/list
diff --git a/doc/install/kubernetes/preparation/tools_installation.md b/doc/install/kubernetes/preparation/tools_installation.md
new file mode 100644
index 00000000000..210bc2f9e58
--- /dev/null
+++ b/doc/install/kubernetes/preparation/tools_installation.md
@@ -0,0 +1,19 @@
+# Installing kubectl and Helm on your computer
+
+In order to work with the GitLab Helm charts, `kubectl` and `helm` must be installed and configured on your computer.
+
+## Installing `kubectl`
+
+`kubectl` is the Kubernetes command line tool, which can be used to deploy settings to the cluster.
+
+Follow the [official documentation](https://kubernetes.io/docs/tasks/tools/install-kubectl/) for the most up to date instructions.
+
+## Installing `helm`
+
+Helm is a package management tool for Kubernetes, and is used to deploy charts.
+
+You can get Helm from the project's [releases page](https://github.com/kubernetes/helm/releases), or follow other options under the official documentation of [Installing Helm](https://docs.helm.sh/using_helm/#installing-helm).
+
+# Next steps
+
+Once installed, proceed to the next [installation step](../gitlab_chart.md#prerequisites).
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index a301d1a613c..932cd479d56 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -20,4 +20,21 @@ To use reCAPTCHA, first you must create a site and private key.
6. Check the `Enable reCAPTCHA` checkbox
-7. Save the configuration.
+7. Save the configuration.
+
+## Enabling reCAPTCHA for user logins via passwords
+
+By default, reCAPTCHA is only enabled for user registrations. To enable it for
+user logins via passwords, the `X-GitLab-Show-Login-Captcha` HTTP header must
+be set. For example, in NGINX, this can be done via the `proxy_set_header`
+configuration variable:
+
+```
+proxy_set_header X-GitLab-Show-Login-Captcha 1;
+```
+
+In GitLab Omnibus, this can be configured via `/etc/gitlab/gitlab.rb`:
+
+```ruby
+nginx['proxy_set_headers'] = { 'X-GitLab-Show-Login-Captcha' => 1 }
+```
diff --git a/doc/topics/autodevops/img/auto_monitoring.png b/doc/topics/autodevops/img/auto_monitoring.png
index 92902e3ca72..2900e5d1877 100644
--- a/doc/topics/autodevops/img/auto_monitoring.png
+++ b/doc/topics/autodevops/img/auto_monitoring.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_choose_gke.png b/doc/topics/autodevops/img/guide_choose_gke.png
new file mode 100644
index 00000000000..6da3a7220da
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_choose_gke.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_cluster_apps.png b/doc/topics/autodevops/img/guide_cluster_apps.png
new file mode 100644
index 00000000000..33d25f2950d
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_cluster_apps.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_connect_cluster.png b/doc/topics/autodevops/img/guide_connect_cluster.png
index b856b81a1d0..703d536f37a 100644
--- a/doc/topics/autodevops/img/guide_connect_cluster.png
+++ b/doc/topics/autodevops/img/guide_connect_cluster.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_create_cluster.png b/doc/topics/autodevops/img/guide_create_cluster.png
new file mode 100644
index 00000000000..cd1d0fdd8da
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_create_cluster.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_create_project.png b/doc/topics/autodevops/img/guide_create_project.png
new file mode 100644
index 00000000000..4ed1071db03
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_create_project.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_enable_autodevops.png b/doc/topics/autodevops/img/guide_enable_autodevops.png
new file mode 100644
index 00000000000..0fc3ecca19a
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_enable_autodevops.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_environments.png b/doc/topics/autodevops/img/guide_environments.png
new file mode 100644
index 00000000000..1d8d5614e64
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_environments.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_environments_metrics.png b/doc/topics/autodevops/img/guide_environments_metrics.png
new file mode 100644
index 00000000000..f0d31f31581
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_environments_metrics.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_first_pipeline.png b/doc/topics/autodevops/img/guide_first_pipeline.png
new file mode 100644
index 00000000000..57459dcc9d9
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_first_pipeline.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_gitlab_gke_details.png b/doc/topics/autodevops/img/guide_gitlab_gke_details.png
new file mode 100644
index 00000000000..bc5a53800f7
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_gitlab_gke_details.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_gke_apis_after.png b/doc/topics/autodevops/img/guide_gke_apis_after.png
new file mode 100644
index 00000000000..380de958867
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_gke_apis_after.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_gke_apis_before.png b/doc/topics/autodevops/img/guide_gke_apis_before.png
new file mode 100644
index 00000000000..d06fc707887
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_gke_apis_before.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_google_auth.png b/doc/topics/autodevops/img/guide_google_auth.png
new file mode 100644
index 00000000000..b97b2be9f15
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_google_auth.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_google_signin.png b/doc/topics/autodevops/img/guide_google_signin.png
new file mode 100644
index 00000000000..e59fc94bd4c
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_google_signin.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_ide_commit.png b/doc/topics/autodevops/img/guide_ide_commit.png
new file mode 100644
index 00000000000..188f60f2a4b
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_ide_commit.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_integration.png b/doc/topics/autodevops/img/guide_integration.png
deleted file mode 100644
index 723b2619ea2..00000000000
--- a/doc/topics/autodevops/img/guide_integration.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_merge_request.png b/doc/topics/autodevops/img/guide_merge_request.png
new file mode 100644
index 00000000000..d78e69be776
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_merge_request.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_merge_request_ide.png b/doc/topics/autodevops/img/guide_merge_request_ide.png
new file mode 100644
index 00000000000..c825b0849e1
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_merge_request_ide.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_merge_request_review_app.png b/doc/topics/autodevops/img/guide_merge_request_review_app.png
new file mode 100644
index 00000000000..1b9b854ddac
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_merge_request_review_app.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_pipeline_stages.png b/doc/topics/autodevops/img/guide_pipeline_stages.png
new file mode 100644
index 00000000000..6e2f078152b
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_pipeline_stages.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_project_landing_page.png b/doc/topics/autodevops/img/guide_project_landing_page.png
new file mode 100644
index 00000000000..4f8d2eb10b1
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_project_landing_page.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_project_template.png b/doc/topics/autodevops/img/guide_project_template.png
new file mode 100644
index 00000000000..298ac0f6fcf
--- /dev/null
+++ b/doc/topics/autodevops/img/guide_project_template.png
Binary files differ
diff --git a/doc/topics/autodevops/img/guide_secret.png b/doc/topics/autodevops/img/guide_secret.png
deleted file mode 100644
index 01f5aa49908..00000000000
--- a/doc/topics/autodevops/img/guide_secret.png
+++ /dev/null
Binary files differ
diff --git a/doc/topics/autodevops/img/rollout_staging_disabled.png b/doc/topics/autodevops/img/rollout_staging_disabled.png
index 71e36b440f0..4c7c6768666 100644
--- a/doc/topics/autodevops/img/rollout_staging_disabled.png
+++ b/doc/topics/autodevops/img/rollout_staging_disabled.png
Binary files differ
diff --git a/doc/topics/autodevops/img/rollout_staging_enabled.png b/doc/topics/autodevops/img/rollout_staging_enabled.png
index d0d1d356627..f45c1c2cb37 100644
--- a/doc/topics/autodevops/img/rollout_staging_enabled.png
+++ b/doc/topics/autodevops/img/rollout_staging_enabled.png
Binary files differ
diff --git a/doc/topics/autodevops/img/staging_enabled.png b/doc/topics/autodevops/img/staging_enabled.png
index 0ef1a67d641..f0e0cd1cfcd 100644
--- a/doc/topics/autodevops/img/staging_enabled.png
+++ b/doc/topics/autodevops/img/staging_enabled.png
Binary files differ
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index fe6a88b1df7..bb934db520e 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -1,6 +1,6 @@
# Auto DevOps
-> [Introduced][ce-37115] in GitLab 10.0.
+> [Introduced][ce-37115] in GitLab 10.0. Generally available on GitLab 11.0.
Auto DevOps automatically detects, builds, tests, deploys, and monitors your
applications.
@@ -13,6 +13,12 @@ without needing to configure anything. Just push your code and GitLab takes
care of everything else. This makes it easier to start new projects and brings
consistency to how applications are set up throughout a company.
+## Quick start
+
+If you are using GitLab.com, see the [quick start guide](quick_start_guide.md)
+for using Auto DevOps with GitLab.com and a Kubernetes cluster on Google Kubernetes
+Engine.
+
## Comparison to application platforms and PaaS
Auto DevOps provides functionality described by others as an application
@@ -34,7 +40,7 @@ in a couple of ways:
## Features
Comprised of a set of stages, Auto DevOps brings these best practices to your
-project in an easy and automatic way:
+project in a simple and automatic way:
1. [Auto Build](#auto-build)
1. [Auto Test](#auto-test)
@@ -135,10 +141,9 @@ and `1.2.3.4` is the IP address of your load balancer; generally NGINX
([see requirements](#requirements)). How to set up the DNS record is beyond
the scope of this document; you should check with your DNS provider.
-Alternatively you can use free public services like [xip.io](http://xip.io) or
-[nip.io](http://nip.io) which provide automatic wildcard DNS without any
-configuration. Just set the Auto DevOps base domain to `1.2.3.4.xip.io` or
-`1.2.3.4.nip.io`.
+Alternatively you can use free public services like [nip.io](http://nip.io)
+which provide automatic wildcard DNS without any configuration. Just set the
+Auto DevOps base domain to `1.2.3.4.nip.io`.
Once set up, all requests will hit the load balancer, which in turn will route
them to the Kubernetes pods that run your application(s).
@@ -198,12 +203,6 @@ and verifying that your app is deployed as a review app in the Kubernetes
cluster with the `review/*` environment scope. Similarly, you can check the
other environments.
-## Quick start
-
-If you are using GitLab.com, see our [quick start guide](quick_start_guide.md)
-for using Auto DevOps with GitLab.com and an external Kubernetes cluster on
-Google Cloud.
-
## Enabling Auto DevOps
If you haven't done already, read the [requirements](#requirements) to make
@@ -288,7 +287,7 @@ NOTE: **Note:**
Auto Test uses tests you already have in your application. If there are no
tests, it's up to you to add them.
-### Auto Code Quality
+### Auto Code Quality **[STARTER]**
Auto Code Quality uses the
[Code Quality image](https://gitlab.com/gitlab-org/security-products/codequality) to run
@@ -323,7 +322,7 @@ to run analysis on the project dependencies and checks for potential security is
report is created, it's uploaded as an artifact which you can later download and
check out.
-In GitLab Ultimate, any security warnings are also
+Any security warnings are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/dependency_scanning.html).
### Auto License Management **[ULTIMATE]**
@@ -331,12 +330,12 @@ In GitLab Ultimate, any security warnings are also
> Introduced in [GitLab Ultimate][ee] 11.0.
License Management uses the
-[License Management Docker image](https://gitlab.com/gitlab-org/security-products/license_management)
+[License Management Docker image](https://gitlab.com/gitlab-org/security-products/license-management)
to search the project dependencies for their license. Once the
report is created, it's uploaded as an artifact which you can later download and
check out.
-In GitLab Ultimate, any licenses are also
+Any licenses are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/license_management.html).
### Auto Container Scanning
@@ -446,7 +445,7 @@ executed somewhere else, it cannot be accessed again.
> [Introduced][ce-19507] in GitLab 11.0.
-For internal and private projects a [GitLab Deploy Token](../../user/project/deploy_tokens/index.md###gitlab-deploy-token)
+For internal and private projects a [GitLab Deploy Token](../../user/project/deploy_tokens/index.md###gitlab-deploy-token)
will be automatically created, when Auto DevOps is enabled and the Auto DevOps settings are saved. This Deploy Token
can be used for permanent access to the registry.
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 61c04f3d9bb..44b0cf758dc 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -1,143 +1,290 @@
-# Auto DevOps: quick start guide
+# Getting started with Auto DevOps
-> [Introduced][ce-37115] in GitLab 10.0.
+This is a step-by-step guide that will help you use [Auto DevOps](index.md) to
+deploy a project hosted on GitLab.com to Google Kubernetes Engine.
-This is a step-by-step guide to deploying a project hosted on GitLab.com to
-Google Cloud, using Auto DevOps.
+We will use GitLab's native Kubernetes integration, so you will not need
+to create a Kubernetes cluster manually using the Google Cloud Platform console.
+We will create and deploy a simple application that we create from a GitLab template.
-We made a minimal [Ruby
-application](https://gitlab.com/auto-devops-examples/minimal-ruby-app) to use
-as an example for this guide. It contains two main files:
+These instructions will also work for a self-hosted GitLab instance; you'll just
+need to ensure your own [Runners are configured](../../ci/runners/README.md) and
+[Google OAuth is enabled](../../integration/google.md).
-* `server.rb` - our application. It will start an HTTP server on port 5000 and
- render "Hello, world!"
-* `Dockerfile` - to build our app into a container image. It will use a ruby
- base image and run `server.rb`
+## Configuring your Google account
-## Fork sample project on GitLab.com
+Before creating and connecting your Kubernetes cluster to your GitLab project,
+you need a Google Cloud Platform account. If you don't already have one,
+sign up at https://console.cloud.google.com. You'll need to either sign in with an existing
+Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one.
-Let’s start by forking our sample application. Go to [the project
-page](https://gitlab.com/auto-devops-examples/minimal-ruby-app) and press the
-**Fork** button. Soon you should have a project under your namespace with the
-necessary files.
+1. Follow the steps as outlined in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)
+ in order for the required APIs and related services to be enabled.
+1. Make sure you have created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account).
-You can also start a new project from a
-[GitLab project template](https://gitlab.com/gitlab-org/project-templates) if
-you want to use a different language.
+TIP: **Tip:**
+Every new Google Cloud Platform (GCP) account receives [$300 in credit](https://console.cloud.google.com/freetrial),
+and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with GitLab's
+Google Kubernetes Engine Integration. All you have to do is [follow this link](https://goo.gl/AaJzRW) and apply for credit.
-## Setup your own cluster on Google Kubernetes Engine
+## Creating a new project from a template
-If you do not already have a Google Cloud account, create one at
-https://console.cloud.google.com.
+We will use one of GitLab's project templates to get started. As the name suggests,
+those projects provide a barebones application built on some well-known frameworks.
-Visit the [**Kubernetes Engine**](https://console.cloud.google.com/kubernetes/list)
-tab and create a new cluster. You can change the name and leave the rest of the
-default settings. Once you have your cluster running, you need to connect to the
-cluster by following the Google interface.
+1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select
+ **New project**.
+1. Go to the **Create from template** tab where you can choose among a Ruby on
+ Rails, Spring, or NodeJS Express project. For this example,
+ we'll use the Ruby on Rails template.
-## Connect to Kubernetes cluster
+ ![Select project template](img/guide_project_template.png)
-You need to have the Google Cloud SDK installed. e.g.
-On macOS, install [homebrew](https://brew.sh):
+1. Give your project a name, optionally a description, and make it public so that
+ you can take advantage of the features available in the
+ [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com).
-1. Install Brew Caskroom: `brew install caskroom/cask/brew-cask`
-2. Install Google Cloud SDK: `brew cask install google-cloud-sdk`
-3. Add `kubectl` with: `gcloud components install kubectl`
-4. Log in: `gcloud auth login`
+ ![Create project](img/guide_create_project.png)
-Now go back to the Google interface, find your cluster, follow the instructions
-under "Connect to the cluster" and open the Kubernetes Dashboard. It will look
-something like:
+1. Click **Create project**.
-```sh
-gcloud container clusters get-credentials ruby-autodeploy \ --zone europe-west2-c --project api-project-XXXXXXX
-```
+Now that the project is created, the next step is to create the Kubernetes cluster
+under which this application will be deployed.
-Finally, run `kubectl proxy`.
+## Creating a Kubernetes cluster from within GitLab
-![connect to cluster](img/guide_connect_cluster.png)
+1. On the project's landing page, click the button labeled **Add Kubernetes cluster**
+ (note that this option is also available when you navigate to **Operations > Kubernetes**).
-## Copy credentials to GitLab.com project
+ ![Project landing page](img/guide_project_landing_page.png)
-Once you have the Kubernetes Dashboard interface running, you should visit
-**Secrets** under the "Config" section. There, you should find the settings we
-need for GitLab integration: `ca.crt` and token.
+1. Choose **Create on Google Kubernetes Engine**.
-![connect to cluster](img/guide_secret.png)
+ ![Choose GKE](img/guide_choose_gke.png)
-You need to copy-paste the `ca.crt` and token into your project on GitLab.com in
-the Kubernetes integration page under project
-**Settings > Integrations > Project services > Kubernetes**. Don't actually copy
-the namespace though. Each project should have a unique namespace, and by leaving
-it blank, GitLab will create one for you.
+1. Sign in with Google.
-![connect to cluster](img/guide_integration.png)
+ ![Google sign in](img/guide_google_signin.png)
-For the API URL, you should use the "Endpoint" IP from your cluster page on
-Google Cloud Platform.
+1. Connect with your Google account and press **Allow** when asked (this will
+ be shown only the first time you connect GitLab with your Google account).
-## Expose application to the world
+ ![Google auth](img/guide_google_auth.png)
-In order to be able to visit your application, you need to install an NGINX
-ingress controller and point your domain name to its external IP address. Let's
-see how that's done.
+1. The last step is to fill in the cluster details. Give it a name, leave the
+ environment scope as is, and choose the GCP project under which the cluster
+ will be created. (Per the instructions when you
+ [configured your Google account](#configuring-your-google-account), a project
+ should have already been created for you.) Next, choose the
+ [region/zone](https://cloud.google.com/compute/docs/regions-zones/) under which the
+ cluster will be created, enter the number of nodes you want it to have, and
+ finally choose their [machine type](https://cloud.google.com/compute/docs/machine-types).
-### Set up Ingress controller
+ ![GitLab GKE cluster details](img/guide_gitlab_gke_details.png)
-You’ll need to make sure you have an ingress controller. If you don’t have one, do:
+1. Once ready, click **Create Kubernetes cluster**.
-```sh
-brew install kubernetes-helm
-helm init
-helm install --name ruby-app stable/nginx-ingress
-```
+After a couple of minutes, the cluster will be created. You can also see its
+status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
-This should create several services including `ruby-app-nginx-ingress-controller`.
-You can list your services by running `kubectl get svc` to confirm that.
+The next step is to install some applications on your cluster that are needed
+to take full advantage of Auto DevOps.
-### Point DNS at Cluster IP
+## Installing Helm, Ingress, and Prometheus
-Find out the external IP address of the `ruby-app-nginx-ingress-controller` by
-running:
+GitLab's Kubernetes integration comes with some
+[pre-defined applications](../../user/project/clusters/index.md#installing-applications)
+for you to install.
-```sh
-kubectl get svc ruby-app-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
-```
+![Cluster applications](img/guide_cluster_apps.png)
+
+The first one to install is Helm Tiller, a package manager for Kubernetes, which
+is needed in order to install the rest of the applications. Go ahead and click
+its **Install** button.
+
+Once it's installed, the other applications that rely on it will each have their **Install**
+button enabled. For this guide, we need Ingress and Prometheus. Ingress provides
+load balancing, SSL termination, and name-based virtual hosting, using NGINX behind
+the scenes. Prometheus is an open-source monitoring and alerting system that we'll
+use to supervise the deployed application. We will not install GitLab Runner as
+we'll use the shared Runners that GitLab.com provides.
+
+After the Ingress is installed, wait a few seconds and copy the IP address that
+is displayed, which we'll use in the next step when enabling Auto DevOps.
+
+## Enabling Auto DevOps
+
+Now that the Kubernetes cluster is set up and ready, let's enable Auto DevOps.
+
+1. First, navigate to **Settings > CI/CD > Auto DevOps**.
+1. Select **Enable Auto DevOps**.
+1. Add in your base **Domain** by using the one GitLab suggests. Note that
+ generally, you would associate the IP address with a domain name on your
+ registrar's settings. In this case, for the sake of the guide, we will use
+ an alternative DNS that will map any domain name of the scheme
+ `anything.ip_address.nip.io` to the corresponding `ip_address`. For example,
+ if the IP address of the Ingress is `1.2.3.4`, the domain name to fill in
+ would be `1.2.3.4.nip.io`.
+1. Lastly, let's select the [continuous deployment strategy](index.md#deployment-strategy)
+ which will automatically deploy the application to production once the pipeline
+ successfully runs on the `master` branch.
+1. Click **Save changes**.
+
+ ![Auto DevOps settings](img/guide_enable_autodevops.png)
+
+Once you complete all the above and save your changes, a new pipeline is
+automatically created. To view the pipeline, go to **CI/CD > Pipelines**.
+
+![First pipeline](img/guide_first_pipeline.png)
+
+In the next section we'll break down the pipeline and explain what each job does.
+
+## Deploying the application
+
+By now you should see the pipeline running, but what is it running exactly?
+
+To navigate inside the pipeline, click its status badge. (It's status should be "running").
+The pipeline is split into 4 stages, each running a couple of jobs.
+
+![Pipeline stages](img/guide_pipeline_stages.png)
+
+In the **build** stage, the application is built into a Docker image and then
+uploaded to your project's [Container Registry](../../user/project/container_registry.md) ([Auto Build](index.md#auto-build)).
+
+In the **test** stage, GitLab runs various checks on the application:
+
+- The `test` job runs unit and integration tests by detecting the language and
+ framework ([Auto Test](index.md#auto-test))
+- The `code_quality` job checks the code quality and is allowed to fail
+ ([Auto Code Quality](index.md#auto-code-quality)) **[STARTER]**
+- The `container_scanning` job checks the Docker container if it has any
+ vulnerabilities and is allowed to fail ([Auto Container Scanning](index.md#auto-container-scanning))
+- The `dependency_scanning` job checks if the application has any dependencies
+ susceptible to vulnerabilities and is allowed to fail ([Auto Dependency Scanning](index.md#auto-dependency-scanning)) **[ULTIMATE]**
+- The `sast` job runs static analysis on the current code to check for potential
+ security issues and is allowed to fail([Auto SAST](index.md#auto-sast)) **[ULTIMATE]**
+- The `license_management` job searches the application's dependencies to determine each of their
+ licenses and is allowed to fail ([Auto License Management](index.md#auto-license-management)) **[ULTIMATE]**
NOTE: **Note:**
-If your ingress controller has been installed in a different way, you can find
-how to get the external IP address in the
-[Cluster documentation](../../user/project/clusters/index.md#getting-the-external-ip-address).
+As you might have noticed, all jobs except `test` are allowed to fail in the
+test stage.
+
+The **production** stage is run after the tests and checks finish, and it automatically
+deploys the application in Kubernetes ([Auto Deploy](index.md#auto-deploy)).
+
+Lastly, in the **performance** stage, some performance tests will run
+on the deployed application
+([Auto Browser Performance Testing](index.md#auto-browser-performance-testing)). **[PREMIUM]**
+
+---
-Use this IP address to configure your DNS. This part heavily depends on your
-preferences and domain provider. But in case you are not sure, just create an
-A record with a wildcard host like `*.<your-domain>`.
+The URL for the deployed application can be found under the **Environments**
+page where you can also monitor your application. Let's explore that.
+
+### Monitoring
+
+Now that the application is successfully deployed, let's navigate to its
+website. First, go to **Operations > Environments**.
+
+![Environments](img/guide_environments.png)
+
+In **Environments** you can see some details about the deployed
+applications. In the rightmost column for the production environment, you can make use of the three icons:
+
+- The first icon will open the URL of the application that is deployed in
+ production. It's a very simple page, but the important part is that it works!
+- The next icon with the small graph will take you to the metrics page where
+ Prometheus collects data about the Kubernetes cluster and how the application
+ affects it (in terms of memory/CPU usage, latency, etc.).
+
+ ![Environments metrics](img/guide_environments_metrics.png)
+
+- The third icon is the [web terminal](../../ci/environments.md#web-terminals)
+ and it will open a terminal session right inside the container where the
+ application is running.
+
+Right below, there is the
+[Deploy Board](https://docs.gitlab.com/ee/user/project/deploy_boards.md).
+The squares represent pods in your Kubernetes cluster that are associated with
+the given environment. Hovering above each square you can see the state of a
+deployment and clicking a square will take you to the pod's logs page.
+
+TIP: **Tip:**
+There is only one pod hosting the application at the moment, but you can add
+more pods by defining the [`REPLICAS` variable](index.md#environment-variables)
+under **Settings > CI/CD > Variables**.
+
+### Working with branches
+
+Following the [GitLab flow](../../workflow/gitlab_flow.md#working-with-feature-branches)
+let's create a feature branch that will add some content to the application.
+
+Under your repository, navigate to the following file: `app/views/welcome/index.html.erb`.
+By now, it should only contain a paragraph: `<p>You're on Rails!</p>`, so let's
+start adding content. Let's use GitLab's [Web IDE](../../user/project/web_ide/index.md) to make the change. Once
+you're on the Web IDE, make the following change:
+
+```html
+<p>You're on Rails! Powered by GitLab Auto DevOps.</p>
+```
+
+Stage the file, add a commit message, and create a new branch and a merge request
+by clicking **Commit**.
+
+![Web IDE commit](img/guide_ide_commit.png)
+
+Once you submit the merge request, you'll see the pipeline running. This will
+run all the jobs as [described previously](#deploying-the-application), as well
+a few more that run only on branches other than `master`.
+
+![Merge request](img/guide_merge_request.png)
+
+After a few minutes you'll notice that there was a failure in a test.
+This means there's a test that was 'broken' by our change.
+Navigating into the `test` job that failed, you can see what the broken test is:
+
+```
+Failure:
+WelcomeControllerTest#test_should_get_index [/app/test/controllers/welcome_controller_test.rb:7]:
+<You're on Rails!> expected but was
+<You're on Rails! Powered by GitLab Auto DevOps.>..
+Expected 0 to be >= 1.
+
+bin/rails test test/controllers/welcome_controller_test.rb:4
+```
-Use `nslookup minimal-ruby-app-staging.<yourdomain>` to confirm that domain is
-assigned to the cluster IP.
+Let's fix that:
-## Set up Auto DevOps
+1. Back to the merge request, click the **Web IDE** button.
+1. Find the `test/controllers/welcome_controller_test.rb` file and open it.
+1. Change line 7 to say `You're on Rails! Powered by GitLab Auto DevOps.`
+1. Click **Commit**.
+1. On your left, under "Unstaged changes", click the little checkmark icon
+ to stage the changes.
+1. Write a commit message and click **Commit**.
-In your GitLab.com project, go to **Settings > CI/CD** and find the Auto DevOps
-section. Select "Enable Auto DevOps", add in your base domain, and save.
+Now, if you go back to the merge request you should not only see the test passing,
+but also the application deployed as a [review app](index.md#auto-review-apps). You
+can visit it by following the URL in the merge request. The changes that we
+previously made should be there.
-Next, a pipeline needs to be triggered. Since the test project doesn't have a
-`.gitlab-ci.yml`, you need to either push a change to the repository or
-manually visit `https://gitlab.com/<username>/minimal-ruby-app/pipelines/new`,
-where `<username>` is your username.
+![Review app](img/guide_merge_request_review_app.png)
-This will create a new pipeline with several jobs: `build`, `test`, `code_quality`,
-and `production`. The `build` job will create a Docker image with your new
-change and push it to the Container Registry. The `test` job will test your
-changes, whereas the `code_quality` job will run static analysis on your changes.
-Finally, the `production` job will deploy your changes to a production application.
+Once you merge the merge request, the pipeline will run on the `master` branch,
+and the application will be eventually deployed straight to production.
-Once the deploy job succeeds you should be able to see your application by
-visiting the Kubernetes dashboard. Select the namespace of your project, which
-will look like `minimal-ruby-app-23`, but with a unique ID for your project,
-and your app will be listed as "production" under the Deployment tab.
+## Conclusion
-Once its ready, just visit `http://minimal-ruby-app.example.com` to see the
-famous "Hello, world!"!
+After implementing this project, you should now have a solid understanding of the basics of Auto DevOps.
+We started from building and testing to deploying and monitoring an application
+all within GitLab. Despite its automatic nature, Audo DevOps can also be configured
+and customized to fit your workflow. Here are some helpful resources for further reading:
-[ce-37115]: https://gitlab.com/gitlab-org/gitlab-ce/issues/37115
+1. [Auto DevOps](index.md)
+1. [Multiple Kubernetes clusters](index.md#using-multiple-kubernetes-clusters) **[PREMIUM]**
+1. [Incremental rollout to production](index.md#incremental-rollout-to-production) **[PREMIUM]**
+1. [Disable jobs you don't need with environment variables](index.md#environment-variables)
+1. [Use a static IP for your cluster](../../user/project/clusters/index.md#using-a-static-ip)
+1. [Use your own buildpacks to build your application](index.md#custom-buildpacks)
+1. [Prometheus monitoring](../../user/project/integrations/prometheus.md)
diff --git a/doc/update/10.8-to-11.0.md b/doc/update/10.8-to-11.0.md
index 78a47ab939f..f9b6044bd2f 100644
--- a/doc/update/10.8-to-11.0.md
+++ b/doc/update/10.8-to-11.0.md
@@ -81,8 +81,8 @@ More information can be found on the [yarn website](https://yarnpkg.com/en/docs/
### 5. Update Go
-NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go
-1.5.x through 1.7.x. Be sure to upgrade your installation if necessary.
+NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
+1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
You can check which version you are running with `go version`.
@@ -92,11 +92,11 @@ Download and install Go:
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
-echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz
+curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
+echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.8.3.linux-amd64.tar.gz
+rm go1.10.3.linux-amd64.tar.gz
```
### 6. Get latest code
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 58a483bb3b2..20c46cafbe5 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -7,9 +7,10 @@ cluster in a few steps.
## Overview
-With a Kubernetes cluster associated to your project, you can use
+With one or more Kubernetes clusters associated to your project, you can use
[Review Apps](../../../ci/review_apps/index.md), deploy your applications, run
-your pipelines, and much more, in an easy way.
+your pipelines, use it with [Auto DevOps](../../../topics/autodevops/index.md),
+and much more, all from within GitLab.
There are two options when adding a new cluster to your project; either associate
your account with Google Kubernetes Engine (GKE) so that you can [create new
@@ -18,59 +19,65 @@ or provide the credentials to an [existing Kubernetes cluster](#adding-an-existi
## Adding and creating a new GKE cluster via GitLab
+TIP: **Tip:**
+Every new Google Cloud Platform (GCP) account receives [$300 in credit upon sign up](https://console.cloud.google.com/freetrial),
+and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with GitLab's
+Google Kubernetes Engine Integration. All you have to do is [follow this link](https://goo.gl/AaJzRW) and apply for credit.
+
NOTE: **Note:**
-You need Maintainer [permissions] and above to access the Kubernetes page.
-
-Before proceeding, make sure the following requirements are met:
-
-- The [Google authentication integration](../../../integration/google.md) must
- be enabled in GitLab at the instance level. If that's not the case, ask your
- GitLab administrator to enable it.
-- Your associated Google account must have the right privileges to manage
- clusters on GKE. That would mean that a [billing
- account](https://cloud.google.com/billing/docs/how-to/manage-billing-account)
- must be set up and that you have to have permissions to access it.
-- You must have Maintainer [permissions] in order to be able to access the
- **Kubernetes** page.
-- You must have [Cloud Billing API](https://cloud.google.com/billing/) enabled
-- You must have [Resource Manager
- API](https://cloud.google.com/resource-manager/)
+The [Google authentication integration](../../../integration/google.md) must
+be enabled in GitLab at the instance level. If that's not the case, ask your
+GitLab administrator to enable it. On GitLab.com, this is enabled.
+
+### Requirements
+
+Before creating your first cluster on Google Kubernetes Engine with GitLab's
+integration, make sure the following requirements are met:
+
+- A [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account)
+ is set up and you have permissions to access it.
+- The Kubernetes Engine API is enabled. Follow the steps as outlined in the
+ ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin).
+
+### Creating the cluster
If all of the above requirements are met, you can proceed to create and add a
-new Kubernetes cluster that will be hosted on GKE to your project:
+new Kubernetes cluster to your project:
1. Navigate to your project's **Operations > Kubernetes** page.
+
+ NOTE: **Note:**
+ You need Maintainer [permissions] and above to access the Kubernetes page.
+
1. Click on **Add Kubernetes cluster**.
1. Click on **Create with Google Kubernetes Engine**.
1. Connect your Google account if you haven't done already by clicking the
**Sign in with Google** button.
-1. Fill in the requested values:
+1. From there on, choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.
- **Environment scope** - The [associated environment](#setting-the-environment-scope) to this cluster.
- - **Google Cloud Platform project** - The project you created in your GCP
- console that will host the Kubernetes cluster. This must **not** be confused
- with the project ID. Learn more about [Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
- - **Zone** - The [zone](https://cloud.google.com/compute/docs/regions-zones/)
+ - **Google Cloud Platform project** - Choose the project you created in your GCP
+ console that will host the Kubernetes cluster. Learn more about
+ [Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
+ - **Zone** - Choose the [region zone](https://cloud.google.com/compute/docs/regions-zones/)
under which the cluster will be created.
- - **Number of nodes** - The number of nodes you wish the cluster to have.
+ - **Number of nodes** - Enter the number of nodes you wish the cluster to have.
- **Machine type** - The [machine type](https://cloud.google.com/compute/docs/machine-types)
of the Virtual Machine instance that the cluster will be based on.
1. Finally, click the **Create Kubernetes cluster** button.
-After a few moments, your cluster should be created. If something goes wrong,
-you will be notified.
-
-You can now proceed to install some pre-defined applications and then
-enable the Cluster integration.
+After a couple of minutes, your cluster will be ready to go. You can now proceed
+to install some [pre-defined applications](#installing-applications).
## Adding an existing Kubernetes cluster
-NOTE: **Note:**
-You need Maintainer [permissions] and above to access the Kubernetes page.
-
To add an existing Kubernetes cluster to your project:
1. Navigate to your project's **Operations > Kubernetes** page.
+
+ NOTE: **Note:**
+ You need Maintainer [permissions] and above to access the Kubernetes page.
+
1. Click on **Add Kubernetes cluster**.
1. Click on **Add an existing Kubernetes cluster** and fill in the details:
- **Kubernetes cluster name** (required) - The name you wish to give the cluster.
@@ -91,9 +98,8 @@ To add an existing Kubernetes cluster to your project:
to create one. You can also view or create service tokens in the
[Kubernetes dashboard](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/#config)
(under **Config > Secrets**).
- - **Project namespace** (optional) - The following apply:
- - By default you don't have to fill it in; by leaving it blank, GitLab will
- create one for you.
+ - **Project namespace** (optional) - You don't have to fill it in; by leaving
+ it blank, GitLab will create one for you. Also:
- Each project should have a unique namespace.
- The project namespace is not necessarily the namespace of the secret, if
you're using a secret with broader permissions, like the secret from `default`.
@@ -103,11 +109,8 @@ To add an existing Kubernetes cluster to your project:
be the same.
1. Finally, click the **Create Kubernetes cluster** button.
-After a few moments, your cluster should be created. If something goes wrong,
-you will be notified.
-
-You can now proceed to install some pre-defined applications and then
-enable the Kubernetes cluster integration.
+After a couple of minutes, your cluster will be ready to go. You can now proceed
+to install some [pre-defined applications](#installing-applications).
## Security implications
@@ -152,9 +155,9 @@ added directly to your configured cluster. Those applications are needed for
| Application | GitLab version | Description |
| ----------- | :------------: | ----------- |
-| [Helm Tiller](https://docs.helm.sh/) | 10.2+ | Helm is a package manager for Kubernetes and is required to install all the other applications. It will be automatically installed as a dependency when you try to install a different app. It is installed in its own pod inside the cluster which can run the `helm` CLI in a safe environment. |
+| [Helm Tiller](https://docs.helm.sh/) | 10.2+ | Helm is a package manager for Kubernetes and is required to install all the other applications. It is installed in its own pod inside the cluster which can run the `helm` CLI in a safe environment. |
| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps] or deploy your own web apps. |
-| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications |
+| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications. |
| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](#security-implications) before doing so. |
| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. |
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index edb0c6bdc30..5dc62a30128 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -111,7 +111,7 @@ by yourself (except when an issue is due). You will only receive automatic
notifications when somebody else comments or adds changes to the ones that
you've created or mentions you.
-If a merge request becomes unmergeable, its author will be notified about the cause.
+If an open merge request becomes unmergeable due to conflict, its author will be notified about the cause.
If a user has also set the merge request to automatically merge once pipeline succeeds,
then that user will also be notified.
diff --git a/doc/workflow/todos.md b/doc/workflow/todos.md
index 762bf616268..760cd87d4cc 100644
--- a/doc/workflow/todos.md
+++ b/doc/workflow/todos.md
@@ -31,7 +31,7 @@ A Todo appears in your Todos dashboard when:
- you are `@mentioned` in a comment on a commit,
- a job in the CI pipeline running for your merge request failed, but this
job is not allowed to fail.
-- a merge request becomes unmergeable, and you are either:
+- an open merge request becomes unmergeable due to conflict, and you are either:
- the author, or
- have set it to automatically merge once pipeline succeeds.
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 1b1c83d9fb3..b0073a5f1ae 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -165,6 +165,8 @@ module Backup
progress.print " * #{wiki.full_path} ... "
begin
wiki.repository.create_from_bundle(path_to_wiki_bundle)
+ restore_custom_hooks(wiki)
+
progress.puts "[DONE]".color(:green)
rescue => e
progress.puts "[Failed] restoring #{wiki.full_path} wiki".color(:red)
diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb
index 4bc82ecb4d6..bb9f488cd87 100644
--- a/lib/banzai/filter/gollum_tags_filter.rb
+++ b/lib/banzai/filter/gollum_tags_filter.rb
@@ -56,10 +56,12 @@ module Banzai
# Pattern to match allowed image extensions
ALLOWED_IMAGE_EXTENSIONS = /.+(jpg|png|gif|svg|bmp)\z/i.freeze
+ # Do not perform linking inside these tags.
+ IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
+
def call
doc.search(".//text()").each do |node|
- # Do not perform linking inside <code> blocks
- next unless node.ancestors('code').empty?
+ next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS)
# A Gollum ToC tag is `[[_TOC_]]`, but due to MarkdownFilter running
# before this one, it will be converted into `[[<em>TOC</em>]]`, so it
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index d00e5b07f95..222aa06b800 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -4,6 +4,9 @@ module Gitlab
class Collection
class Item
def initialize(key:, value:, public: true, file: false)
+ raise ArgumentError, "`value` must be of type String, while it was: #{value.class}" unless
+ value.is_a?(String) || value.nil?
+
@variable = {
key: key, value: value, public: public, file: file
}
diff --git a/lib/gitlab/favicon.rb b/lib/gitlab/favicon.rb
index faf7016d73a..d512fc58e46 100644
--- a/lib/gitlab/favicon.rb
+++ b/lib/gitlab/favicon.rb
@@ -2,10 +2,10 @@ module Gitlab
class Favicon
class << self
def main
- return appearance_favicon.url if appearance_favicon.exists?
-
image_name =
- if Gitlab::Utils.to_boolean(ENV['CANARY'])
+ if appearance_favicon.exists?
+ appearance_favicon.url
+ elsif Gitlab::Utils.to_boolean(ENV['CANARY'])
'favicon-yellow.png'
elsif Rails.env.development?
'favicon-blue.png'
@@ -13,7 +13,7 @@ module Gitlab
'favicon.png'
end
- ActionController::Base.helpers.image_path(image_name)
+ ActionController::Base.helpers.image_path(image_name, host: host)
end
def status_overlay(status_name)
@@ -22,7 +22,7 @@ module Gitlab
"#{status_name}.png"
)
- ActionController::Base.helpers.image_path(path)
+ ActionController::Base.helpers.image_path(path, host: host)
end
def available_status_names
@@ -35,6 +35,16 @@ module Gitlab
private
+ # we only want to create full urls when there's a different asset_host
+ # configured.
+ def host
+ if Gitlab::Application.config.asset_host.nil? || Gitlab::Application.config.asset_host == Gitlab.config.gitlab.base_url
+ nil
+ else
+ Gitlab.config.gitlab.base_url
+ end
+ end
+
def appearance
RequestStore.store[:appearance] ||= (Appearance.current || Appearance.new)
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 93f9adaf1f1..a0fad3833a9 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -1494,7 +1494,11 @@ module Gitlab
def can_be_merged?(source_sha, target_branch)
gitaly_migrate(:can_be_merged) do |is_enabled|
if is_enabled
- gitaly_can_be_merged?(source_sha, find_branch(target_branch, true).target)
+ if branch = find_branch(target_branch, true)
+ gitaly_can_be_merged?(source_sha, branch.target)
+ else
+ false
+ end
else
rugged_can_be_merged?(source_sha, target_branch)
end
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
index 30af3e97b4a..d2133a6d65b 100644
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ b/lib/gitlab/kubernetes/helm/install_command.rb
@@ -2,11 +2,12 @@ module Gitlab
module Kubernetes
module Helm
class InstallCommand < BaseCommand
- attr_reader :name, :chart, :repository, :values
+ attr_reader :name, :chart, :version, :repository, :values
- def initialize(name, chart:, values:, repository: nil)
+ def initialize(name, chart:, values:, version: nil, repository: nil)
@name = name
@chart = chart
+ @version = version
@values = values
@repository = repository
end
@@ -39,9 +40,13 @@ module Gitlab
def script_command
<<~HEREDOC
- helm install #{chart} --name #{name} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null
+ helm install #{chart} --name #{name}#{optional_version_flag} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null
HEREDOC
end
+
+ def optional_version_flag
+ " --version #{version}" if version
+ end
end
end
end
diff --git a/lib/gitlab/verify/batch_verifier.rb b/lib/gitlab/verify/batch_verifier.rb
index 1ef369a4b67..167ba1b3149 100644
--- a/lib/gitlab/verify/batch_verifier.rb
+++ b/lib/gitlab/verify/batch_verifier.rb
@@ -7,13 +7,15 @@ module Gitlab
@batch_size = batch_size
@start = start
@finish = finish
+
+ fix_google_api_logger
end
# Yields a Range of IDs and a Hash of failed verifications (object => error)
def run_batches(&blk)
- relation.in_batches(of: batch_size, start: start, finish: finish) do |relation| # rubocop: disable Cop/InBatches
- range = relation.first.id..relation.last.id
- failures = run_batch(relation)
+ all_relation.in_batches(of: batch_size, start: start, finish: finish) do |batch| # rubocop: disable Cop/InBatches
+ range = batch.first.id..batch.last.id
+ failures = run_batch_for(batch)
yield(range, failures)
end
@@ -29,24 +31,56 @@ module Gitlab
private
- def run_batch(relation)
- relation.map { |upload| verify(upload) }.compact.to_h
+ def run_batch_for(batch)
+ batch.map { |upload| verify(upload) }.compact.to_h
end
def verify(object)
+ local?(object) ? verify_local(object) : verify_remote(object)
+ rescue => err
+ failure(object, err.inspect)
+ end
+
+ def verify_local(object)
expected = expected_checksum(object)
actual = actual_checksum(object)
- raise 'Checksum missing' unless expected.present?
- raise 'Checksum mismatch' unless expected == actual
+ return failure(object, 'Checksum missing') unless expected.present?
+ return failure(object, 'Checksum mismatch') unless expected == actual
+
+ success
+ end
+ # We don't calculate checksum for remote objects, so just check existence
+ def verify_remote(object)
+ return failure(object, 'Remote object does not exist') unless remote_object_exists?(object)
+
+ success
+ end
+
+ def success
nil
- rescue => err
- [object, err]
+ end
+
+ def failure(object, message)
+ [object, message]
+ end
+
+ # It's already set to Logger::INFO, but acts as if it is set to
+ # Logger::DEBUG, and this fixes it...
+ def fix_google_api_logger
+ if Object.const_defined?('Google::Apis')
+ Google::Apis.logger.level = Logger::INFO
+ end
end
# This should return an ActiveRecord::Relation suitable for calling #in_batches on
- def relation
+ def all_relation
+ raise NotImplementedError.new
+ end
+
+ # Should return true if the object is stored locally
+ def local?(_object)
raise NotImplementedError.new
end
@@ -59,6 +93,11 @@ module Gitlab
def actual_checksum(_object)
raise NotImplementedError.new
end
+
+ # Be sure to perform a hard check of the remote object (don't just check DB value)
+ def remote_object_exists?(object)
+ raise NotImplementedError.new
+ end
end
end
end
diff --git a/lib/gitlab/verify/job_artifacts.rb b/lib/gitlab/verify/job_artifacts.rb
index 03500a61074..dbadfbde9e3 100644
--- a/lib/gitlab/verify/job_artifacts.rb
+++ b/lib/gitlab/verify/job_artifacts.rb
@@ -11,10 +11,14 @@ module Gitlab
private
- def relation
+ def all_relation
::Ci::JobArtifact.all
end
+ def local?(artifact)
+ artifact.local_store?
+ end
+
def expected_checksum(artifact)
artifact.file_sha256
end
@@ -22,6 +26,10 @@ module Gitlab
def actual_checksum(artifact)
Digest::SHA256.file(artifact.file.path).hexdigest
end
+
+ def remote_object_exists?(artifact)
+ artifact.file.file.exists?
+ end
end
end
end
diff --git a/lib/gitlab/verify/lfs_objects.rb b/lib/gitlab/verify/lfs_objects.rb
index 970e2a7b718..d3f58a73ac7 100644
--- a/lib/gitlab/verify/lfs_objects.rb
+++ b/lib/gitlab/verify/lfs_objects.rb
@@ -11,8 +11,12 @@ module Gitlab
private
- def relation
- LfsObject.with_files_stored_locally
+ def all_relation
+ LfsObject.all
+ end
+
+ def local?(lfs_object)
+ lfs_object.local_store?
end
def expected_checksum(lfs_object)
@@ -22,6 +26,10 @@ module Gitlab
def actual_checksum(lfs_object)
LfsObject.calculate_oid(lfs_object.file.path)
end
+
+ def remote_object_exists?(lfs_object)
+ lfs_object.file.file.exists?
+ end
end
end
end
diff --git a/lib/gitlab/verify/rake_task.rb b/lib/gitlab/verify/rake_task.rb
index dd138e6b92b..e190eaddc79 100644
--- a/lib/gitlab/verify/rake_task.rb
+++ b/lib/gitlab/verify/rake_task.rb
@@ -45,7 +45,7 @@ module Gitlab
return unless verbose?
failures.each do |object, error|
- say " - #{verifier.describe(object)}: #{error.inspect}".color(:red)
+ say " - #{verifier.describe(object)}: #{error}".color(:red)
end
end
end
diff --git a/lib/gitlab/verify/uploads.rb b/lib/gitlab/verify/uploads.rb
index 0ffa71a6d72..73fc43cb590 100644
--- a/lib/gitlab/verify/uploads.rb
+++ b/lib/gitlab/verify/uploads.rb
@@ -11,8 +11,12 @@ module Gitlab
private
- def relation
- Upload.with_files_stored_locally
+ def all_relation
+ Upload.all.preload(:model)
+ end
+
+ def local?(upload)
+ upload.local?
end
def expected_checksum(upload)
@@ -22,6 +26,10 @@ module Gitlab
def actual_checksum(upload)
Upload.hexdigest(upload.absolute_path)
end
+
+ def remote_object_exists?(upload)
+ upload.build_uploader.file.exists?
+ end
end
end
end
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index 247d7be7d78..1827d9b2a9f 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -16,7 +16,6 @@ namespace :gettext do
# See: https://gitlab.com/gitlab-org/gitlab-ce/issues/33014#note_31218998
FileUtils.touch(File.join(Rails.root, 'locale/gitlab.pot'))
- Rake::Task['gettext:pack'].invoke
Rake::Task['gettext:po_to_json'].invoke
end
diff --git a/qa/qa.rb b/qa/qa.rb
index 503379823f4..5013024e60f 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -46,10 +46,13 @@ module QA
autoload :Runner, 'qa/factory/resource/runner'
autoload :PersonalAccessToken, 'qa/factory/resource/personal_access_token'
autoload :KubernetesCluster, 'qa/factory/resource/kubernetes_cluster'
+ autoload :Wiki, 'qa/factory/resource/wiki'
end
module Repository
autoload :Push, 'qa/factory/repository/push'
+ autoload :ProjectPush, 'qa/factory/repository/project_push'
+ autoload :WikiPush, 'qa/factory/repository/wiki_push'
end
module Settings
@@ -165,6 +168,16 @@ module QA
autoload :Show, 'qa/page/project/operations/kubernetes/show'
end
end
+
+ module Wiki
+ autoload :Edit, 'qa/page/project/wiki/edit'
+ autoload :New, 'qa/page/project/wiki/new'
+ autoload :Show, 'qa/page/project/wiki/show'
+ end
+ end
+
+ module Shared
+ autoload :ClonePanel, 'qa/page/shared/clone_panel'
end
module Profile
diff --git a/qa/qa/factory/repository/project_push.rb b/qa/qa/factory/repository/project_push.rb
new file mode 100644
index 00000000000..48674c08a8d
--- /dev/null
+++ b/qa/qa/factory/repository/project_push.rb
@@ -0,0 +1,34 @@
+module QA
+ module Factory
+ module Repository
+ class ProjectPush < Factory::Repository::Push
+ dependency Factory::Resource::Project, as: :project do |project|
+ project.name = 'project-with-code'
+ project.description = 'Project with repository'
+ end
+
+ product :output do |factory|
+ factory.output
+ end
+
+ def initialize
+ @file_name = 'file.txt'
+ @file_content = '# This is test project'
+ @commit_message = "This is a test commit"
+ @branch_name = 'master'
+ @new_branch = true
+ end
+
+ def repository_uri
+ @repository_uri ||= begin
+ project.visit!
+ Page::Project::Show.act do
+ choose_repository_clone_http
+ repository_location.uri
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb
index 7c0d580c5ca..4f97e65b091 100644
--- a/qa/qa/factory/repository/push.rb
+++ b/qa/qa/factory/repository/push.rb
@@ -5,25 +5,17 @@ module QA
module Repository
class Push < Factory::Base
attr_accessor :file_name, :file_content, :commit_message,
- :branch_name, :new_branch, :output
+ :branch_name, :new_branch, :output, :repository_uri
attr_writer :remote_branch
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-with-code'
- project.description = 'Project with repository'
- end
-
- product :output do |factory|
- factory.output
- end
-
def initialize
@file_name = 'file.txt'
- @file_content = '# This is test project'
+ @file_content = '# This is test file'
@commit_message = "This is a test commit"
@branch_name = 'master'
@new_branch = true
+ @repository_uri = ""
end
def remote_branch
@@ -37,14 +29,8 @@ module QA
end
def fabricate!
- project.visit!
-
Git::Repository.perform do |repository|
- repository.uri = Page::Project::Show.act do
- choose_repository_clone_http
- repository_location.uri
- end
-
+ repository.uri = repository_uri
repository.use_default_credentials
repository.clone
repository.configure_identity('GitLab QA', 'root@gitlab.com')
diff --git a/qa/qa/factory/repository/wiki_push.rb b/qa/qa/factory/repository/wiki_push.rb
new file mode 100644
index 00000000000..fb7c2bb660d
--- /dev/null
+++ b/qa/qa/factory/repository/wiki_push.rb
@@ -0,0 +1,32 @@
+module QA
+ module Factory
+ module Repository
+ class WikiPush < Factory::Repository::Push
+ dependency Factory::Resource::Wiki, as: :wiki do |wiki|
+ wiki.title = 'Home'
+ wiki.content = '# My First Wiki Content'
+ wiki.message = 'Update home'
+ end
+
+ def initialize
+ @file_name = 'Home.md'
+ @file_content = '# Welcome to My Wiki'
+ @commit_message = 'Updating Home Page'
+ @branch_name = 'master'
+ @new_branch = false
+ end
+
+ def repository_uri
+ @repository_uri ||= begin
+ wiki.visit!
+ Page::Project::Wiki::Show.act do
+ go_to_clone_repository
+ choose_repository_clone_http
+ repository_location.uri
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/factory/resource/branch.rb b/qa/qa/factory/resource/branch.rb
index 4cabe7eab45..7fb0633ec90 100644
--- a/qa/qa/factory/resource/branch.rb
+++ b/qa/qa/factory/resource/branch.rb
@@ -31,13 +31,13 @@ module QA
def fabricate!
project.visit!
- Factory::Repository::Push.fabricate! do |resource|
+ Factory::Repository::ProjectPush.fabricate! do |resource|
resource.project = project
resource.file_name = 'kick-off.txt'
resource.commit_message = 'First commit'
end
- branch = Factory::Repository::Push.fabricate! do |resource|
+ branch = Factory::Repository::ProjectPush.fabricate! do |resource|
resource.project = project
resource.file_name = 'README.md'
resource.commit_message = 'Add readme'
diff --git a/qa/qa/factory/resource/merge_request.rb b/qa/qa/factory/resource/merge_request.rb
index 7588ac5735d..24d3597d993 100644
--- a/qa/qa/factory/resource/merge_request.rb
+++ b/qa/qa/factory/resource/merge_request.rb
@@ -21,14 +21,14 @@ module QA
project.name = 'project-with-merge-request'
end
- dependency Factory::Repository::Push, as: :target do |push, factory|
+ dependency Factory::Repository::ProjectPush, as: :target do |push, factory|
factory.project.visit!
push.project = factory.project
push.branch_name = 'master'
push.remote_branch = factory.target_branch
end
- dependency Factory::Repository::Push, as: :source do |push, factory|
+ dependency Factory::Repository::ProjectPush, as: :source do |push, factory|
push.project = factory.project
push.branch_name = factory.target_branch
push.remote_branch = factory.source_branch
diff --git a/qa/qa/factory/resource/wiki.rb b/qa/qa/factory/resource/wiki.rb
new file mode 100644
index 00000000000..cc200a512d5
--- /dev/null
+++ b/qa/qa/factory/resource/wiki.rb
@@ -0,0 +1,25 @@
+module QA
+ module Factory
+ module Resource
+ class Wiki < Factory::Base
+ attr_accessor :title, :content, :message
+
+ dependency Factory::Resource::Project, as: :project do |project|
+ project.name = 'project-for-wikis'
+ project.description = 'project for adding wikis'
+ end
+
+ def fabricate!
+ Page::Menu::Side.act { click_wiki }
+ Page::Project::Wiki::New.perform do |page|
+ page.go_to_create_first_page
+ page.set_title(@title)
+ page.set_content(@content)
+ page.set_message(@message)
+ page.create_new_page
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/menu/side.rb b/qa/qa/page/menu/side.rb
index 3630b7e8568..6bf4825cf00 100644
--- a/qa/qa/page/menu/side.rb
+++ b/qa/qa/page/menu/side.rb
@@ -13,6 +13,7 @@ module QA
element :top_level_items, '.sidebar-top-level-items'
element :operations_section, "class: 'shortcuts-operations'"
element :activity_link, "title: 'Activity'"
+ element :wiki_link_text, "Wiki"
end
view 'app/assets/javascripts/fly_out_nav.js' do
@@ -61,6 +62,12 @@ module QA
end
end
+ def click_wiki
+ within_sidebar do
+ click_link('Wiki')
+ end
+ end
+
private
def hover_settings
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 5bbef040330..1406edece17 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -2,11 +2,7 @@ module QA
module Page
module Project
class Show < Page::Base
- view 'app/views/shared/_clone_panel.html.haml' do
- element :clone_dropdown
- element :clone_options_dropdown, '.clone-options-dropdown'
- element :project_repository_location, 'text_field_tag :project_clone'
- end
+ include Page::Shared::ClonePanel
view 'app/views/projects/_last_push.html.haml' do
element :create_merge_request
@@ -26,21 +22,6 @@ module QA
element :branches_dropdown
end
- def choose_repository_clone_http
- choose_repository_clone('HTTP', 'http')
- end
-
- def choose_repository_clone_ssh
- # It's not always beginning with ssh:// so detecting with @
- # would be more reliable because ssh would always contain it.
- # We can't use .git because HTTP also contain that part.
- choose_repository_clone('SSH', '@')
- end
-
- def repository_location
- Git::Location.new(find('#project_clone').value)
- end
-
def project_name
find('.qa-project-name').text
end
@@ -65,31 +46,11 @@ module QA
click_element :create_merge_request
end
- def wait_for_push
- sleep 5
- refresh
- end
-
def go_to_new_issue
click_element :new_menu_toggle
click_link 'New issue'
end
-
- private
-
- def choose_repository_clone(kind, detect_text)
- wait(reload: false) do
- click_element :clone_dropdown
-
- page.within('.clone-options-dropdown') do
- click_link(kind)
- end
-
- # Ensure git clone textbox was updated
- repository_location.git_uri.include?(detect_text)
- end
- end
end
end
end
diff --git a/qa/qa/page/project/wiki/edit.rb b/qa/qa/page/project/wiki/edit.rb
new file mode 100644
index 00000000000..6fa45569cc0
--- /dev/null
+++ b/qa/qa/page/project/wiki/edit.rb
@@ -0,0 +1,27 @@
+module QA
+ module Page
+ module Project
+ module Wiki
+ class Edit < Page::Base
+ view 'app/views/projects/wikis/_main_links.html.haml' do
+ element :new_page_link, 'New page'
+ element :page_history_link, 'Page history'
+ element :edit_page_link, 'Edit'
+ end
+
+ def go_to_new_page
+ click_on 'New page'
+ end
+
+ def got_to_view_history_page
+ click_on 'Page history'
+ end
+
+ def go_to_edit_page
+ click_on 'Edit'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/wiki/new.rb b/qa/qa/page/project/wiki/new.rb
new file mode 100644
index 00000000000..415b3835538
--- /dev/null
+++ b/qa/qa/page/project/wiki/new.rb
@@ -0,0 +1,45 @@
+module QA
+ module Page
+ module Project
+ module Wiki
+ class New < Page::Base
+ view 'app/views/projects/wikis/_form.html.haml' do
+ element :wiki_title_textbox, 'text_field :title'
+ element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content"
+ element :wiki_message_textbox, 'text_field :message'
+ element :save_changes_button, 'submit _("Save changes")'
+ element :create_page_button, 'submit s_("Wiki|Create page")'
+ end
+
+ view 'app/views/shared/empty_states/_wikis.html.haml' do
+ element :create_link, 'Create your first page'
+ end
+
+ def go_to_create_first_page
+ click_link 'Create your first page'
+ end
+
+ def set_title(title)
+ fill_in 'wiki_title', with: title
+ end
+
+ def set_content(content)
+ fill_in 'wiki_content', with: content
+ end
+
+ def set_message(message)
+ fill_in 'wiki_message', with: message
+ end
+
+ def save_changes
+ click_on 'Save changes'
+ end
+
+ def create_new_page
+ click_on 'Create page'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb
new file mode 100644
index 00000000000..044e514bab3
--- /dev/null
+++ b/qa/qa/page/project/wiki/show.rb
@@ -0,0 +1,19 @@
+module QA
+ module Page
+ module Project
+ module Wiki
+ class Show < Page::Base
+ include Page::Shared::ClonePanel
+
+ view 'app/views/projects/wikis/pages.html.haml' do
+ element :clone_repository_link, 'Clone repository'
+ end
+
+ def go_to_clone_repository
+ click_on 'Clone repository'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/shared/clone_panel.rb b/qa/qa/page/shared/clone_panel.rb
new file mode 100644
index 00000000000..73e3dff956d
--- /dev/null
+++ b/qa/qa/page/shared/clone_panel.rb
@@ -0,0 +1,50 @@
+module QA
+ module Page
+ module Shared
+ module ClonePanel
+ def self.included(base)
+ base.view 'app/views/shared/_clone_panel.html.haml' do
+ element :clone_dropdown
+ element :clone_options_dropdown, '.clone-options-dropdown'
+ element :project_repository_location, 'text_field_tag :project_clone'
+ end
+ end
+
+ def choose_repository_clone_http
+ choose_repository_clone('HTTP', 'http')
+ end
+
+ def choose_repository_clone_ssh
+ # It's not always beginning with ssh:// so detecting with @
+ # would be more reliable because ssh would always contain it.
+ # We can't use .git because HTTP also contain that part.
+ choose_repository_clone('SSH', '@')
+ end
+
+ def repository_location
+ Git::Location.new(find('#project_clone').value)
+ end
+
+ def wait_for_push
+ sleep 5
+ refresh
+ end
+
+ private
+
+ def choose_repository_clone(kind, detect_text)
+ wait(reload: false) do
+ click_element :clone_dropdown
+
+ page.within('.clone-options-dropdown') do
+ click_link(kind)
+ end
+
+ # Ensure git clone textbox was updated
+ repository_location.git_uri.include?(detect_text)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/merge_request/rebase_spec.rb b/qa/qa/specs/features/merge_request/rebase_spec.rb
index 2a44d42af6f..6a0ed4592c4 100644
--- a/qa/qa/specs/features/merge_request/rebase_spec.rb
+++ b/qa/qa/specs/features/merge_request/rebase_spec.rb
@@ -16,7 +16,7 @@ module QA
merge_request.title = 'Needs rebasing'
end
- Factory::Repository::Push.fabricate! do |push|
+ Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.file_name = "other.txt"
push.file_content = "New file added!"
diff --git a/qa/qa/specs/features/merge_request/squash_spec.rb b/qa/qa/specs/features/merge_request/squash_spec.rb
index dbbdf852a38..b68704154cf 100644
--- a/qa/qa/specs/features/merge_request/squash_spec.rb
+++ b/qa/qa/specs/features/merge_request/squash_spec.rb
@@ -13,7 +13,7 @@ module QA
merge_request.title = 'Squashing commits'
end
- Factory::Repository::Push.fabricate! do |push|
+ Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.commit_message = 'to be squashed'
push.branch_name = merge_request.source_branch
diff --git a/qa/qa/specs/features/project/activity_spec.rb b/qa/qa/specs/features/project/activity_spec.rb
index ba94ce8cf28..07ac7321aa2 100644
--- a/qa/qa/specs/features/project/activity_spec.rb
+++ b/qa/qa/specs/features/project/activity_spec.rb
@@ -4,7 +4,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Repository::Push.fabricate! do |push|
+ Factory::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
push.file_content = '# This is a test project'
push.commit_message = 'Add README.md'
diff --git a/qa/qa/specs/features/project/auto_devops_spec.rb b/qa/qa/specs/features/project/auto_devops_spec.rb
index 202a847d1a5..c50a13432f5 100644
--- a/qa/qa/specs/features/project/auto_devops_spec.rb
+++ b/qa/qa/specs/features/project/auto_devops_spec.rb
@@ -16,7 +16,7 @@ module QA
end
# Create Auto Devops compatible repo
- Factory::Repository::Push.fabricate! do |push|
+ Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.directory = Pathname
.new(__dir__)
diff --git a/qa/qa/specs/features/project/deploy_key_clone_spec.rb b/qa/qa/specs/features/project/deploy_key_clone_spec.rb
index 46b3e38c1c5..10e4cbb6906 100644
--- a/qa/qa/specs/features/project/deploy_key_clone_spec.rb
+++ b/qa/qa/specs/features/project/deploy_key_clone_spec.rb
@@ -75,7 +75,7 @@ module QA
- docker
YAML
- Factory::Repository::Push.fabricate! do |resource|
+ Factory::Repository::ProjectPush.fabricate! do |resource|
resource.project = @project
resource.file_name = '.gitlab-ci.yml'
resource.commit_message = 'Add .gitlab-ci.yml'
diff --git a/qa/qa/specs/features/project/pipelines_spec.rb b/qa/qa/specs/features/project/pipelines_spec.rb
index 74f6474443d..bdb3d671516 100644
--- a/qa/qa/specs/features/project/pipelines_spec.rb
+++ b/qa/qa/specs/features/project/pipelines_spec.rb
@@ -40,7 +40,7 @@ module QA
runner.tags = %w[qa test]
end
- Factory::Repository::Push.fabricate! do |push|
+ Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.file_name = '.gitlab-ci.yml'
push.commit_message = 'Add .gitlab-ci.yml'
diff --git a/qa/qa/specs/features/project/wikis_spec.rb b/qa/qa/specs/features/project/wikis_spec.rb
new file mode 100644
index 00000000000..49290a1a896
--- /dev/null
+++ b/qa/qa/specs/features/project/wikis_spec.rb
@@ -0,0 +1,45 @@
+module QA
+ feature 'Wiki Functionality', :core do
+ def login
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+ end
+
+ def validate_content(content)
+ expect(page).to have_content('Wiki was successfully updated')
+ expect(page).to have_content(/#{content}/)
+ end
+
+ before do
+ login
+ end
+
+ scenario 'User creates, edits, clones, and pushes to the wiki' do
+ wiki = Factory::Resource::Wiki.fabricate! do |resource|
+ resource.title = 'Home'
+ resource.content = '# My First Wiki Content'
+ resource.message = 'Update home'
+ end
+
+ validate_content('My First Wiki Content')
+
+ Page::Project::Wiki::Edit.act { go_to_edit_page }
+ Page::Project::Wiki::New.perform do |page|
+ page.set_content("My Second Wiki Content")
+ page.save_changes
+ end
+
+ validate_content('My Second Wiki Content')
+
+ Factory::Repository::WikiPush.fabricate! do |push|
+ push.wiki = wiki
+ push.file_name = 'Home.md'
+ push.file_content = '# My Third Wiki Content'
+ push.commit_message = 'Update Home.md'
+ end
+ Page::Menu::Side.act { click_wiki }
+
+ expect(page).to have_content('My Third Wiki Content')
+ end
+ end
+end
diff --git a/qa/qa/specs/features/repository/protected_branches_spec.rb b/qa/qa/specs/features/repository/protected_branches_spec.rb
index 491675875b9..c5b8c271d7d 100644
--- a/qa/qa/specs/features/repository/protected_branches_spec.rb
+++ b/qa/qa/specs/features/repository/protected_branches_spec.rb
@@ -13,11 +13,15 @@ module QA
Page::Main::Login.act { sign_in_using_credentials }
end
- after do
+ after do |example|
# We need to clear localStorage because we're using it for the dropdown,
# and capybara doesn't do this for us.
# https://github.com/teamcapybara/capybara/issues/1702
Capybara.execute_script 'localStorage.clear()'
+
+ # In order to help diagnose a false failure
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/48241
+ log_push_output if example.exception
end
context 'when developers and maintainers are allowed to push to a protected branch' do
@@ -27,9 +31,9 @@ module QA
expect(protected_branch.name).to have_content(branch_name)
expect(protected_branch.push_allowance).to have_content('Developers + Maintainers')
- push = push_new_file(branch_name)
+ @push = push_new_file(branch_name)
- expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/)
+ expect(@push.output).to match(/remote: To create a merge request for protected-branch, visit/)
end
end
@@ -37,11 +41,11 @@ module QA
scenario 'user without push rights fails to push to the protected branch' do
create_protected_branch(allow_to_push: false)
- push = push_new_file(branch_name)
+ @push = push_new_file(branch_name)
- expect(push.output)
+ expect(@push.output)
.to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/)
- expect(push.output)
+ expect(@push.output)
.to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/)
end
end
@@ -56,7 +60,7 @@ module QA
end
def push_new_file(branch)
- Factory::Repository::Push.fabricate! do |resource|
+ Factory::Repository::ProjectPush.fabricate! do |resource|
resource.project = project
resource.file_name = 'new_file.md'
resource.file_content = '# This is a new file'
@@ -65,5 +69,13 @@ module QA
resource.new_branch = false
end
end
+
+ def log_push_output
+ if defined?(@push)
+ filename = File.join('tmp', "push-output-#{project.name}")
+ puts "Exception detected. Push output will be saved to #{filename}"
+ IO.binwrite(filename, @push.output)
+ end
+ end
end
end
diff --git a/qa/qa/specs/features/repository/push_spec.rb b/qa/qa/specs/features/repository/push_spec.rb
index 51d9c2c7fd2..16aaa2e6762 100644
--- a/qa/qa/specs/features/repository/push_spec.rb
+++ b/qa/qa/specs/features/repository/push_spec.rb
@@ -5,7 +5,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Repository::Push.fabricate! do |push|
+ Factory::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
push.file_content = '# This is a test project'
push.commit_message = 'Add README.md'
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 555b186fe31..7e048843e2f 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -53,21 +53,22 @@ describe SessionsController do
include UserActivitiesHelpers
let(:user) { create(:user) }
+ let(:user_params) { { login: user.username, password: user.password } }
it 'authenticates user correctly' do
- post(:create, user: { login: user.username, password: user.password })
+ post(:create, user: user_params)
expect(subject.current_user). to eq user
end
it 'creates an audit log record' do
- expect { post(:create, user: { login: user.username, password: user.password }) }.to change { SecurityEvent.count }.by(1)
+ expect { post(:create, user: user_params) }.to change { SecurityEvent.count }.by(1)
expect(SecurityEvent.last.details[:with]).to eq('standard')
end
include_examples 'user login request with unique ip limit', 302 do
def request
- post(:create, user: { login: user.username, password: user.password })
+ post(:create, user: user_params)
expect(subject.current_user).to eq user
subject.sign_out user
end
@@ -75,10 +76,40 @@ describe SessionsController do
it 'updates the user activity' do
expect do
- post(:create, user: { login: user.username, password: user.password })
+ post(:create, user: user_params)
end.to change { user_activity(user) }
end
end
+
+ context 'when reCAPTCHA is enabled' do
+ let(:user) { create(:user) }
+ let(:user_params) { { login: user.username, password: user.password } }
+
+ before do
+ stub_application_setting(recaptcha_enabled: true)
+ request.headers[described_class::CAPTCHA_HEADER] = 1
+ end
+
+ it 'displays an error when the reCAPTCHA is not solved' do
+ # Without this, `verify_recaptcha` arbitraily returns true in test env
+ Recaptcha.configuration.skip_verify_env.delete('test')
+
+ post(:create, user: user_params)
+
+ expect(response).to render_template(:new)
+ expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
+ expect(subject.current_user).to be_nil
+ end
+
+ it 'successfully logs in a user when reCAPTCHA is solved' do
+ # Avoid test ordering issue and ensure `verify_recaptcha` returns true
+ Recaptcha.configuration.skip_verify_env << 'test'
+
+ post(:create, user: user_params)
+
+ expect(subject.current_user).to eq user
+ end
+ end
end
context 'when using two-factor authentication via OTP' do
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index e79f0a7f257..adb3ff4321f 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -1,19 +1,69 @@
require 'spec_helper'
describe Gitlab::Ci::Variables::Collection::Item do
+ let(:variable_key) { 'VAR' }
+ let(:variable_value) { 'something' }
+ let(:expected_value) { variable_value }
+
let(:variable) do
- { key: 'VAR', value: 'something', public: true }
+ { key: variable_key, value: variable_value, public: true }
end
describe '.new' do
- it 'raises error if unknown key i specified' do
- expect { described_class.new(key: 'VAR', value: 'abc', files: true) }
- .to raise_error ArgumentError, 'unknown keyword: files'
+ context 'when unknown keyword is specified' do
+ it 'raises error' do
+ expect { described_class.new(key: variable_key, value: 'abc', files: true) }
+ .to raise_error ArgumentError, 'unknown keyword: files'
+ end
+ end
+
+ context 'when required keywords are not specified' do
+ it 'raises error' do
+ expect { described_class.new(key: variable_key) }
+ .to raise_error ArgumentError, 'missing keyword: value'
+ end
end
- it 'raises error when required keywords are not specified' do
- expect { described_class.new(key: 'VAR') }
- .to raise_error ArgumentError, 'missing keyword: value'
+ shared_examples 'creates variable' do
+ subject { described_class.new(key: variable_key, value: variable_value) }
+
+ it 'saves given value' do
+ expect(subject[:key]).to eq variable_key
+ expect(subject[:value]).to eq expected_value
+ end
+ end
+
+ shared_examples 'raises error for invalid type' do
+ it do
+ expect { described_class.new(key: variable_key, value: variable_value) }
+ .to raise_error ArgumentError, /`value` must be of type String, while it was:/
+ end
+ end
+
+ it_behaves_like 'creates variable'
+
+ context "when it's nil" do
+ let(:variable_value) { nil }
+ let(:expected_value) { nil }
+
+ it_behaves_like 'creates variable'
+ end
+
+ context "when it's an empty string" do
+ let(:variable_value) { '' }
+ let(:expected_value) { '' }
+
+ it_behaves_like 'creates variable'
+ end
+
+ context 'when provided value is not a string' do
+ [1, false, [], {}, Object.new].each do |val|
+ context "when it's #{val}" do
+ let(:variable_value) { val }
+
+ it_behaves_like 'raises error for invalid type'
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection_spec.rb b/spec/lib/gitlab/ci/variables/collection_spec.rb
index cb2f7718c9c..5c91816a586 100644
--- a/spec/lib/gitlab/ci/variables/collection_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection_spec.rb
@@ -29,7 +29,7 @@ describe Gitlab::Ci::Variables::Collection do
end
it 'appends an internal resource' do
- collection = described_class.new([{ key: 'TEST', value: 1 }])
+ collection = described_class.new([{ key: 'TEST', value: '1' }])
subject.append(collection.first)
@@ -74,15 +74,15 @@ describe Gitlab::Ci::Variables::Collection do
describe '#+' do
it 'makes it possible to combine with an array' do
- collection = described_class.new([{ key: 'TEST', value: 1 }])
+ collection = described_class.new([{ key: 'TEST', value: '1' }])
variables = [{ key: 'TEST', value: 'something' }]
expect((collection + variables).count).to eq 2
end
it 'makes it possible to combine with another collection' do
- collection = described_class.new([{ key: 'TEST', value: 1 }])
- other = described_class.new([{ key: 'TEST', value: 2 }])
+ collection = described_class.new([{ key: 'TEST', value: '1' }])
+ other = described_class.new([{ key: 'TEST', value: '2' }])
expect((collection + other).count).to eq 2
end
@@ -90,10 +90,10 @@ describe Gitlab::Ci::Variables::Collection do
describe '#to_runner_variables' do
it 'creates an array of hashes in a runner-compatible format' do
- collection = described_class.new([{ key: 'TEST', value: 1 }])
+ collection = described_class.new([{ key: 'TEST', value: '1' }])
expect(collection.to_runner_variables)
- .to eq [{ key: 'TEST', value: 1, public: true }]
+ .to eq [{ key: 'TEST', value: '1', public: true }]
end
end
diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb
index 5e54fd2a1f9..844ad3e895f 100644
--- a/spec/lib/gitlab/favicon_spec.rb
+++ b/spec/lib/gitlab/favicon_spec.rb
@@ -21,6 +21,21 @@ RSpec.describe Gitlab::Favicon, :request_store do
create :appearance, favicon: fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'))
expect(described_class.main).to match %r{/uploads/-/system/appearance/favicon/\d+/dk.png}
end
+
+ context 'asset host' do
+ before do
+ allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production'))
+ end
+
+ it 'returns a relative url when the asset host is not configured' do
+ expect(described_class.main).to match %r{^/assets/favicon-(?:\h+).png$}
+ end
+
+ it 'returns a full url when the asset host is configured' do
+ allow(Gitlab::Application.config).to receive(:asset_host).and_return('http://assets.local')
+ expect(described_class.main).to match %r{^http://localhost/assets/favicon-(?:\h+).png$}
+ end
+ end
end
describe '.status_overlay' do
diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
index 740466ea5cb..aa7e43dfb16 100644
--- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
@@ -7,13 +7,7 @@ describe Gitlab::Kubernetes::Helm::Api do
let(:namespace) { Gitlab::Kubernetes::Namespace.new(gitlab_namespace, client) }
let(:application) { create(:clusters_applications_prometheus) }
- let(:command) do
- Gitlab::Kubernetes::Helm::InstallCommand.new(
- application.name,
- chart: application.chart,
- values: application.values
- )
- end
+ let(:command) { application.install_command }
subject { helm }
diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
index 547f3f1752c..25c6fa3b9a3 100644
--- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
@@ -3,44 +3,60 @@ require 'rails_helper'
describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:application) { create(:clusters_applications_prometheus) }
let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
-
- let(:install_command) do
- described_class.new(
- application.name,
- chart: application.chart,
- values: application.values
- )
- end
+ let(:install_command) { application.install_command }
subject { install_command }
- it_behaves_like 'helm commands' do
- let(:commands) do
- <<~EOS
+ context 'for ingress' do
+ let(:application) { create(:clusters_applications_ingress) }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
helm init --client-only >/dev/null
helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
- EOS
+ EOS
+ end
+ end
+ end
+
+ context 'for prometheus' do
+ let(:application) { create(:clusters_applications_prometheus) }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --client-only >/dev/null
+ helm install #{application.chart} --name #{application.name} --version #{application.version} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
+ EOS
+ end
end
end
- context 'with an application with a repository' do
+ context 'for runner' do
let(:ci_runner) { create(:ci_runner) }
let(:application) { create(:clusters_applications_runner, runner: ci_runner) }
- let(:install_command) do
- described_class.new(
- application.name,
- chart: application.chart,
- values: application.values,
- repository: application.repository
- )
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --client-only >/dev/null
+ helm repo add #{application.name} #{application.repository}
+ helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
+ EOS
+ end
end
+ end
+
+ context 'for jupyter' do
+ let(:application) { create(:clusters_applications_jupyter) }
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --client-only >/dev/null
- helm repo add #{application.name} #{application.repository}
- helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
+ helm init --client-only >/dev/null
+ helm repo add #{application.name} #{application.repository}
+ helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null
EOS
end
end
diff --git a/spec/lib/gitlab/verify/job_artifacts_spec.rb b/spec/lib/gitlab/verify/job_artifacts_spec.rb
index ec490bdfde2..6e916a56564 100644
--- a/spec/lib/gitlab/verify/job_artifacts_spec.rb
+++ b/spec/lib/gitlab/verify/job_artifacts_spec.rb
@@ -21,15 +21,38 @@ describe Gitlab::Verify::JobArtifacts do
FileUtils.rm_f(artifact.file.path)
expect(failures.keys).to contain_exactly(artifact)
- expect(failure).to be_a(Errno::ENOENT)
- expect(failure.to_s).to include(artifact.file.path)
+ expect(failure).to include('No such file or directory')
+ expect(failure).to include(artifact.file.path)
end
it 'fails artifacts with a mismatched checksum' do
File.truncate(artifact.file.path, 0)
expect(failures.keys).to contain_exactly(artifact)
- expect(failure.to_s).to include('Checksum mismatch')
+ expect(failure).to include('Checksum mismatch')
+ end
+
+ context 'with remote files' do
+ let(:file) { double(:file) }
+
+ before do
+ stub_artifacts_object_storage
+ artifact.update!(file_store: ObjectStorage::Store::REMOTE)
+ expect(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file)
+ end
+
+ it 'passes artifacts in object storage that exist' do
+ expect(file).to receive(:exists?).and_return(true)
+
+ expect(failures).to eq({})
+ end
+
+ it 'fails artifacts in object storage that do not exist' do
+ expect(file).to receive(:exists?).and_return(false)
+
+ expect(failures.keys).to contain_exactly(artifact)
+ expect(failure).to include('Remote object does not exist')
+ end
end
end
end
diff --git a/spec/lib/gitlab/verify/lfs_objects_spec.rb b/spec/lib/gitlab/verify/lfs_objects_spec.rb
index 0f890e2c7ce..2feaedd6f14 100644
--- a/spec/lib/gitlab/verify/lfs_objects_spec.rb
+++ b/spec/lib/gitlab/verify/lfs_objects_spec.rb
@@ -21,30 +21,37 @@ describe Gitlab::Verify::LfsObjects do
FileUtils.rm_f(lfs_object.file.path)
expect(failures.keys).to contain_exactly(lfs_object)
- expect(failure).to be_a(Errno::ENOENT)
- expect(failure.to_s).to include(lfs_object.file.path)
+ expect(failure).to include('No such file or directory')
+ expect(failure).to include(lfs_object.file.path)
end
it 'fails LFS objects with a mismatched oid' do
File.truncate(lfs_object.file.path, 0)
expect(failures.keys).to contain_exactly(lfs_object)
- expect(failure.to_s).to include('Checksum mismatch')
+ expect(failure).to include('Checksum mismatch')
end
context 'with remote files' do
+ let(:file) { double(:file) }
+
before do
stub_lfs_object_storage
+ lfs_object.update!(file_store: ObjectStorage::Store::REMOTE)
+ expect(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file)
end
- it 'skips LFS objects in object storage' do
- local_failure = create(:lfs_object)
- create(:lfs_object, :object_storage)
+ it 'passes LFS objects in object storage that exist' do
+ expect(file).to receive(:exists?).and_return(true)
+
+ expect(failures).to eq({})
+ end
- failures = {}
- described_class.new(batch_size: 10).run_batches { |_, failed| failures.merge!(failed) }
+ it 'fails LFS objects in object storage that do not exist' do
+ expect(file).to receive(:exists?).and_return(false)
- expect(failures.keys).to contain_exactly(local_failure)
+ expect(failures.keys).to contain_exactly(lfs_object)
+ expect(failure).to include('Remote object does not exist')
end
end
end
diff --git a/spec/lib/gitlab/verify/uploads_spec.rb b/spec/lib/gitlab/verify/uploads_spec.rb
index 85768308edc..38c30fab1ba 100644
--- a/spec/lib/gitlab/verify/uploads_spec.rb
+++ b/spec/lib/gitlab/verify/uploads_spec.rb
@@ -23,37 +23,73 @@ describe Gitlab::Verify::Uploads do
FileUtils.rm_f(upload.absolute_path)
expect(failures.keys).to contain_exactly(upload)
- expect(failure).to be_a(Errno::ENOENT)
- expect(failure.to_s).to include(upload.absolute_path)
+ expect(failure).to include('No such file or directory')
+ expect(failure).to include(upload.absolute_path)
end
it 'fails uploads with a mismatched checksum' do
upload.update!(checksum: 'something incorrect')
expect(failures.keys).to contain_exactly(upload)
- expect(failure.to_s).to include('Checksum mismatch')
+ expect(failure).to include('Checksum mismatch')
end
it 'fails uploads with a missing precalculated checksum' do
upload.update!(checksum: '')
expect(failures.keys).to contain_exactly(upload)
- expect(failure.to_s).to include('Checksum missing')
+ expect(failure).to include('Checksum missing')
end
context 'with remote files' do
+ let(:file) { double(:file) }
+
before do
stub_uploads_object_storage(AvatarUploader)
+ upload.update!(store: ObjectStorage::Store::REMOTE)
end
- it 'skips uploads in object storage' do
- local_failure = create(:upload)
- create(:upload, :object_storage)
+ describe 'returned hash object' do
+ before do
+ expect(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file)
+ end
+
+ it 'passes uploads in object storage that exist' do
+ expect(file).to receive(:exists?).and_return(true)
+
+ expect(failures).to eq({})
+ end
+
+ it 'fails uploads in object storage that do not exist' do
+ expect(file).to receive(:exists?).and_return(false)
+
+ expect(failures.keys).to contain_exactly(upload)
+ expect(failure).to include('Remote object does not exist')
+ end
+ end
+
+ describe 'performance' do
+ before do
+ allow(file).to receive(:exists?)
+ allow(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file)
+ end
+
+ it "avoids N+1 queries" do
+ control_count = ActiveRecord::QueryRecorder.new { perform_task }
+
+ # Create additional uploads in object storage
+ projects = create_list(:project, 3, :with_avatar)
+ uploads = projects.flat_map(&:uploads)
+ uploads.each do |upload|
+ upload.update!(store: ObjectStorage::Store::REMOTE)
+ end
- failures = {}
- described_class.new(batch_size: 10).run_batches { |_, failed| failures.merge!(failed) }
+ expect { perform_task }.not_to exceed_query_limit(control_count)
+ end
- expect(failures.keys).to contain_exactly(local_failure)
+ def perform_task
+ described_class.new(batch_size: 100).run_batches { }
+ end
end
end
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 775ca4ba0eb..a9a45367b4a 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -416,16 +416,10 @@ describe Notify do
end
it 'has the correct subject and body' do
- reasons = %w[foo bar]
-
- allow_any_instance_of(MergeRequestPresenter).to receive(:unmergeable_reasons).and_return(reasons)
aggregate_failures do
is_expected.to have_referable_subject(merge_request, reply: true)
is_expected.to have_body_text(project_merge_request_path(project, merge_request))
- is_expected.to have_body_text('following reasons:')
- reasons.each do |reason|
- is_expected.to have_body_text(reason)
- end
+ is_expected.to have_body_text('due to conflict.')
end
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 0a0d7d3fea9..1b01c31a17f 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1869,7 +1869,11 @@ describe Ci::Build do
end
context 'when yaml_variables are undefined' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: project.default_branch)
+ end
before do
build.yaml_variables = nil
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index a47a07d908d..bb5b2ef3a47 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -73,6 +73,7 @@ describe Clusters::Applications::Ingress do
it 'should be initialized with ingress arguments' do
expect(subject.name).to eq('ingress')
expect(subject.chart).to eq('stable/nginx-ingress')
+ expect(subject.version).to be_nil
expect(subject.values).to eq(ingress.values)
end
end
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index ca48a1d8072..65750141e65 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -36,6 +36,7 @@ describe Clusters::Applications::Jupyter do
it 'should be initialized with 4 arguments' do
expect(subject.name).to eq('jupyter')
expect(subject.chart).to eq('jupyter/jupyterhub')
+ expect(subject.version).to be_nil
expect(subject.repository).to eq('https://jupyterhub.github.io/helm-chart/')
expect(subject.values).to eq(jupyter.values)
end
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index d2302583ac8..efd57040005 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -109,6 +109,7 @@ describe Clusters::Applications::Prometheus do
it 'should be initialized with 3 arguments' do
expect(subject.name).to eq('prometheus')
expect(subject.chart).to eq('stable/prometheus')
+ expect(subject.version).to eq('6.7.3')
expect(subject.values).to eq(prometheus.values)
end
end
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 3ef59457c5f..b12500d0acd 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -31,6 +31,7 @@ describe Clusters::Applications::Runner do
it 'should be initialized with 4 arguments' do
expect(subject.name).to eq('runner')
expect(subject.chart).to eq('runner/gitlab-runner')
+ expect(subject.version).to be_nil
expect(subject.repository).to eq('https://charts.gitlab.io')
expect(subject.values).to eq(gitlab_runner.values)
end
diff --git a/spec/models/concerns/sortable_spec.rb b/spec/models/concerns/sortable_spec.rb
index b821a84d5e0..39c16ae60af 100644
--- a/spec/models/concerns/sortable_spec.rb
+++ b/spec/models/concerns/sortable_spec.rb
@@ -40,15 +40,25 @@ describe Sortable do
describe 'ordering by name' do
it 'ascending' do
- expect(relation).to receive(:reorder).with("lower(name) asc")
+ expect(relation).to receive(:reorder).once.and_call_original
- relation.order_by('name_asc')
+ table = Regexp.escape(ActiveRecord::Base.connection.quote_table_name(:namespaces))
+ column = Regexp.escape(ActiveRecord::Base.connection.quote_column_name(:name))
+
+ sql = relation.order_by('name_asc').to_sql
+
+ expect(sql).to match /.+ORDER BY LOWER\(#{table}.#{column}\) ASC\z/
end
it 'descending' do
- expect(relation).to receive(:reorder).with("lower(name) desc")
+ expect(relation).to receive(:reorder).once.and_call_original
+
+ table = Regexp.escape(ActiveRecord::Base.connection.quote_table_name(:namespaces))
+ column = Regexp.escape(ActiveRecord::Base.connection.quote_column_name(:name))
+
+ sql = relation.order_by('name_desc').to_sql
- relation.order_by('name_desc')
+ expect(sql).to match /.+ORDER BY LOWER\(#{table}.#{column}\) DESC\z/
end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 3f028b3bd5c..4b957c8a29f 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -1324,6 +1324,7 @@ describe MergeRequest do
context 'when broken' do
before do
allow(subject).to receive(:broken?) { true }
+ allow(project.repository).to receive(:can_be_merged?).and_return(false)
end
it 'becomes unmergeable' do
@@ -2144,32 +2145,61 @@ describe MergeRequest do
describe 'transition to cannot_be_merged' do
let(:notification_service) { double(:notification_service) }
let(:todo_service) { double(:todo_service) }
-
- subject { create(:merge_request, merge_status: :unchecked) }
+ subject { create(:merge_request, state, merge_status: :unchecked) }
before do
allow(NotificationService).to receive(:new).and_return(notification_service)
allow(TodoService).to receive(:new).and_return(todo_service)
+
+ allow(subject.project.repository).to receive(:can_be_merged?).and_return(false)
end
- it 'notifies, but does not notify again if rechecking still results in cannot_be_merged' do
- expect(notification_service).to receive(:merge_request_unmergeable).with(subject).once
- expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).once
+ [:opened, :locked].each do |state|
+ context state do
+ let(:state) { state }
+
+ it 'notifies conflict, but does not notify again if rechecking still results in cannot_be_merged' do
+ expect(notification_service).to receive(:merge_request_unmergeable).with(subject).once
+ expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).once
+
+ subject.mark_as_unmergeable
+ subject.mark_as_unchecked
+ subject.mark_as_unmergeable
+ end
+
+ it 'notifies conflict, whenever newly unmergeable' do
+ expect(notification_service).to receive(:merge_request_unmergeable).with(subject).twice
+ expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).twice
+
+ subject.mark_as_unmergeable
+ subject.mark_as_unchecked
+ subject.mark_as_mergeable
+ subject.mark_as_unchecked
+ subject.mark_as_unmergeable
+ end
+
+ it 'does not notify whenever merge request is newly unmergeable due to other reasons' do
+ allow(subject.project.repository).to receive(:can_be_merged?).and_return(true)
- subject.mark_as_unmergeable
- subject.mark_as_unchecked
- subject.mark_as_unmergeable
+ expect(notification_service).not_to receive(:merge_request_unmergeable)
+ expect(todo_service).not_to receive(:merge_request_became_unmergeable)
+
+ subject.mark_as_unmergeable
+ end
+ end
end
- it 'notifies whenever merge request is newly unmergeable' do
- expect(notification_service).to receive(:merge_request_unmergeable).with(subject).twice
- expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).twice
+ [:closed, :merged].each do |state|
+ let(:state) { state }
+
+ context state do
+ it 'does not notify' do
+ expect(notification_service).not_to receive(:merge_request_unmergeable)
+ expect(todo_service).not_to receive(:merge_request_became_unmergeable)
- subject.mark_as_unmergeable
- subject.mark_as_unchecked
- subject.mark_as_mergeable
- subject.mark_as_unchecked
- subject.mark_as_unmergeable
+ subject.mark_as_unmergeable
+ end
+ end
end
end
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index d5fb4a7742c..e3b37739e8e 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -70,41 +70,6 @@ describe MergeRequestPresenter do
end
end
- describe "#unmergeable_reasons" do
- let(:presenter) { described_class.new(resource, current_user: user) }
-
- before do
- # Mergeable base state
- allow(resource).to receive(:has_no_commits?).and_return(false)
- allow(resource).to receive(:source_branch_exists?).and_return(true)
- allow(resource).to receive(:target_branch_exists?).and_return(true)
- allow(resource.project.repository).to receive(:can_be_merged?).and_return(true)
- end
-
- it "handles mergeable request" do
- expect(presenter.unmergeable_reasons).to eq([])
- end
-
- it "handles no commit" do
- allow(resource).to receive(:has_no_commits?).and_return(true)
-
- expect(presenter.unmergeable_reasons).to eq(["no commits"])
- end
-
- it "handles branches missing" do
- allow(resource).to receive(:source_branch_exists?).and_return(false)
- allow(resource).to receive(:target_branch_exists?).and_return(false)
-
- expect(presenter.unmergeable_reasons).to eq(["source branch is missing", "target branch is missing"])
- end
-
- it "handles merge conflict" do
- allow(resource.project.repository).to receive(:can_be_merged?).and_return(false)
-
- expect(presenter.unmergeable_reasons).to eq(["has merge conflicts"])
- end
- end
-
describe '#conflict_resolution_path' do
let(:project) { create :project }
let(:user) { create :user }
diff --git a/spec/views/devise/shared/_signin_box.html.haml_spec.rb b/spec/views/devise/shared/_signin_box.html.haml_spec.rb
index 0870b8f09f9..66c064e3fba 100644
--- a/spec/views/devise/shared/_signin_box.html.haml_spec.rb
+++ b/spec/views/devise/shared/_signin_box.html.haml_spec.rb
@@ -6,6 +6,7 @@ describe 'devise/shared/_signin_box' do
stub_devise
assign(:ldap_servers, [])
allow(view).to receive(:current_application_settings).and_return(Gitlab::CurrentSettings.current_application_settings)
+ allow(view).to receive(:captcha_enabled?).and_return(false)
end
it 'is shown when Crowd is enabled' do