summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-31 15:06:41 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-31 15:06:41 +0000
commit083d64c6468a070ae7b0b406ead8d87da27d1d22 (patch)
treeba92a9b5b6418f805ede9ef05b371d82d2c1d27d
parent0be510a49f6e4f8e27b19b707fd1dac61571f78f (diff)
downloadgitlab-ce-083d64c6468a070ae7b0b406ead8d87da27d1d22.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml5
-rw-r--r--app/controllers/concerns/metrics_dashboard.rb11
-rw-r--r--app/controllers/projects/environments_controller.rb3
-rw-r--r--app/controllers/projects/grafana_api_controller.rb11
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/helpers/tree_helper.rb4
-rw-r--r--app/models/releases/source.rb4
-rw-r--r--app/services/groups/transfer_service.rb4
-rw-r--r--app/services/projects/transfer_service.rb2
-rw-r--r--app/views/projects/buttons/_download_links.html.haml6
-rw-r--r--app/views/search/_results.html.haml1
-rw-r--r--changelogs/unreleased/sh-use-rails-redis-store.yml5
-rw-r--r--config/application.rb5
-rw-r--r--config/routes/project.rb7
-rw-r--r--doc/administration/gitaly/index.md2
-rw-r--r--doc/integration/elasticsearch.md9
-rw-r--r--doc/topics/autodevops/index.md246
-rw-r--r--doc/topics/autodevops/quick_start_guide.md2
-rw-r--r--doc/user/clusters/applications.md127
-rw-r--r--doc/user/packages/npm_registry/index.md3
-rw-r--r--doc/user/project/clusters/img/create_dns.pngbin23923 -> 0 bytes
-rw-r--r--doc/user/project/clusters/img/deploy_apps.pngbin82157 -> 0 bytes
-rw-r--r--doc/user/project/clusters/index.md145
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md2
-rw-r--r--doc/user/project/pages/getting_started/fork_sample_project.md61
-rw-r--r--doc/user/project/pages/getting_started/new_or_existing_website.md45
-rw-r--r--doc/user/project/pages/getting_started/pages_bundled_template.md29
-rw-r--r--doc/user/project/pages/getting_started_part_one.md51
-rw-r--r--doc/user/project/pages/getting_started_part_two.md171
-rw-r--r--doc/user/project/pages/index.md50
-rw-r--r--doc/user/project/pages/introduction.md35
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md4
-rw-r--r--doc/user/project/pages/pages_access_control.md48
-rw-r--r--lib/banzai/filter/inline_grafana_metrics_filter.rb78
-rw-r--r--lib/banzai/filter/inline_metrics_redactor_filter.rb89
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb1
-rw-r--r--lib/gitlab/metrics/dashboard/finder.rb3
-rw-r--r--lib/gitlab/metrics/dashboard/service_selector.rb5
-rw-r--r--lib/gitlab/metrics/dashboard/url.rb46
-rw-r--r--lib/gitlab/workhorse.rb1
-rw-r--r--locale/gitlab.pot12
-rw-r--r--qa/qa/runtime/fixtures.rb2
-rw-r--r--qa/qa/service/docker_run/maven.rb8
-rw-r--r--spec/controllers/concerns/metrics_dashboard_spec.rb13
-rw-r--r--spec/controllers/projects/grafana_api_controller_spec.rb83
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb1
-rw-r--r--spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb81
-rw-r--r--spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb48
-rw-r--r--spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb11
-rw-r--r--spec/lib/gitlab/metrics/dashboard/url_spec.rb85
-rw-r--r--spec/models/release_spec.rb4
-rw-r--r--spec/models/releases/source_spec.rb2
-rw-r--r--spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb7
55 files changed, 1054 insertions, 632 deletions
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 01ef38a7341..05e974ccfb5 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -94,10 +94,7 @@ schedule:review-build-cng:
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
- # v2.3.7 + some stability improvements not yet released:
- # - sidekiq readinessProbe should be `pgrep -f sidekiq`: https://gitlab.com/gitlab-org/charts/gitlab/merge_requests/991
- # - Allows livenessProbe and readinessProbe to be configured for unicorn: https://gitlab.com/gitlab-org/charts/gitlab/merge_requests/985
- GITLAB_HELM_CHART_REF: "df7c52dc69df441909880b8f2fd15e938cdb2047"
+ GITLAB_HELM_CHART_REF: "v2.4.4"
GITLAB_EDITION: "ce"
environment:
name: review/${CI_COMMIT_REF_NAME}
diff --git a/app/controllers/concerns/metrics_dashboard.rb b/app/controllers/concerns/metrics_dashboard.rb
index 62efdacb710..b06b5d5a30c 100644
--- a/app/controllers/concerns/metrics_dashboard.rb
+++ b/app/controllers/concerns/metrics_dashboard.rb
@@ -3,21 +3,24 @@
# Provides an action which fetches a metrics dashboard according
# to the parameters specified by the controller.
module MetricsDashboard
+ include RenderServiceResults
extend ActiveSupport::Concern
def metrics_dashboard
result = dashboard_finder.find(
project_for_dashboard,
current_user,
- metrics_dashboard_params
+ metrics_dashboard_params.to_h.symbolize_keys
)
- if include_all_dashboards?
+ if include_all_dashboards? && result
result[:all_dashboards] = dashboard_finder.find_all_paths(project_for_dashboard)
end
respond_to do |format|
- if result[:status] == :success
+ if result.nil?
+ format.json { continue_polling_response }
+ elsif result[:status] == :success
format.json { render dashboard_success_response(result) }
else
format.json { render dashboard_error_response(result) }
@@ -56,7 +59,7 @@ module MetricsDashboard
def dashboard_error_response(result)
{
- status: result[:http_status],
+ status: result[:http_status] || :bad_request,
json: result.slice(:all_dashboards, :message, :status)
}
end
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index c053ca19a94..5fd475f5499 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -199,8 +199,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
def metrics_dashboard_params
params
- .permit(:embedded, :group, :title, :y_label)
- .to_h.symbolize_keys
+ .permit(:embedded, :group, :title, :y_label, :dashboard_path, :environment)
.merge(dashboard_path: params[:dashboard], environment: environment)
end
diff --git a/app/controllers/projects/grafana_api_controller.rb b/app/controllers/projects/grafana_api_controller.rb
index 4bdf4c12cac..85f47b92e58 100644
--- a/app/controllers/projects/grafana_api_controller.rb
+++ b/app/controllers/projects/grafana_api_controller.rb
@@ -2,6 +2,9 @@
class Projects::GrafanaApiController < Projects::ApplicationController
include RenderServiceResults
+ include MetricsDashboard
+
+ before_action :validate_feature_enabled!, only: [:metrics_dashboard]
def proxy
result = ::Grafana::ProxyService.new(
@@ -19,6 +22,14 @@ class Projects::GrafanaApiController < Projects::ApplicationController
private
+ def metrics_dashboard_params
+ params.permit(:embedded, :grafana_url)
+ end
+
+ def validate_feature_enabled!
+ render_403 unless Feature.enabled?(:gfm_grafana_integration)
+ end
+
def query_params
params.permit(:query, :start, :end, :step)
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 099609c29ca..777fe82e4c0 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module SearchHelper
+ SEARCH_PERMITTED_PARAMS = [:search, :scope, :project_id, :group_id, :repository_ref, :snippets].freeze
+
def search_autocomplete_opts(term)
return unless current_user
@@ -200,7 +202,7 @@ module SearchHelper
search_params = params
.merge(search)
.merge({ scope: scope })
- .permit(:search, :scope, :project_id, :group_id, :repository_ref, :snippets)
+ .permit(SEARCH_PERMITTED_PARAMS)
if @scope == scope
li_class = 'active'
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 28adc7ccbdb..fc25b78da93 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -197,9 +197,7 @@ module TreeHelper
end
def directory_download_links(project, ref, archive_prefix)
- formats = ['zip', 'tar.gz', 'tar.bz2', 'tar']
-
- formats.map do |fmt|
+ Gitlab::Workhorse::ARCHIVE_FORMATS.map do |fmt|
{
text: fmt,
path: project_archive_path(project, id: tree_join(ref, archive_prefix), format: fmt)
diff --git a/app/models/releases/source.rb b/app/models/releases/source.rb
index 4d3d54457af..2f00d25d768 100644
--- a/app/models/releases/source.rb
+++ b/app/models/releases/source.rb
@@ -6,11 +6,9 @@ module Releases
attr_accessor :project, :tag_name, :format
- FORMATS = %w(zip tar.gz tar.bz2 tar).freeze
-
class << self
def all(project, tag_name)
- Releases::Source::FORMATS.map do |format|
+ Gitlab::Workhorse::ARCHIVE_FORMATS.map do |format|
Releases::Source.new(project: project,
tag_name: tag_name,
format: format)
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index 6902b7bd529..14f5a605633 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -13,7 +13,7 @@ module Groups
TransferError = Class.new(StandardError)
- attr_reader :error
+ attr_reader :error, :new_parent_group
def initialize(group, user, params = {})
super
@@ -115,3 +115,5 @@ module Groups
end
end
end
+
+Groups::TransferService.prepend_if_ee('EE::Groups::TransferService')
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index 525fc18b312..718416a03d4 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -13,6 +13,8 @@ module Projects
include Gitlab::ShellAdapter
TransferError = Class.new(StandardError)
+ attr_reader :new_namespace
+
def execute(new_namespace)
@new_namespace = new_namespace
diff --git a/app/views/projects/buttons/_download_links.html.haml b/app/views/projects/buttons/_download_links.html.haml
index b256d94065b..990f3ff526b 100644
--- a/app/views/projects/buttons/_download_links.html.haml
+++ b/app/views/projects/buttons/_download_links.html.haml
@@ -1,6 +1,4 @@
-- formats = [['zip', 'btn-primary'], ['tar.gz'], ['tar.bz2'], ['tar']]
-
.btn-group.ml-0.w-100
- - formats.each do |(fmt, extra_class)|
+ - Gitlab::Workhorse::ARCHIVE_FORMATS.each_with_index do |fmt, index|
- archive_path = project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt)
- = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "btn btn-xs #{extra_class}"
+ = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "btn btn-xs #{"btn-primary" if index == 0}"
diff --git a/app/views/search/_results.html.haml b/app/views/search/_results.html.haml
index de9947528cf..629a5a045b1 100644
--- a/app/views/search/_results.html.haml
+++ b/app/views/search/_results.html.haml
@@ -1,6 +1,7 @@
- if @search_objects.to_a.empty?
= render partial: "search/results/empty"
= render_if_exists 'shared/promotions/promote_advanced_search'
+ = render_if_exists 'search/form_revert_to_basic'
- else
.row-content-block.d-md-flex.text-left.align-items-center
- unless @search_objects.is_a?(Kaminari::PaginatableWithoutCount)
diff --git a/changelogs/unreleased/sh-use-rails-redis-store.yml b/changelogs/unreleased/sh-use-rails-redis-store.yml
new file mode 100644
index 00000000000..cf20c23b415
--- /dev/null
+++ b/changelogs/unreleased/sh-use-rails-redis-store.yml
@@ -0,0 +1,5 @@
+---
+title: Use Rails 5.2 Redis caching store
+merge_request: 19202
+author:
+type: other
diff --git a/config/application.rb b/config/application.rb
index 5d7c52c5d81..894e107e7da 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -247,7 +247,10 @@ module Gitlab
end
# Use caching across all environments
+ # Full list of options:
+ # https://api.rubyonrails.org/classes/ActiveSupport/Cache/RedisCacheStore.html#method-c-new
caching_config_hash = Gitlab::Redis::Cache.params
+ caching_config_hash[:compress] = false
caching_config_hash[:namespace] = Gitlab::Redis::Cache::CACHE_NAMESPACE
caching_config_hash[:expires_in] = 2.weeks # Cache should not grow forever
if Sidekiq.server? # threaded context
@@ -255,7 +258,7 @@ module Gitlab
caching_config_hash[:pool_timeout] = 1
end
- config.cache_store = :redis_store, caching_config_hash
+ config.cache_store = :redis_cache_store, caching_config_hash
config.active_job.queue_adapter = :sidekiq
diff --git a/config/routes/project.rb b/config/routes/project.rb
index ebd6b14be76..cc86e318dae 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -187,9 +187,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resource :import, only: [:new, :create, :show]
resource :avatar, only: [:show, :destroy]
- get 'grafana/proxy/:datasource_id/*proxy_path',
- to: 'grafana_api#proxy',
- as: :grafana_api
+ scope :grafana, as: :grafana_api do
+ get 'proxy/:datasource_id/*proxy_path', to: 'grafana_api#proxy'
+ get :metrics_dashboard, to: 'grafana_api#metrics_dashboard'
+ end
end
# End of the /-/ scope.
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 2d5de7e476c..1b41d862020 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -328,6 +328,8 @@ When you tail the Gitaly logs on your Gitaly server you should see requests
coming in. One sure way to trigger a Gitaly request is to clone a repository
from your GitLab server over HTTP.
+DANGER: **Danger:** If you have [custom server-side Git hooks](../custom_hooks.md#custom-server-side-git-hooks) configured, either per repository or globally, you must move these to the Gitaly node. If you have multiple Gitaly nodes, copy your custom hook(s) to all nodes.
+
### Disabling the Gitaly service in a cluster environment
If you are running Gitaly [as a remote
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index da53987ce1b..5c77bd5bcd9 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -583,3 +583,12 @@ Here are some common pitfalls and how to overcome them:
AWS has [fixed limits](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html)
for this setting ("Maximum Size of HTTP Request Payloads"), based on the size of
the underlying instance.
+
+### Reverting to basic search
+
+Sometimes there may be issues with your Elasticsearch index data and as such
+GitLab will allow you to revert to "basic search" when there are no search
+results and assuming that basic search is supported in that scope. This "basic
+search" will behave as though you don't have Elasticsearch enabled at all for
+your instance and search using other data sources (ie. Postgres data and Git
+data).
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 83bcb7950b5..88cd618a5c7 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -95,58 +95,85 @@ Auto DevOps.
To make full use of Auto DevOps, you will need:
+- **Kubernetes** (for Auto Review Apps, Auto Deploy, and Auto Monitoring)
+
+ To enable deployments, you will need:
+
+ 1. A [Kubernetes 1.5+ cluster](../../user/project/clusters/index.md) for the project. The easiest
+ way is to add a [new GKE cluster using the GitLab UI](../../user/project/clusters/add_remove_clusters.md#add-new-gke-cluster).
+ 1. NGINX Ingress. You can deploy it to your Kubernetes cluster by installing
+ the [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
+ once you have configured GitLab's Kubernetes integration in the previous step.
+
+ Alternatively, you can use the
+ [`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
+ Helm chart to install Ingress manually.
+
+ NOTE: **Note:**
+ If you are using your own Ingress instead of the one provided by GitLab's managed
+ apps, ensure you are running at least version 0.9.0 of NGINX Ingress and
+ [enable Prometheus metrics](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/customization/custom-vts-metrics-prometheus/nginx-vts-metrics-conf.yaml)
+ in order for the response metrics to appear. You will also have to
+ [annotate](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
+ the NGINX Ingress deployment to be scraped by Prometheus using
+ `prometheus.io/scrape: "true"` and `prometheus.io/port: "10254"`.
+
+- **Base domain** (for Auto Review Apps, Auto Deploy, and Auto Monitoring)
+
+ You will need a domain configured with wildcard DNS which is going to be used
+ by all of your Auto DevOps applications. If you're using the
+ [GitLab-managed app for Ingress](../../user/clusters/applications.md#ingress),
+ the URL endpoint will be automatically configured for you.
+
+ You will then need to [specify the Auto DevOps base domain](#auto-devops-base-domain).
+
- **GitLab Runner** (for all stages)
Your Runner needs to be configured to be able to run Docker. Generally this
means using either the [Docker](https://docs.gitlab.com/runner/executors/docker.html)
or [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html) executors, with
[privileged mode enabled](https://docs.gitlab.com/runner/executors/docker.html#use-docker-in-docker-with-privileged-mode).
-
The Runners do not need to be installed in the Kubernetes cluster, but the
Kubernetes executor is easy to use and is automatically autoscaling.
Docker-based Runners can be configured to autoscale as well, using [Docker
Machine](https://docs.gitlab.com/runner/install/autoscaling.html).
+ If you have configured GitLab's Kubernetes integration in the first step, you
+ can deploy it to your cluster by installing the
+ [GitLab-managed app for GitLab Runner](../../user/clusters/applications.md#gitlab-runner).
+
Runners should be registered as [shared Runners](../../ci/runners/README.md#registering-a-shared-runner)
for the entire GitLab instance, or [specific Runners](../../ci/runners/README.md#registering-a-specific-runner)
- that are assigned to specific projects.
-- **Base domain** (for Auto Review Apps and Auto Deploy)
-
- You will need a domain configured with wildcard DNS which is going to be used
- by all of your Auto DevOps applications.
+ that are assigned to specific projects (the default if you have installed the
+ GitLab Runner managed application).
- Read the [specifics](#auto-devops-base-domain).
-- **Kubernetes** (for Auto Review Apps, Auto Deploy, and Auto Monitoring)
-
- To enable deployments, you will need:
-
- - Kubernetes 1.5+.
- - A [Kubernetes cluster][kubernetes-clusters] for the project.
- - A load balancer. You can use NGINX Ingress by deploying it to your
- Kubernetes cluster by either:
- - Using the [`nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress) Helm chart.
- - Installing the Ingress [GitLab Managed App](../../user/clusters/applications.md#ingress).
- **Prometheus** (for Auto Monitoring)
- To enable Auto Monitoring, you
- will need Prometheus installed somewhere (inside or outside your cluster) and
- configured to scrape your Kubernetes cluster. To get response metrics
- (in addition to system metrics), you need to
- [configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
+ To enable Auto Monitoring, you will need Prometheus installed somewhere
+ (inside or outside your cluster) and configured to scrape your Kubernetes cluster.
+ If you have configured GitLab's Kubernetes integration, you can deploy it to
+ your cluster by installing the
+ [GitLab-managed app for Prometheus](../../user/clusters/applications.md#prometheus).
The [Prometheus service](../../user/project/integrations/prometheus.md)
- integration needs to be enabled for the project, or enabled as a
+ integration needs to be enabled for the project (or enabled as a
[default service template](../../user/project/integrations/services_templates.md)
- for the entire GitLab installation.
+ for the entire GitLab installation).
+
+ To get response metrics (in addition to system metrics), you need to
+ [configure Prometheus to monitor NGINX](../../user/project/integrations/prometheus_library/nginx_ingress.md#configuring-nginx-ingress-monitoring).
If you do not have Kubernetes or Prometheus installed, then Auto Review Apps,
Auto Deploy, and Auto Monitoring will be silently skipped.
+One all requirements are met, you can go ahead and [enable Auto DevOps](#enablingdisabling-auto-devops).
+
## Auto DevOps base domain
-The Auto DevOps base domain is required if you want to make use of [Auto
-Review Apps](#auto-review-apps) and [Auto Deploy](#auto-deploy). It can be defined
-in any of the following places:
+The Auto DevOps base domain is required if you want to make use of
+[Auto Review Apps](#auto-review-apps), [Auto Deploy](#auto-deploy), and
+[Auto Monitoring](#auto-monitoring). It can be defined in any of the following
+places:
- either under the cluster's settings, whether for [projects](../../user/project/clusters/index.md#base-domain) or [groups](../../user/group/clusters/index.md#base-domain)
- or in instance-wide settings in the **admin area > Settings** under the "Continuous Integration and Delivery" section
@@ -156,9 +183,15 @@ in any of the following places:
The base domain variable `KUBE_INGRESS_BASE_DOMAIN` follows the same order of precedence
as other environment [variables](../../ci/variables/README.md#priority-of-environment-variables).
-NOTE: **Note**
-`AUTO_DEVOPS_DOMAIN` environment variable is deprecated and
-[is scheduled to be removed](https://gitlab.com/gitlab-org/gitlab-foss/issues/56959).
+TIP: **Tip:**
+If you're using the [GitLab managed app for Ingress](../../user/clusters/applications.md#ingress),
+the URL endpoint should be automatically configured for you. All you have to do
+is use its value for the `KUBE_INGRESS_BASE_DOMAIN` variable.
+
+NOTE: **Note:**
+`AUTO_DEVOPS_DOMAIN` was [deprecated in GitLab 11.8](https://gitlab.com/gitlab-org/gitlab-foss/issues/52363)
+and replaced with `KUBE_INGRESS_BASE_DOMAIN`. It was removed in
+[GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-foss/issues/56959).
A wildcard DNS A record matching the base domain(s) is required, for example,
given a base domain of `example.com`, you'd need a DNS entry like:
@@ -179,77 +212,28 @@ 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).
-NOTE: **Note:**
-From GitLab 11.8, `KUBE_INGRESS_BASE_DOMAIN` replaces `AUTO_DEVOPS_DOMAIN`.
-Support for `AUTO_DEVOPS_DOMAIN` was [removed in GitLab
-12.0](https://gitlab.com/gitlab-org/gitlab-foss/issues/56959).
-
-## Using multiple Kubernetes clusters **(PREMIUM)**
-
-When using Auto DevOps, you may want to deploy different environments to
-different Kubernetes clusters. This is possible due to the 1:1 connection that
-[exists between them](../../user/project/clusters/index.md#multiple-kubernetes-clusters-premium).
-
-In the [Auto DevOps template] (used behind the scenes by Auto DevOps), there
-are currently 3 defined environment names that you need to know:
-
-- `review/` (every environment starting with `review/`)
-- `staging`
-- `production`
-
-Those environments are tied to jobs that use [Auto Deploy](#auto-deploy), so
-except for the environment scope, they would also need to have a different
-domain they would be deployed to. This is why you need to define a separate
-`KUBE_INGRESS_BASE_DOMAIN` variable for all the above
-[based on the environment](../../ci/variables/README.md#limiting-environment-scopes-of-environment-variables).
-
-The following table is an example of how the three different clusters would
-be configured.
-
-| Cluster name | Cluster environment scope | `KUBE_INGRESS_BASE_DOMAIN` variable value | Variable environment scope | Notes |
-|--------------|---------------------------|-------------------------------------------|----------------------------|---|
-| review | `review/*` | `review.example.com` | `review/*` | The review cluster which will run all [Review Apps](../../ci/review_apps/index.md). `*` is a wildcard, which means it will be used by every environment name starting with `review/`. |
-| staging | `staging` | `staging.example.com` | `staging` | (Optional) The staging cluster which will run the deployments of the staging environments. You need to [enable it first](#deploy-policy-for-staging-and-production-environments). |
-| production | `production` | `example.com` | `production` | The production cluster which will run the deployments of the production environment. You can use [incremental rollouts](#incremental-rollout-to-production-premium). |
-
-To add a different cluster for each environment:
-
-1. Navigate to your project's **Operations > Kubernetes** and create the Kubernetes clusters
- with their respective environment scope as described from the table above.
-
- ![Auto DevOps multiple clusters](img/autodevops_multiple_clusters.png)
-
-1. After the clusters are created, navigate to each one and install Helm Tiller
- and Ingress. Wait for the Ingress IP address to be assigned.
-1. Make sure you have [configured your DNS](#auto-devops-base-domain) with the
- specified Auto DevOps domains.
-1. Navigate to each cluster's page, through **Operations > Kubernetes**,
- and add the domain based on its Ingress IP address.
-
-Now that all is configured, you can test your setup by creating a merge request
-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.
-
## Enabling/Disabling Auto DevOps
-When first using Auto Devops, review the [requirements](#requirements) to ensure all necessary components to make
+When first using Auto DevOps, review the [requirements](#requirements) to ensure all necessary components to make
full use of Auto DevOps are available. If this is your fist time, we recommend you follow the
[quick start guide](quick_start_guide.md).
GitLab.com users can enable/disable Auto DevOps at the project-level only. Self-managed users
can enable/disable Auto DevOps at the project-level, group-level or instance-level.
-### At the instance level (Administrators only)
+### At the project level
-Even when disabled at the instance level, group owners and project maintainers can still enable
-Auto DevOps at the group and project level, respectively.
+If enabling, check that your project doesn't have a `.gitlab-ci.yml`, or if one exists, remove it.
-1. Go to **Admin area > Settings > Continuous Integration and Deployment**.
-1. Toggle the checkbox labeled **Default to Auto DevOps pipeline for all projects**.
-1. If enabling, optionally set up the Auto DevOps [base domain](#auto-devops-base-domain) which will be used for Auto Deploy and Auto Review Apps.
+1. Go to your project's **Settings > CI/CD > Auto DevOps**.
+1. Toggle the **Default to Auto DevOps pipeline** checkbox (checked to enable, unchecked to disable)
+1. When enabling, it's optional but recommended to add in the [base domain](#auto-devops-base-domain)
+ that will be used by Auto DevOps to [deploy your application](#auto-deploy)
+ and choose the [deployment strategy](#deployment-strategy).
1. Click **Save changes** for the changes to take effect.
+When the feature has been enabled, an Auto DevOps pipeline is triggered on the default branch.
+
### At the group level
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/52447) in GitLab 11.10.
@@ -266,19 +250,16 @@ When enabling or disabling Auto DevOps at group-level, group configuration will
the subgroups and projects inside that group, unless Auto DevOps is specifically enabled or disabled on
the subgroup or project.
-### At the project level
+### At the instance level (Administrators only)
-If enabling, check that your project doesn't have a `.gitlab-ci.yml`, or if one exists, remove it.
+Even when disabled at the instance level, group owners and project maintainers can still enable
+Auto DevOps at the group and project level, respectively.
-1. Go to your project's **Settings > CI/CD > Auto DevOps**.
-1. Toggle the **Default to Auto DevOps pipeline** checkbox (checked to enable, unchecked to disable)
-1. When enabling, it's optional but recommended to add in the [base domain](#auto-devops-base-domain)
- that will be used by Auto DevOps to [deploy your application](#auto-deploy)
- and choose the [deployment strategy](#deployment-strategy).
+1. Go to **Admin area > Settings > Continuous Integration and Deployment**.
+1. Toggle the checkbox labeled **Default to Auto DevOps pipeline for all projects**.
+1. If enabling, optionally set up the Auto DevOps [base domain](#auto-devops-base-domain) which will be used for Auto Deploy and Auto Review Apps.
1. Click **Save changes** for the changes to take effect.
-When the feature has been enabled, an Auto DevOps pipeline is triggered on the default branch.
-
### Enable for a percentage of projects
There is also a feature flag to enable Auto DevOps by default to your chosen percentage of projects.
@@ -310,6 +291,53 @@ The available options are:
- `master` branch is directly deployed to staging.
- Manual actions are provided for incremental rollout to production.
+## Using multiple Kubernetes clusters **(PREMIUM)**
+
+When using Auto DevOps, you may want to deploy different environments to
+different Kubernetes clusters. This is possible due to the 1:1 connection that
+[exists between them](../../user/project/clusters/index.md#multiple-kubernetes-clusters-premium).
+
+In the [Auto DevOps template] (used behind the scenes by Auto DevOps), there
+are currently 3 defined environment names that you need to know:
+
+- `review/` (every environment starting with `review/`)
+- `staging`
+- `production`
+
+Those environments are tied to jobs that use [Auto Deploy](#auto-deploy), so
+except for the environment scope, they would also need to have a different
+domain they would be deployed to. This is why you need to define a separate
+`KUBE_INGRESS_BASE_DOMAIN` variable for all the above
+[based on the environment](../../ci/variables/README.md#limiting-environment-scopes-of-environment-variables).
+
+The following table is an example of how the three different clusters would
+be configured.
+
+| Cluster name | Cluster environment scope | `KUBE_INGRESS_BASE_DOMAIN` variable value | Variable environment scope | Notes |
+|--------------|---------------------------|-------------------------------------------|----------------------------|---|
+| review | `review/*` | `review.example.com` | `review/*` | The review cluster which will run all [Review Apps](../../ci/review_apps/index.md). `*` is a wildcard, which means it will be used by every environment name starting with `review/`. |
+| staging | `staging` | `staging.example.com` | `staging` | (Optional) The staging cluster which will run the deployments of the staging environments. You need to [enable it first](#deploy-policy-for-staging-and-production-environments). |
+| production | `production` | `example.com` | `production` | The production cluster which will run the deployments of the production environment. You can use [incremental rollouts](#incremental-rollout-to-production-premium). |
+
+To add a different cluster for each environment:
+
+1. Navigate to your project's **Operations > Kubernetes** and create the Kubernetes clusters
+ with their respective environment scope as described from the table above.
+
+ ![Auto DevOps multiple clusters](img/autodevops_multiple_clusters.png)
+
+1. After the clusters are created, navigate to each one and install Helm Tiller
+ and Ingress. Wait for the Ingress IP address to be assigned.
+1. Make sure you have [configured your DNS](#auto-devops-base-domain) with the
+ specified Auto DevOps domains.
+1. Navigate to each cluster's page, through **Operations > Kubernetes**,
+ and add the domain based on its Ingress IP address.
+
+Now that all is configured, you can test your setup by creating a merge request
+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.
+
## Stages of Auto DevOps
The following sections describe the stages of Auto DevOps. Read them carefully
@@ -672,8 +700,6 @@ workers:
### Auto Monitoring
-See the [requirements](#requirements) for Auto Monitoring to enable this stage.
-
Once your application is deployed, Auto Monitoring makes it possible to monitor
your application's server and response metrics right out of the box. Auto
Monitoring uses [Prometheus](../../user/project/integrations/prometheus.md) to
@@ -687,18 +713,15 @@ The metrics include:
- **Response Metrics:** latency, throughput, error rate
- **System Metrics:** CPU utilization, memory utilization
-In order to make use of monitoring you need to:
-
-1. [Deploy Prometheus](../../user/project/integrations/prometheus.md) into your Kubernetes cluster
-1. If you would like response metrics, ensure you are running at least version
- 0.9.0 of NGINX Ingress and
- [enable Prometheus metrics](https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/customization/custom-vts-metrics-prometheus/nginx-vts-metrics-conf.yaml).
-1. Finally, [annotate](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
- the NGINX Ingress deployment to be scraped by Prometheus using
- `prometheus.io/scrape: "true"` and `prometheus.io/port: "10254"`.
+To make use of Auto Monitoring:
-To view the metrics, open the
-[Monitoring dashboard for a deployed environment](../../ci/environments.md#monitoring-environments).
+1. [Install and configure the requirements](#requirements).
+1. [Enable Auto DevOps](#enablingdisabling-auto-devops) if you haven't done already.
+1. Finally, go to your project's **CI/CD > Pipelines** and run a pipeline.
+1. Once the pipeline finishes successfully, open the
+ [monitoring dashboard for a deployed environment](../../ci/environments.md#monitoring-environments)
+ to view the metrics of your deployed application. To view the metrics of the
+ whole Kubernetes cluster, navigate to **Operations > Metrics**.
![Auto Metrics](img/auto_monitoring.png)
@@ -1303,7 +1326,6 @@ curl --data "value=true" --header "PRIVATE-TOKEN: personal_access_token" https:/
```
[ce-37115]: https://gitlab.com/gitlab-org/gitlab-foss/issues/37115
-[kubernetes-clusters]: ../../user/project/clusters/index.md
[docker-in-docker]: ../../docker/using_docker_build.md#use-docker-in-docker-executor
[review-app]: ../../ci/review_apps/index.md
[container-registry]: ../../user/packages/container_registry/index.md
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 2d3576f6022..8ec3d5fe36e 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -280,6 +280,6 @@ and customized to fit your workflow. Here are some helpful resources for further
1. [Multiple Kubernetes clusters](index.md#using-multiple-kubernetes-clusters-premium) **(PREMIUM)**
1. [Incremental rollout to production](index.md#incremental-rollout-to-production-premium) **(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 a static IP for your cluster](../../user/clusters/applications.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/user/clusters/applications.md b/doc/user/clusters/applications.md
index f2dd4319f88..105843fd678 100644
--- a/doc/user/clusters/applications.md
+++ b/doc/user/clusters/applications.md
@@ -107,10 +107,20 @@ To resolve this:
project that is used to run your jobs and send the results back to
GitLab. It is used in conjunction with [GitLab
CI/CD](../../ci/README.md), 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](../project/clusters/index.md#security-implications) before doing so.
+service included with GitLab that coordinates the jobs.
+
+If the project is on GitLab.com, shared Runners are available
+(the first 2000 minutes are free, you can
+[buy more later](../../subscriptions/index.md#extra-shared-runners-pipeline-minutes))
+and you do not have to deploy one if they are enough for your needs. If a
+project-specific Runner is desired, or there are no shared Runners, it is easy
+to deploy one.
+
+Note that the deployed Runner will be set as **privileged**, which means it will essentially
+have root access to the underlying machine. This is required to build Docker images,
+so it is the default. Make sure you read the
+[security implications](../project/clusters/index.md#security-implications)
+before deploying one.
NOTE: **Note:**
The [`runner/gitlab-runner`](https://gitlab.com/gitlab-org/charts/gitlab-runner)
@@ -129,11 +139,112 @@ web proxy for your applications and is useful if you want to use [Auto
DevOps](../../topics/autodevops/index.md) or deploy your own web apps.
NOTE: **Note:**
+With the following procedure, a load balancer must be installed in your cluster
+to obtain the endpoint. You can use either
+Ingress, or Knative's own load balancer ([Istio](https://istio.io)) if using Knative.
+
+In order to publish your web application, you first need to find the endpoint which will be either an IP
+address or a hostname associated with your load balancer.
+
+To install it, click on the **Install** button for Ingress. GitLab will attempt
+to determine the external endpoint and it should be available within a few minutes.
+
+#### Determining the external endpoint automatically
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/17052) in GitLab 10.6.
+
+After you install Ingress, the external endpoint should be available within a few minutes.
+
+TIP: **Tip:**
+This endpoint can be used for the
+[Auto DevOps base domain](../../topics/autodevops/index.md#auto-devops-base-domain)
+using the `KUBE_INGRESS_BASE_DOMAIN` environment variable.
+
+If the endpoint doesn't appear and your cluster runs on Google Kubernetes Engine:
+
+1. Check your [Kubernetes cluster on Google Kubernetes Engine](https://console.cloud.google.com/kubernetes) to ensure there are no errors on its nodes.
+1. Ensure you have enough [Quotas](https://console.cloud.google.com/iam-admin/quotas) on Google Kubernetes Engine. For more information, see [Resource Quotas](https://cloud.google.com/compute/quotas).
+1. Check [Google Cloud's Status](https://status.cloud.google.com/) to ensure they are not having any disruptions.
+
+Once installed, you may see a `?` for "Ingress IP Address" depending on the
+cloud provider. For EKS specifically, this is because the ELB is created
+with a DNS name, not an IP address. If GitLab is still unable to
+determine the endpoint of your Ingress or Knative application, you can
+[determine it manually](#determining-the-external-endpoint-manually).
+
+NOTE: **Note:**
The [`stable/nginx-ingress`](https://github.com/helm/charts/tree/master/stable/nginx-ingress)
chart is used to install this application with a
[`values.yaml`](https://gitlab.com/gitlab-org/gitlab/blob/master/vendor/ingress/values.yaml)
file.
+#### Determining the external endpoint manually
+
+If the cluster is on GKE, click the **Google Kubernetes Engine** link in the
+**Advanced settings**, or go directly to the
+[Google Kubernetes Engine dashboard](https://console.cloud.google.com/kubernetes/)
+and select the proper project and cluster. Then click **Connect** and execute
+the `gcloud` command in a local terminal or using the **Cloud Shell**.
+
+If the cluster is not on GKE, follow the specific instructions for your
+Kubernetes provider to configure `kubectl` with the right credentials.
+The output of the following examples will show the external endpoint of your
+cluster. This information can then be used to set up DNS entries and forwarding
+rules that allow external access to your deployed applications.
+
+If you installed Ingress via the **Applications**, run the following command:
+
+```bash
+kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
+```
+
+Some Kubernetes clusters return a hostname instead, like [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
+
+```bash
+kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
+```
+
+For Istio/Knative, the command will be different:
+
+```bash
+kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
+```
+
+Otherwise, you can list the IP addresses of all load balancers:
+
+```bash
+kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
+```
+
+NOTE: **Note:**
+If EKS is used, an [Elastic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/)
+will also be created, which will incur additional AWS costs.
+
+NOTE: **Note:**
+You may see a trailing `%` on some Kubernetes versions, **do not include it**.
+
+The Ingress is now available at this address and will route incoming requests to
+the proper service based on the DNS name in the request. To support this, a
+wildcard DNS CNAME record should be created for the desired domain name. For example,
+`*.myekscluster.com` would point to the Ingress hostname obtained earlier.
+
+#### Using a static IP
+
+By default, an ephemeral external IP address is associated to the cluster's load
+balancer. If you associate the ephemeral IP with your DNS and the IP changes,
+your apps will not be able to be reached, and you'd have to change the DNS
+record again. In order to avoid that, you should change it into a static
+reserved IP.
+
+Read how to [promote an ephemeral external IP address in GKE](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip).
+
+#### Pointing your DNS at the external endpoint
+
+Once you've set up the external endpoint, you should associate it with a [wildcard DNS
+record](https://en.wikipedia.org/wiki/Wildcard_DNS_record) such as `*.example.com.`
+in order to be able to reach your apps. If your external endpoint is an IP address,
+use an A record. If your external endpoint is a hostname, use a CNAME record.
+
#### Web Application Firewall (ModSecurity)
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/65192) in GitLab 12.3 (enabled using `ingress_modsecurity` [feature flag](../../development/feature_flags/development.md#enabling-a-feature-flag-in-development)).
@@ -259,6 +370,14 @@ chart is used to install this application.
open-source monitoring and alerting system useful to supervise your
deployed applications.
+GitLab is able to monitor applications automatically, using the
+[Prometheus integration](../project/integrations/prometheus.md). Kubernetes container CPU and
+memory metrics are automatically collected, and response metrics are retrieved
+from NGINX Ingress as well.
+
+To enable monitoring, simply install Prometheus into the cluster with the
+**Install** button.
+
NOTE: **Note:**
The [`stable/prometheus`](https://github.com/helm/charts/tree/master/stable/prometheus)
chart is used to install this application with a
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index 5f5d86ab17e..357b7a30591 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -42,6 +42,9 @@ it is not possible due to a naming collision. For example:
| `gitlab-org/gitlab` | `@gitlab-org/gitlab` | Yes |
| `gitlab-org/gitlab` | `@foo/bar` | No |
+CAUTION: **When updating the path of a user/group or transferring a (sub)group/project:**
+If you update the root namespace of a project with NPM packages, your changes will be rejected. To be allowed to do that, make sure to remove any NPM package first. Don't forget to update your `.npmrc` files to follow the above naming convention and run `npm publish` if necessary.
+
Now, you can configure your project to authenticate with the GitLab NPM
Registry.
diff --git a/doc/user/project/clusters/img/create_dns.png b/doc/user/project/clusters/img/create_dns.png
deleted file mode 100644
index 61ed85e5cd9..00000000000
--- a/doc/user/project/clusters/img/create_dns.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/clusters/img/deploy_apps.png b/doc/user/project/clusters/img/deploy_apps.png
deleted file mode 100644
index 0d9fcc838d9..00000000000
--- a/doc/user/project/clusters/img/deploy_apps.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index fc946fc785c..1867b9c0198 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -218,149 +218,12 @@ differentiate the new cluster with the rest.
## Installing applications
-GitLab can install and manage some applications in your project-level
-cluster. For more information on installing, upgrading, uninstalling,
-and troubleshooting applications for your project cluster, see
+GitLab can install and manage some applications like Helm, GitLab Runner, Ingress,
+Prometheus, etc., in your project-level cluster. For more information on
+installing, upgrading, uninstalling, and troubleshooting applications for
+your project cluster, see
[GitLab Managed Apps](../../clusters/applications.md).
-### Getting the external endpoint
-
-NOTE: **Note:**
-With the following procedure, a load balancer must be installed in your cluster
-to obtain the endpoint. You can use either
-[Ingress](#installing-applications), or Knative's own load balancer
-([Istio](https://istio.io)) if using [Knative](#installing-applications).
-
-In order to publish your web application, you first need to find the endpoint which will be either an IP
-address or a hostname associated with your load balancer.
-
-#### Automatically determining the external endpoint
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/17052) in GitLab 10.6.
-
-After you install [Ingress or Knative](#installing-applications), GitLab attempts to determine the external endpoint
-and it should be available within a few minutes. If the endpoint doesn't appear
-and your cluster runs on Google Kubernetes Engine:
-
-1. Check your [Kubernetes cluster on Google Kubernetes Engine](https://console.cloud.google.com/kubernetes) to ensure there are no errors on its nodes.
-1. Ensure you have enough [Quotas](https://console.cloud.google.com/iam-admin/quotas) on Google Kubernetes Engine. For more information, see [Resource Quotas](https://cloud.google.com/compute/quotas).
-1. Check [Google Cloud's Status](https://status.cloud.google.com/) to ensure they are not having any disruptions.
-
-If GitLab is still unable to determine the endpoint of your Ingress or Knative application, you can
-manually determine it by following the steps below.
-
-#### Manually determining the external endpoint
-
-If the cluster is on GKE, click the **Google Kubernetes Engine** link in the
-**Advanced settings**, or go directly to the
-[Google Kubernetes Engine dashboard](https://console.cloud.google.com/kubernetes/)
-and select the proper project and cluster. Then click **Connect** and execute
-the `gcloud` command in a local terminal or using the **Cloud Shell**.
-
-If the cluster is not on GKE, follow the specific instructions for your
-Kubernetes provider to configure `kubectl` with the right credentials.
-The output of the following examples will show the external endpoint of your
-cluster. This information can then be used to set up DNS entries and forwarding
-rules that allow external access to your deployed applications.
-
-If you installed the Ingress [via the **Applications**](#installing-applications),
-run the following command:
-
-```bash
-kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
-```
-
-Some Kubernetes clusters return a hostname instead, like [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
-
-```bash
-kubectl get service --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
-```
-
-For Istio/Knative, the command will be different:
-
-```bash
-kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
-```
-
-Otherwise, you can list the IP addresses of all load balancers:
-
-```bash
-kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
-```
-
-#### Using a static IP
-
-By default, an ephemeral external IP address is associated to the cluster's load
-balancer. If you associate the ephemeral IP with your DNS and the IP changes,
-your apps will not be able to be reached, and you'd have to change the DNS
-record again. In order to avoid that, you should change it into a static
-reserved IP.
-
-Read how to [promote an ephemeral external IP address in GKE](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip).
-
-#### Pointing your DNS at the external endpoint
-
-Once you've set up the external endpoint, you should associate it with a [wildcard DNS
-record](https://en.wikipedia.org/wiki/Wildcard_DNS_record) such as `*.example.com.`
-in order to be able to reach your apps. If your external endpoint is an IP address,
-use an A record. If your external endpoint is a hostname, use a CNAME record.
-
-#### Deploy services to the cluster
-
-GitLab supports one-click deployment of helpful services to the cluster, many of
-which support Auto DevOps. Back on the Kubernetes cluster screen in GitLab, a
-list of applications is now available to deploy.
-
-First, install Helm Tiller, a package manager for Kubernetes. This enables
-deployment of the other applications.
-
-![Deploy Apps](img/deploy_apps.png)
-
-##### Deploying NGINX Ingress (optional)
-
-Next, if you would like the deployed app to be reachable on the internet, deploy
-the Ingress. Note that this will also cause an
-[Elastic Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/)
-to be created, which will incur additional AWS costs.
-
-Once installed, you may see a `?` for "Ingress IP Address". This is because the
-created ELB is available at a DNS name, not an IP address. To get the DNS name,
-run:
-
-```sh
-kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}"
-```
-
-Note that you may see a trailing `%` on some Kubernetes versions, **do not include it**.
-
-The Ingress is now available at this address and will route incoming requests to
-the proper service based on the DNS name in the request. To support this, a
-wildcard DNS CNAME record should be created for the desired domain name. For example,
-`*.myekscluster.com` would point to the Ingress hostname obtained earlier.
-
-![Create DNS](img/create_dns.png)
-
-##### Deploying the GitLab Runner (optional)
-
-If the project is on GitLab.com, free shared Runners are available and you do
-not have to deploy one. If a project specific Runner is desired, or there are no
-shared Runners, it is easy to deploy one.
-
-Simply click on the **Install** button for the GitLab Runner. It is important to
-note that the Runner deployed is set as **privileged**, which means it essentially
-has root access to the underlying machine. This is required to build docker images,
-and so is on by default.
-
-##### Deploying Prometheus (optional)
-
-GitLab is able to monitor applications automatically, utilizing
-[Prometheus](../integrations/prometheus.html). Kubernetes container CPU and
-memory metrics are automatically collected, and response metrics are retrieved
-from NGINX Ingress as well.
-
-To enable monitoring, simply install Prometheus into the cluster with the
-**Install** button.
-
## Deploying to a Kubernetes cluster
A Kubernetes cluster can be the destination for a deployment job. If
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index e114e8b3ebc..be6371bb1ca 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -77,7 +77,7 @@ The minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.
![install-knative](img/install-knative.png)
1. After the Knative installation has finished, you can wait for the IP address or hostname to be displayed in the
- **Knative Endpoint** field or [retrieve the Istio Ingress Endpoint manually](../#manually-determining-the-external-endpoint).
+ **Knative Endpoint** field or [retrieve the Istio Ingress Endpoint manually](../../../clusters/applications.md#determining-the-external-endpoint-manually).
NOTE: **Note:**
Running `kubectl` commands on your cluster requires setting up access to the cluster first.
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index d630956c109..93f6dbb0302 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -30,7 +30,7 @@ For other deployments, there is [some configuration](#manually-setting-up-nginx-
### About managed NGINX Ingress deployments
-NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's Endpoint](../../clusters/index.md#getting-the-external-endpoint).
+NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's Endpoint](../../../clusters/applications.md#ingress).
NGINX is configured for Prometheus monitoring, by setting:
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
index 83eac44666c..a1dcb105196 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -30,7 +30,7 @@ For other deployments, there is [some configuration](#manually-setting-up-nginx-
### About managed NGINX Ingress deployments
-NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's Endpoint](../../clusters/index.md#getting-the-external-endpoint).
+NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's Endpoint](../../../clusters/applications.md#ingress).
NGINX is configured for Prometheus monitoring, by setting:
diff --git a/doc/user/project/pages/getting_started/fork_sample_project.md b/doc/user/project/pages/getting_started/fork_sample_project.md
new file mode 100644
index 00000000000..ac1a29ca2a0
--- /dev/null
+++ b/doc/user/project/pages/getting_started/fork_sample_project.md
@@ -0,0 +1,61 @@
+---
+type: reference, howto
+---
+
+# New Pages website from a forked sample
+
+To get started with GitLab Pages from a sample website, the easiest
+way to do it is by using one of the [bundled templates](pages_bundled_template.md).
+If you don't find one that suits your needs, you can opt by
+forking (copying) a [sample project from the most popular Static Site Generators](https://gitlab.com/pages).
+
+<table class="borderless-table center fixed-table middle width-80">
+ <tr>
+ <td style="width: 30%"><img src="../img/icons/fork.png" alt="Fork" class="image-noshadow half-width"></td>
+ <td style="width: 10%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 30%"><img src="../img/icons/terminal.png" alt="Deploy" class="image-noshadow half-width"></td>
+ <td style="width: 10%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 30%"><img src="../img/icons/click.png" alt="Visit" class="image-noshadow half-width"></td>
+ </tr>
+ <tr>
+ <td><em>Fork an example project</em></td>
+ <td></td>
+ <td><em>Deploy your website</em></td>
+ <td></td>
+ <td><em>Visit your website's URL</em></td>
+ </tr>
+</table>
+
+**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a [video tutorial](https://www.youtube.com/watch?v=TWqh9MtT4Bg) with all the steps below.**
+
+1. [Fork](../../../../gitlab-basics/fork-project.md) a sample project from the [GitLab Pages examples](https://gitlab.com/pages) group.
+1. From the left sidebar, navigate to your project's **CI/CD > Pipelines**
+ and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
+ site to the server.
+1. Once the pipeline has finished successfully, find the link to visit your
+ website from your project's **Settings > Pages**. It can take aproximatelly
+ 30 minutes to be deployed.
+
+You can also take some **optional** further steps:
+
+- _Remove the fork relationship._ The fork relationship is necessary to contribute back to the project you originally forked from. If you don't have any intentions to do so, you can remove it. To do so, navigate to your project's **Settings**, expand **Advanced settings**, and scroll down to **Remove fork relationship**:
+
+ ![remove fork relationship](../img/remove_fork_relationship.png)
+
+- _Make it a user or group website._ To turn a **project website** forked
+ from the Pages group into a **user/group** website, you'll need to:
+ - Rename it to `namespace.gitlab.io`: go to your project's
+ **Settings > General** and expand **Advanced**. Scroll down to
+ **Rename repository** and change the path to `namespace.gitlab.io`.
+ - Adjust your SSG's [base URL](../getting_started_part_one.md#urls-and-baseurls) from `"project-name"` to
+ `""`. This setting will be at a different place for each SSG, as each of them
+ have their own structure and file tree. Most likely, it will be in the SSG's
+ config file.
diff --git a/doc/user/project/pages/getting_started/new_or_existing_website.md b/doc/user/project/pages/getting_started/new_or_existing_website.md
new file mode 100644
index 00000000000..188b76e4224
--- /dev/null
+++ b/doc/user/project/pages/getting_started/new_or_existing_website.md
@@ -0,0 +1,45 @@
+---
+type: reference, howto
+---
+
+# Start a new Pages website from scratch or deploy an exising website
+
+If you already have a website and want to deploy it with GitLab Pages,
+or, if you want to start a new site from scratch, you'll need to:
+
+- Create a new project in GitLab to hold your site content.
+- Set up GitLab CI/CD to deploy your website to Pages.
+
+To do so, follow the steps below.
+
+1. From your **Project**'s **[Dashboard](https://gitlab.com/dashboard/projects)**,
+ click **New project**, and name it according to the
+ [Pages domain names](../getting_started_part_one.md#gitlab-pages-domain-names).
+1. Clone it to your local computer, add your website
+ files to your project, add, commit and push to GitLab.
+ Alternativelly, you can run `git init` in your local directory,
+ add the remote URL:
+ `git remote add origin git@gitlab.com:namespace/project-name.git`,
+ then add, commit, and push to GitLab.
+1. From the your **Project**'s page, click **Set up CI/CD**:
+
+ ![setup GitLab CI/CD](../img/setup_ci.png)
+
+1. Choose one of the templates from the dropbox menu.
+ Pick up the template corresponding to the SSG you're using (or plain HTML).
+
+ ![gitlab-ci templates](../img/choose_ci_template.png)
+
+ Note that, if you don't find a corresponding template, you can look into
+ [GitLab Pages group of sample projects](https://gitlab.com/pages),
+ you may find one among them that suits your needs, from which you
+ can copy `.gitlab-ci.yml`'s content and adjust for your case.
+ If you don't find it there either, [learn how to write a `.gitlab-ci.yml`
+ file for GitLab Pages](../getting_started_part_four.md).
+
+Once you have both site files and `.gitlab-ci.yml` in your project's
+root, GitLab CI/CD will build your site and deploy it with Pages.
+Once the first build passes, you access your site by
+navigating to your **Project**'s **Settings** > **Pages**,
+where you'll find its default URL. It can take approximately 30 min to be
+deployed.
diff --git a/doc/user/project/pages/getting_started/pages_bundled_template.md b/doc/user/project/pages/getting_started/pages_bundled_template.md
new file mode 100644
index 00000000000..802abeb3cc2
--- /dev/null
+++ b/doc/user/project/pages/getting_started/pages_bundled_template.md
@@ -0,0 +1,29 @@
+---
+type: reference, howto
+---
+
+# New Pages website from a bundled template
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/47857)
+in GitLab 11.8.
+
+The simplest way to create a GitLab Pages site is to use one of the most
+popular templates, which come already bundled with GitLab and are ready to go.
+
+1. From the top navigation, click the **+** button and select **New project**.
+1. Select **Create from Template**.
+1. Choose one of the templates starting with **Pages**:
+
+ ![Project templates for Pages](../img/pages_project_templates_v11_8.png)
+
+1. From the left sidebar, navigate to your project's **CI/CD > Pipelines**
+ and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
+ site to the server.
+1. After the pipeline has finished successfully, wait approximately 30 minutes
+ for your website to be visible. After waiting 30 minutes, find the link to
+ visit your website from your project's **Settings > Pages**. If the link
+ leads to a 404 page, wait a few minutes and try again.
+
+Your website is then visible on your domain and you can modify your files
+as you wish. For every modification pushed to your repository, GitLab CI/CD
+will run a new pipeline to immediately publish your changes to the server.
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 0b1cae9ab4c..f9169fba220 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -3,24 +3,11 @@ last_updated: 2018-06-04
type: concepts, reference
---
-# Static sites and GitLab Pages domains
+# GitLab Pages domain names, URLs, and baseurls
On this document, learn how to name your project for GitLab Pages
according to your intended website's URL.
-## Static sites
-
-GitLab Pages only supports static websites, meaning,
-your output files must be HTML, CSS, and JavaScript only.
-
-To create your static site, you can either hardcode in HTML,
-CSS, and JS, or use a [Static Site Generator (SSG)](https://www.staticgen.com/)
-to simplify your code and build the static site for you,
-which is highly recommendable and much faster than hardcoding.
-
-See the [further reading](#further-reading) section below for
-references on static site concepts.
-
## GitLab Pages domain names
>**Note:**
@@ -93,11 +80,35 @@ To understand Pages domains clearly, read the examples below.
- On your GitLab instance, replace `gitlab.io` above with your
Pages server domain. Ask your sysadmin for this information.
-_Read on about [Projects for GitLab Pages and URL structure](getting_started_part_two.md)._
+## URLs and Baseurls
+
+Every Static Site Generator (SSG) default configuration expects
+to find your website under a (sub)domain (`example.com`), not
+in a subdirectory of that domain (`example.com/subdir`). Therefore,
+whenever you publish a project website (`namespace.gitlab.io/project-name`),
+you'll have to look for this configuration (base URL) on your SSG's
+documentation and set it up to reflect this pattern.
+
+For example, for a Jekyll site, the `baseurl` is defined in the Jekyll
+configuration file, `_config.yml`. If your website URL is
+`https://john.gitlab.io/blog/`, you need to add this line to `_config.yml`:
+
+```yaml
+baseurl: "/blog"
+```
+
+On the contrary, if you deploy your website after forking one of
+our [default examples](https://gitlab.com/pages), the baseurl will
+already be configured this way, as all examples there are project
+websites. If you decide to make yours a user or group website, you'll
+have to remove this configuration from your project. For the Jekyll
+example we've just mentioned, you'd have to change Jekyll's `_config.yml` to:
+
+```yaml
+baseurl: ""
+```
-### Further reading
+## Custom Domains
-- Read through this technical overview on [Static versus Dynamic Websites](https://about.gitlab.com/blog/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/)
-- Understand [how modern Static Site Generators work](https://about.gitlab.com/blog/2016/06/10/ssg-overview-gitlab-pages-part-2/) and what you can add to your static site
-- You can use [any SSG with GitLab Pages](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
-- Fork an [example project](https://gitlab.com/pages) to build your website based upon
+GitLab Pages supports custom domains and subdomains, served under HTTP or HTTPS.
+See [GitLab Pages custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.md) for more information.
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
index ff752917087..70e84f5d486 100644
--- a/doc/user/project/pages/getting_started_part_two.md
+++ b/doc/user/project/pages/getting_started_part_two.md
@@ -1,172 +1,5 @@
---
-last_updated: 2019-06-04
-type: reference, howto
+redirect_to: 'index.md'
---
-# Projects for GitLab Pages and URL structure
-
-## What you need to get started
-
-To get started with GitLab Pages, you need:
-
-1. A project, thus a repository to hold your website's codebase.
-1. A configuration file (`.gitlab-ci.yml`) to deploy your site.
-1. A specific `job` called `pages` in the configuration file
- that will make GitLab aware that you are deploying a GitLab Pages website.
-1. A `public` directory with the static content of the website.
-
-Optional Features:
-
-1. A custom domain or subdomain.
-1. A DNS pointing your (sub)domain to your Pages site.
- 1. **Optional**: an SSL/TLS certificate so your custom
- domain is accessible under HTTPS.
-
-The optional settings, custom domain, DNS records, and SSL/TLS certificates, are described in [GitLab Pages custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.md)).
-
-## Project
-
-Your GitLab Pages project is a regular project created the
-same way you do for the other ones. To get started with GitLab Pages, you have three ways:
-
-- [Use one of the popular project templates bundled with GitLab](#use-one-of-the-popular-pages-templates-bundled-with-gitlab).
-- [Fork one of the templates from Page Examples](#fork-a-project-to-get-started-from).
-- [Create a new project from scratch](#create-a-project-from-scratch).
-
-### Use one of the popular Pages templates bundled with GitLab
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/47857)
-in GitLab 11.8.
-
-The simplest way to create a GitLab Pages site is to
-[use one of the most popular templates](index.md#getting-started),
-which come already bundled with GitLab and are ready to go.
-
-### Fork a project to get started from
-
-If you don't find an existing project template that suits you,
-we've created this [group](https://gitlab.com/pages) of default projects
-containing the most popular SSGs templates to get you started.
-
-<table class="borderless-table center fixed-table middle width-80">
- <tr>
- <td style="width: 30%"><img src="img/icons/fork.png" alt="Fork" class="image-noshadow half-width"></td>
- <td style="width: 10%">
- <strong>
- <i class="fa fa-angle-double-right" aria-hidden="true"></i>
- </strong>
- </td>
- <td style="width: 30%"><img src="img/icons/terminal.png" alt="Deploy" class="image-noshadow half-width"></td>
- <td style="width: 10%">
- <strong>
- <i class="fa fa-angle-double-right" aria-hidden="true"></i>
- </strong>
- </td>
- <td style="width: 30%"><img src="img/icons/click.png" alt="Visit" class="image-noshadow half-width"></td>
- </tr>
- <tr>
- <td><em>Fork an example project</em></td>
- <td></td>
- <td><em>Deploy your website</em></td>
- <td></td>
- <td><em>Visit your website's URL</em></td>
- </tr>
-</table>
-
-**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a [video tutorial](https://www.youtube.com/watch?v=TWqh9MtT4Bg) with all the steps below.**
-
-1. [Fork](../../../gitlab-basics/fork-project.md) a sample project from the [GitLab Pages examples](https://gitlab.com/pages) group.
-1. From the left sidebar, navigate to your project's **CI/CD > Pipelines**
- and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
- site to the server.
-1. Once the pipeline has finished successfully, find the link to visit your
- website from your project's **Settings > Pages**.
-
-You can also take some **optional** further steps:
-
-- _Remove the fork relationship._ The fork relationship is necessary to contribute back to the project you originally forked from. If you don't have any intentions to do so, you can remove it. To do so, navigate to your project's **Settings**, expand **Advanced settings**, and scroll down to **Remove fork relationship**:
-
- ![remove fork relationship](img/remove_fork_relationship.png)
-
-- _Make it a user or group website._ To turn a **project website** forked
- from the Pages group into a **user/group** website, you'll need to:
- - Rename it to `namespace.gitlab.io`: go to your project's
- **Settings > General** and expand **Advanced**. Scroll down to
- **Rename repository** and change the path to `namespace.gitlab.io`.
- - Adjust your SSG's [base URL](#urls-and-baseurls) from `"project-name"` to
- `""`. This setting will be at a different place for each SSG, as each of them
- have their own structure and file tree. Most likely, it will be in the SSG's
- config file.
-
-### Create a project from scratch
-
-1. From your **Project**'s **[Dashboard](https://gitlab.com/dashboard/projects)**,
- click **New project**, and name it according to the
- [Pages domain names](getting_started_part_one.md#gitlab-pages-domain-names).
-1. Clone it to your local computer, add your website
- files to your project, add, commit and push to GitLab.
-1. From the your **Project**'s page, click **Set up CI/CD**:
-
- ![setup GitLab CI/CD](img/setup_ci.png)
-
-1. Choose one of the templates from the dropbox menu.
- Pick up the template corresponding to the SSG you're using (or plain HTML).
-
- ![gitlab-ci templates](img/choose_ci_template.png)
-
-Once you have both site files and `.gitlab-ci.yml` in your project's
-root, GitLab CI/CD will build your site and deploy it with Pages.
-Once the first build passes, you see your site is live by
-navigating to your **Project**'s **Settings** > **Pages**,
-where you'll find its default URL.
-
-> **Notes:**
->
-> - GitLab Pages [supports any SSG](https://about.gitlab.com/blog/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/), but,
-> if you don't find yours among the templates, you'll need
-> to configure your own `.gitlab-ci.yml`. To do that, please
-> read through the article [Creating and Tweaking GitLab CI/CD for GitLab Pages](getting_started_part_four.md). New SSGs are very welcome among
-> the [example projects](https://gitlab.com/pages). If you set
-> up a new one, please
-> [contribute](https://gitlab.com/pages/pages.gitlab.io/blob/master/CONTRIBUTING.md)
-> to our examples.
->
-> - The second step _"Clone it to your local computer"_, can be done
-> differently, achieving the same results: instead of cloning the bare
-> repository to you local computer and moving your site files into it,
-> you can run `git init` in your local website directory, add the
-> remote URL: `git remote add origin git@gitlab.com:namespace/project-name.git`,
-> then add, commit, and push to GitLab.
-
-## URLs and Baseurls
-
-Every Static Site Generator (SSG) default configuration expects
-to find your website under a (sub)domain (`example.com`), not
-in a subdirectory of that domain (`example.com/subdir`). Therefore,
-whenever you publish a project website (`namespace.gitlab.io/project-name`),
-you'll have to look for this configuration (base URL) on your SSG's
-documentation and set it up to reflect this pattern.
-
-For example, for a Jekyll site, the `baseurl` is defined in the Jekyll
-configuration file, `_config.yml`. If your website URL is
-`https://john.gitlab.io/blog/`, you need to add this line to `_config.yml`:
-
-```yaml
-baseurl: "/blog"
-```
-
-On the contrary, if you deploy your website after forking one of
-our [default examples](https://gitlab.com/pages), the baseurl will
-already be configured this way, as all examples there are project
-websites. If you decide to make yours a user or group website, you'll
-have to remove this configuration from your project. For the Jekyll
-example we've just mentioned, you'd have to change Jekyll's `_config.yml` to:
-
-```yaml
-baseurl: ""
-```
-
-## Custom Domains
-
-GitLab Pages supports custom domains and subdomains, served under HTTP or HTTPS.
-See [GitLab Pages custom domains and SSL/TLS Certificates](custom_domains_ssl_tls_certification/index.md) for more information.
+This document was moved to [another location](index.md#getting-started).
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 7d533c6f9d1..d59c2e4fdf3 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -73,6 +73,7 @@ publish any website written directly in plain HTML, CSS, and JavaScript.</p>
To use GitLab Pages, first you need to create a project in GitLab to upload your website's
files to. These projects can be either public, internal, or private, at your own choice.
+
GitLab will always deploy your website from a very specific folder called `public` in your
repository. Note that when you create a new project in GitLab, a [repository](../repository/index.md)
becomes available automatically.
@@ -80,67 +81,48 @@ becomes available automatically.
To deploy your site, GitLab will use its built-in tool called [GitLab CI/CD](../../../ci/README.md),
to build your site and publish it to the GitLab Pages server. The sequence of
scripts that GitLab CI/CD runs to accomplish this task is created from a file named
-`.gitlab-ci.yml`, which you can [create and modify](getting_started_part_four.md) at will.
+`.gitlab-ci.yml`, which you can [create and modify](getting_started_part_four.md) at will. A specific `job` called `pages` in the configuration file will make GitLab aware that you are deploying a GitLab Pages website.
You can either use GitLab's [default domain for GitLab Pages websites](getting_started_part_one.md#gitlab-pages-domain-names),
`*.gitlab.io`, or your own domain (`example.com`). In that case, you'll
need admin access to your domain's registrar (or control panel) to set it up with Pages.
-Optionally, when adding your own domain, you can add an SSL/TLS certificate to secure your
-site under the HTTPS protocol.
-
### Getting started
To get started with GitLab Pages, you can either:
-- [Create a project from scratch](getting_started_part_two.md#create-a-project-from-scratch).
-- [Copy an existing example project](getting_started_part_two.md#fork-a-project-to-get-started-from).
-- Use a bundled project template ready to go:
-
-1. From the top navigation, click the **+** button and select **New project**.
-1. Select **Create from Template**.
-1. Choose one of the templates starting with **Pages**:
-
- ![Project templates for Pages](img/pages_project_templates_v11_8.png)
+- [Use a bundled website template ready to go](getting_started/pages_bundled_template.md).
+- [Copy an existing sample](getting_started/fork_sample_project.md).
+- [Create a website from scratch or deploy an existing one](getting_started/new_or_existing_website.md).
-1. From the left sidebar, navigate to your project's **CI/CD > Pipelines**
- and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your
- site to the server.
-1. After the pipeline has finished successfully, wait approximately 30 minutes
- for your website to be visible. After waiting 30 minutes, find the link to
- visit your website from your project's **Settings > Pages**. If the link
- leads to a 404 page, wait a few minutes and try again.
+Optional features:
-Your website is then visible on your domain and you can modify your files
-as you wish. For every modification pushed to your repository, GitLab CI/CD
-will run a new pipeline to immediately publish your changes to the server.
+- Use a [custom domain or subdomain](custom_domains_ssl_tls_certification/index.md#set-up-pages-with-a-custom-domain).
+- Add an [SSL/TLS certificate to secure your site under the HTTPS protocol](custom_domains_ssl_tls_certification/index.md#adding-an-ssltls-certificate-to-pages).
-_Advanced options:_
-
-- [Use a custom domain](custom_domains_ssl_tls_certification/index.md#set-up-pages-with-a-custom-domain)
-- Apply [SSL/TLS certification](custom_domains_ssl_tls_certification/index.md#adding-an-ssltls-certificate-to-pages) to your custom domain
+Note that, if you're using GitLab Pages default domain (`.gitlab.io`),
+your website will be automatically secure and available under
+HTTPS. If you're using your own custom domain, you can
+optionally secure it with SSL/TLS certificates.
## Availability
If you're using GitLab.com, your website will be publicly available to the internet.
+
+To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md).
+
If you're using self-managed instances (Core, Starter, Premium, or Ultimate),
your websites will be published on your own server, according to the
[Pages admin settings](../../../administration/pages/index.md) chosen by your sysadmin,
who can opt for making them public or internal to your server.
-Note that, if you're using GitLab Pages default domain (`.gitlab.io`),
-your website will be automatically secure and available under
-HTTPS. If you're using your own custom domain, you can
-optionally secure it with SSL/TLS certificates.
-
## Explore GitLab Pages
To learn more about configuration options for GitLab Pages, read the following:
| Document | Description |
| --- | --- |
-| [Static websites and Pages domains](getting_started_part_one.md) | Understand what is a static website, and how GitLab Pages default domains work. |
-| [Projects and URL structure](getting_started_part_two.md) | Forking projects and creating new ones from scratch, understanding URLs structure and baseurls. |
+| [GitLab Pages domain names, URLs, and baseurls](getting_started_part_one.md) | Understand how GitLab Pages default domains work. |
| [GitLab CI/CD for GitLab Pages](getting_started_part_four.md) | Understand how to create your own `.gitlab-ci.yml` for your site. |
| [Exploring GitLab Pages](introduction.md) | Requirements, technical aspects, specific GitLab CI's configuration options, Access Control, custom 404 pages, limitations, FAQ. |
|---+---|
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index 86257e2aa03..01e1909f6d6 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -69,40 +69,7 @@ don't have to create and edit HTML files manually. For example, Jekyll has the
## GitLab Pages Access Control **(CORE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/33422) in GitLab 11.5.
-
-You can enable Pages access control on your project, so that only
-[members of your project](../../permissions.md#project-members-permissions)
-(at least Guest) can access your website:
-
-1. Navigate to your project's **Settings > General > Permissions**.
-1. Toggle the **Pages** button to enable the access control.
-
- NOTE: **Note:**
- If you don't see the toggle button, that means that it's not enabled.
- Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
-
-1. The Pages access control dropdown allows you to set who can view pages hosted
- with GitLab Pages, depending on your project's visibility:
-
- - If your project is private:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
- - If your project is internal:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership.
- - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
- - If your project is public:
- - **Only project members**: Only project members will be able to browse the website.
- - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
-
-1. Click **Save changes**.
-
----
-
-The next time someone tries to access your website and the access control is
-enabled, they will be presented with a page to sign into GitLab and verify they
-can access the website.
+To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md).
## Unpublishing your Pages
diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
index 1338c7e58f5..c9bd3e35a5f 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -21,8 +21,8 @@ open source Certificate Authority.
To follow along with this tutorial, we assume you already have:
-- Created a [project](getting_started_part_two.md) in GitLab which
- contains your website's source code.
+- [Created a project](index.md#getting-started) in GitLab
+ containing your website's source code.
- Acquired a domain (`example.com`) and added a [DNS entry](custom_domains_ssl_tls_certification/index.md#set-up-pages-with-a-custom-domain)
pointing it to your Pages website.
- [Added your domain to your Pages project](custom_domains_ssl_tls_certification/index.md#steps)
diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md
new file mode 100644
index 00000000000..cd715c6e3b9
--- /dev/null
+++ b/doc/user/project/pages/pages_access_control.md
@@ -0,0 +1,48 @@
+---
+type: reference, howto
+---
+
+# GitLab Pages Access Control
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/issues/33422) in GitLab 11.5.
+> - Available on GitLab.com in GitLab 12.4.
+
+You can enable Pages access control on your project, so that only
+[members of your project](../../permissions.md#project-members-permissions)
+(at least Guest) can access your website:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Toggle the **Pages** button to enable the access control.
+
+ NOTE: **Note:**
+ If you don't see the toggle button, that means that it's not enabled.
+ Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
+
+1. The Pages access control dropdown allows you to set who can view pages hosted
+ with GitLab Pages, depending on your project's visibility:
+
+ - If your project is private:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - If your project is internal:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - If your project is public:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+
+1. Click **Save changes**.
+
+The next time someone tries to access your website and the access control is
+enabled, they will be presented with a page to sign into GitLab and verify they
+can access the website.
+
+## Terminating a Pages session
+
+If you want to log out from your Pages website,
+you can do so by revoking application access token for GitLab Pages:
+
+1. Navigate to your profile's **Settings > Applications**.
+1. Find **Authorized applications** at the bottom of the page.
+1. Find **GitLab Pages** and press the **Revoke** button.
diff --git a/lib/banzai/filter/inline_grafana_metrics_filter.rb b/lib/banzai/filter/inline_grafana_metrics_filter.rb
new file mode 100644
index 00000000000..34d93a59f48
--- /dev/null
+++ b/lib/banzai/filter/inline_grafana_metrics_filter.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # HTML filter that inserts a placeholder element for each
+ # reference to a grafana dashboard.
+ class InlineGrafanaMetricsFilter < Banzai::Filter::InlineEmbedsFilter
+ # Placeholder element for the frontend to use as an
+ # injection point for charts.
+ def create_element(params)
+ begin_loading_dashboard(params[:url])
+
+ doc.document.create_element(
+ 'div',
+ class: 'js-render-metrics',
+ 'data-dashboard-url': metrics_dashboard_url(params)
+ )
+ end
+
+ def embed_params(node)
+ return unless Feature.enabled?(:gfm_grafana_integration)
+
+ query_params = Gitlab::Metrics::Dashboard::Url.parse_query(node['href'])
+ return unless [:panelId, :from, :to].all? do |param|
+ query_params.include?(param)
+ end
+
+ { url: node['href'], start: query_params[:from], end: query_params[:to] }
+ end
+
+ # Selects any links with an href contains the configured
+ # grafana domain for the project
+ def xpath_search
+ return unless grafana_url.present?
+
+ %(descendant-or-self::a[starts-with(@href, '#{grafana_url}')])
+ end
+
+ private
+
+ def project
+ context[:project]
+ end
+
+ def grafana_url
+ project&.grafana_integration&.grafana_url
+ end
+
+ def metrics_dashboard_url(params)
+ Gitlab::Routing.url_helpers.project_grafana_api_metrics_dashboard_url(
+ project,
+ embedded: true,
+ grafana_url: params[:url],
+ start: format_time(params[:start]),
+ end: format_time(params[:end])
+ )
+ end
+
+ # Formats a timestamp from Grafana for compatibility with
+ # parsing in JS via `new Date(timestamp)`
+ #
+ # @param time [String] Represents miliseconds since epoch
+ def format_time(time)
+ Time.at(time.to_i / 1000).utc.strftime('%FT%TZ')
+ end
+
+ # Fetches a dashboard and caches the result for the
+ # FE to fetch quickly while rendering charts
+ def begin_loading_dashboard(url)
+ ::Gitlab::Metrics::Dashboard::Finder.find(
+ project,
+ embedded: true,
+ grafana_url: url
+ )
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/inline_metrics_redactor_filter.rb b/lib/banzai/filter/inline_metrics_redactor_filter.rb
index 4d8a5028898..e84ba83e03e 100644
--- a/lib/banzai/filter/inline_metrics_redactor_filter.rb
+++ b/lib/banzai/filter/inline_metrics_redactor_filter.rb
@@ -8,14 +8,17 @@ module Banzai
include Gitlab::Utils::StrongMemoize
METRICS_CSS_CLASS = '.js-render-metrics'
+ URL = Gitlab::Metrics::Dashboard::Url
+
+ Embed = Struct.new(:project_path, :permission)
# Finds all embeds based on the css class the FE
# uses to identify the embedded content, removing
# only unnecessary nodes.
def call
nodes.each do |node|
- path = paths_by_node[node]
- user_has_access = user_access_by_path[path]
+ embed = embeds_by_node[node]
+ user_has_access = user_access_by_embed[embed]
node.remove unless user_has_access
end
@@ -30,40 +33,69 @@ module Banzai
end
# Returns all nodes which the FE will identify as
- # a metrics dashboard placeholder element
+ # a metrics embed placeholder element
#
# @return [Nokogiri::XML::NodeSet]
def nodes
@nodes ||= doc.css(METRICS_CSS_CLASS)
end
- # Maps a node to the full path of a project.
+ # Maps a node to key properties of an embed.
# Memoized so we only need to run the regex to get
# the project full path from the url once per node.
#
- # @return [Hash<Nokogiri::XML::Node, String>]
- def paths_by_node
- strong_memoize(:paths_by_node) do
- nodes.each_with_object({}) do |node, paths|
- paths[node] = path_for_node(node)
+ # @return [Hash<Nokogiri::XML::Node, Embed>]
+ def embeds_by_node
+ strong_memoize(:embeds_by_node) do
+ nodes.each_with_object({}) do |node, embeds|
+ embed = Embed.new
+ url = node.attribute('data-dashboard-url').to_s
+
+ set_path_and_permission(embed, url, URL.regex, :read_environment)
+ set_path_and_permission(embed, url, URL.grafana_regex, :read_project) unless embed.permission
+
+ embeds[node] = embed if embed.permission
end
end
end
- # Gets a project's full_path from the dashboard url
- # in the placeholder node. The FE will use the attr
- # `data-dashboard-url`, so we want to check against that
- # attribute directly in case a user has manually
- # created a metrics element (rather than supporting
- # an alternate attr in InlineMetricsFilter).
+ # Attempts to determine the path and permission attributes
+ # of a url based on expected dashboard url formats and
+ # sets the attributes on an Embed object
#
- # @return [String]
- def path_for_node(node)
- url = node.attribute('data-dashboard-url').to_s
-
- Gitlab::Metrics::Dashboard::Url.regex.match(url) do |m|
+ # @param embed [Embed]
+ # @param url [String]
+ # @param regex [RegExp]
+ # @param permission [Symbol]
+ def set_path_and_permission(embed, url, regex, permission)
+ return unless path = regex.match(url) do |m|
"#{$~[:namespace]}/#{$~[:project]}"
end
+
+ embed.project_path = path
+ embed.permission = permission
+ end
+
+ # Returns a mapping representing whether the current user
+ # has permission to view the embed for the project.
+ # Determined in a batch
+ #
+ # @return [Hash<Embed, Boolean>]
+ def user_access_by_embed
+ strong_memoize(:user_access_by_embed) do
+ unique_embeds.each_with_object({}) do |embed, access|
+ project = projects_by_path[embed.project_path]
+
+ access[embed] = Ability.allowed?(user, embed.permission, project)
+ end
+ end
+ end
+
+ # Returns a unique list of embeds
+ #
+ # @return [Array<Embed>]
+ def unique_embeds
+ embeds_by_node.values.uniq
end
# Maps a project's full path to a Project object.
@@ -74,22 +106,17 @@ module Banzai
def projects_by_path
strong_memoize(:projects_by_path) do
Project.eager_load(:route, namespace: [:route])
- .where_full_path_in(paths_by_node.values.uniq)
+ .where_full_path_in(unique_project_paths)
.index_by(&:full_path)
end
end
- # Returns a mapping representing whether the current user
- # has permission to view the metrics for the project.
- # Determined in a batch
+ # Returns a list of the full_paths of every project which
+ # has an embed in the doc
#
- # @return [Hash<Project, Boolean>]
- def user_access_by_path
- strong_memoize(:user_access_by_path) do
- projects_by_path.each_with_object({}) do |(path, project), access|
- access[path] = Ability.allowed?(user, :read_environment, project)
- end
- end
+ # @return [Array<String>]
+ def unique_project_paths
+ embeds_by_node.values.map(&:project_path).uniq
end
end
end
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index 08e27257fdf..f6c12cdb53b 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -30,6 +30,7 @@ module Banzai
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
Filter::InlineMetricsFilter,
+ Filter::InlineGrafanaMetricsFilter,
Filter::TableOfContentsFilter,
Filter::AutolinkFilter,
Filter::ExternalLinkFilter,
diff --git a/lib/gitlab/metrics/dashboard/finder.rb b/lib/gitlab/metrics/dashboard/finder.rb
index 297f109ff81..268112f33a9 100644
--- a/lib/gitlab/metrics/dashboard/finder.rb
+++ b/lib/gitlab/metrics/dashboard/finder.rb
@@ -12,6 +12,7 @@ module Gitlab
# @param project [Project]
# @param user [User]
# @param environment [Environment]
+ # @param options [Hash<Symbol,Any>]
# @param options - embedded [Boolean] Determines whether the
# dashboard is to be rendered as part of an
# issue or location other than the primary
@@ -31,6 +32,8 @@ module Gitlab
# @param options - cluster [Cluster]
# @param options - cluster_type [Symbol] The level of
# cluster, one of [:admin, :project, :group]
+ # @param options - grafana_url [String] URL pointing
+ # to a grafana dashboard panel
# @return [Hash]
def find(project, user, options = {})
service_for(options)
diff --git a/lib/gitlab/metrics/dashboard/service_selector.rb b/lib/gitlab/metrics/dashboard/service_selector.rb
index 10b686fbb81..aee7f6685ad 100644
--- a/lib/gitlab/metrics/dashboard/service_selector.rb
+++ b/lib/gitlab/metrics/dashboard/service_selector.rb
@@ -18,6 +18,7 @@ module Gitlab
# @return [Gitlab::Metrics::Dashboard::Services::BaseService]
def call(params)
return SERVICES::CustomMetricEmbedService if custom_metric_embed?(params)
+ return SERVICES::GrafanaMetricEmbedService if grafana_metric_embed?(params)
return SERVICES::DynamicEmbedService if dynamic_embed?(params)
return SERVICES::DefaultEmbedService if params[:embedded]
return SERVICES::SystemDashboardService if system_dashboard?(params[:dashboard_path])
@@ -40,6 +41,10 @@ module Gitlab
SERVICES::CustomMetricEmbedService.valid_params?(params)
end
+ def grafana_metric_embed?(params)
+ SERVICES::GrafanaMetricEmbedService.valid_params?(params)
+ end
+
def dynamic_embed?(params)
SERVICES::DynamicEmbedService.valid_params?(params)
end
diff --git a/lib/gitlab/metrics/dashboard/url.rb b/lib/gitlab/metrics/dashboard/url.rb
index 94f8b2e02b1..712f769bbeb 100644
--- a/lib/gitlab/metrics/dashboard/url.rb
+++ b/lib/gitlab/metrics/dashboard/url.rb
@@ -14,17 +14,31 @@ module Gitlab
def regex
%r{
(?<url>
- #{Regexp.escape(Gitlab.config.gitlab.url)}
- \/#{Project.reference_pattern}
+ #{gitlab_pattern}
+ #{project_pattern}
(?:\/\-)?
\/environments
\/(?<environment>\d+)
\/metrics
- (?<query>
- \?[a-zA-Z0-9%.()+_=-]+
- (&[a-zA-Z0-9%.()+_=-]+)*
- )?
- (?<anchor>\#[a-z0-9_-]+)?
+ #{query_pattern}
+ #{anchor_pattern}
+ )
+ }x
+ end
+
+ # Matches dashboard urls for a Grafana embed.
+ #
+ # EX - https://<host>/<namespace>/<project>/grafana/metrics_dashboard
+ def grafana_regex
+ %r{
+ (?<url>
+ #{gitlab_pattern}
+ #{project_pattern}
+ (?:\/\-)?
+ \/grafana
+ \/metrics_dashboard
+ #{query_pattern}
+ #{anchor_pattern}
)
}x
end
@@ -45,6 +59,24 @@ module Gitlab
def build_dashboard_url(*args)
Gitlab::Routing.url_helpers.metrics_dashboard_namespace_project_environment_url(*args)
end
+
+ private
+
+ def gitlab_pattern
+ Regexp.escape(Gitlab.config.gitlab.url)
+ end
+
+ def project_pattern
+ "\/#{Project.reference_pattern}"
+ end
+
+ def query_pattern
+ '(?<query>\?[a-zA-Z0-9%.()+_=-]+(&[a-zA-Z0-9%.()+_=-]+)*)?'
+ end
+
+ def anchor_pattern
+ '(?<anchor>\#[a-z0-9_-]+)?'
+ end
end
end
end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index db67e4fd479..713ca31bbc5 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -14,6 +14,7 @@ module Gitlab
NOTIFICATION_CHANNEL = 'workhorse:notifications'
ALLOWED_GIT_HTTP_ACTIONS = %w[git_receive_pack git_upload_pack info_refs].freeze
DETECT_HEADER = 'Gitlab-Workhorse-Detect-Content-Type'
+ ARCHIVE_FORMATS = %w(zip tar.gz tar.bz2 tar).freeze
include JwtAuthenticatable
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 76bfa60867d..6ed098d1842 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8498,6 +8498,9 @@ msgstr ""
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
msgstr ""
+msgid "GroupSettings|cannot change when group contains projects with NPM packages"
+msgstr ""
+
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
msgstr ""
@@ -17645,6 +17648,9 @@ msgstr ""
msgid "TransferGroup|Database is not supported."
msgstr ""
+msgid "TransferGroup|Group contains projects with NPM packages."
+msgstr ""
+
msgid "TransferGroup|Group is already a root group."
msgstr ""
@@ -17672,6 +17678,9 @@ msgstr ""
msgid "TransferProject|Project with same name or path in target namespace already exists"
msgstr ""
+msgid "TransferProject|Root namespace can't be updated if project has NPM packages"
+msgstr ""
+
msgid "TransferProject|Transfer failed, please contact an admin."
msgstr ""
@@ -19209,6 +19218,9 @@ msgstr ""
msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
msgstr ""
+msgid "You can try again using %{begin_link}basic search%{end_link}"
+msgstr ""
+
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
diff --git a/qa/qa/runtime/fixtures.rb b/qa/qa/runtime/fixtures.rb
index f91218ea0b5..ed051b18a9a 100644
--- a/qa/qa/runtime/fixtures.rb
+++ b/qa/qa/runtime/fixtures.rb
@@ -30,7 +30,7 @@ module QA
yield dir
ensure
- FileUtils.remove_entry(dir)
+ FileUtils.remove_entry(dir, true)
end
private
diff --git a/qa/qa/service/docker_run/maven.rb b/qa/qa/service/docker_run/maven.rb
index 435a68776d9..8bdea20963d 100644
--- a/qa/qa/service/docker_run/maven.rb
+++ b/qa/qa/service/docker_run/maven.rb
@@ -27,10 +27,16 @@ module QA
--hostname #{host_name}
--name #{@name}
--volume #{@volume_host_path}:/home/maven
- #{@image} sh -c "sleep 60"
+ #{@image} sh -c "sleep 300"
CMD
shell "docker cp #{@volume_host_path}/. #{@name}:/home/maven"
shell "docker exec -t #{@name} sh -c 'cd /home/maven && mvn deploy -s settings.xml'"
+
+ # Stop the container when `mvn deploy` is finished otherwise
+ # the sleeping container will hold onto the files in @volume_host_path,
+ # which causes problems when they're created in a tmp dir
+ # that we want to delete
+ shell "docker stop #{@name}"
end
end
end
diff --git a/spec/controllers/concerns/metrics_dashboard_spec.rb b/spec/controllers/concerns/metrics_dashboard_spec.rb
index a71e34fd1ca..71c3833bd2d 100644
--- a/spec/controllers/concerns/metrics_dashboard_spec.rb
+++ b/spec/controllers/concerns/metrics_dashboard_spec.rb
@@ -31,11 +31,13 @@ describe MetricsDashboard do
end
context 'when params are provided' do
+ let(:params) { { environment: environment } }
+
before do
allow(controller).to receive(:project).and_return(project)
allow(controller)
.to receive(:metrics_dashboard_params)
- .and_return(environment: environment)
+ .and_return(params)
end
it 'returns the specified dashboard' do
@@ -43,6 +45,15 @@ describe MetricsDashboard do
expect(json_response).not_to have_key('all_dashboards')
end
+ context 'when the params are in an alternate format' do
+ let(:params) { ActionController::Parameters.new({ environment: environment }).permit! }
+
+ it 'returns the specified dashboard' do
+ expect(json_response['dashboard']['dashboard']).to eq('Environment metrics')
+ expect(json_response).not_to have_key('all_dashboards')
+ end
+ end
+
context 'when parameters are provided and the list of all dashboards is required' do
before do
allow(controller).to receive(:include_all_dashboards?).and_return(true)
diff --git a/spec/controllers/projects/grafana_api_controller_spec.rb b/spec/controllers/projects/grafana_api_controller_spec.rb
index 352a364295b..96a12efdcfc 100644
--- a/spec/controllers/projects/grafana_api_controller_spec.rb
+++ b/spec/controllers/projects/grafana_api_controller_spec.rb
@@ -94,4 +94,87 @@ describe Projects::GrafanaApiController do
end
end
end
+
+ describe 'GET #metrics_dashboard' do
+ let(:service_result) { { status: :success, dashboard: '{}' } }
+ let(:params) do
+ {
+ format: :json,
+ embedded: true,
+ grafana_url: 'https://grafana.example.com',
+ namespace_id: project.namespace.full_path,
+ project_id: project.name
+ }
+ end
+
+ before do
+ allow(Gitlab::Metrics::Dashboard::Finder)
+ .to receive(:find)
+ .and_return(service_result)
+ end
+
+ context 'when the result is still processing' do
+ let(:service_result) { nil }
+
+ it 'returns 204 no content' do
+ get :metrics_dashboard, params: params
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+
+ context 'when the result was successful' do
+ it 'returns the dashboard response' do
+ get :metrics_dashboard, params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({
+ 'dashboard' => '{}',
+ 'status' => 'success'
+ })
+ end
+ end
+
+ context 'when an error has occurred' do
+ shared_examples_for 'error response' do |http_status|
+ it "returns #{http_status}" do
+ get :metrics_dashboard, params: params
+
+ expect(response).to have_gitlab_http_status(http_status)
+ expect(json_response['status']).to eq('error')
+ expect(json_response['message']).to eq('error message')
+ end
+ end
+
+ context 'with an error accessing grafana' do
+ let(:service_result) do
+ {
+ http_status: :service_unavailable,
+ status: :error,
+ message: 'error message'
+ }
+ end
+
+ it_behaves_like 'error response', :service_unavailable
+ end
+
+ context 'with a processing error' do
+ let(:service_result) { { status: :error, message: 'error message' } }
+
+ it_behaves_like 'error response', :bad_request
+ end
+ end
+
+ context 'when grafana embeds are not enabled' do
+ before do
+ stub_feature_flags(gfm_grafana_integration: false)
+ end
+
+ it 'returns 403 immediately' do
+ get :metrics_dashboard, params: params
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
end
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 0f60cd42748..7b969aea547 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -28,6 +28,7 @@ describe 'User uses header search field', :js do
context 'when using the keyboard shortcut' do
before do
+ find('#search.js-autocomplete-disabled')
find('body').native.send_keys('s')
end
diff --git a/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb
new file mode 100644
index 00000000000..81053469e7a
--- /dev/null
+++ b/spec/lib/banzai/filter/inline_grafana_metrics_filter_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Banzai::Filter::InlineGrafanaMetricsFilter do
+ include FilterSpecHelper
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:grafana_integration) { create(:grafana_integration, project: project) }
+
+ let(:input) { %(<a href="#{url}">example</a>) }
+ let(:doc) { filter(input) }
+
+ let(:url) { grafana_integration.grafana_url + dashboard_path }
+ let(:dashboard_path) do
+ '/d/XDaNK6amz/gitlab-omnibus-redis' \
+ '?from=1570397739557&to=1570484139557' \
+ '&var-instance=All&panelId=14'
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(gfm_grafana_integration: false)
+ end
+
+ it 'leaves the markdown unchanged' do
+ expect(unescape(doc.to_s)).to eq(input)
+ end
+ end
+
+ it 'appends a metrics charts placeholder with dashboard url after metrics links' do
+ node = doc.at_css('.js-render-metrics')
+ expect(node).to be_present
+
+ dashboard_url = urls.project_grafana_api_metrics_dashboard_url(
+ project,
+ embedded: true,
+ grafana_url: url,
+ start: "2019-10-06T21:35:39Z",
+ end: "2019-10-07T21:35:39Z"
+ )
+
+ expect(node.attribute('data-dashboard-url').to_s).to eq(dashboard_url)
+ end
+
+ context 'when the dashboard link is part of a paragraph' do
+ let(:paragraph) { %(This is an <a href="#{url}">example</a> of metrics.) }
+ let(:input) { %(<p>#{paragraph}</p>) }
+
+ it 'appends the charts placeholder after the enclosing paragraph' do
+ expect(unescape(doc.at_css('p').to_s)).to include(paragraph)
+ expect(doc.at_css('.js-render-metrics')).to be_present
+ end
+ end
+
+ context 'when grafana is not configured' do
+ before do
+ allow(project).to receive(:grafana_integration).and_return(nil)
+ end
+
+ it 'leaves the markdown unchanged' do
+ expect(unescape(doc.to_s)).to eq(input)
+ end
+ end
+
+ context 'when parameters are missing' do
+ let(:dashboard_path) { '/d/XDaNK6amz/gitlab-omnibus-redis' }
+
+ it 'leaves the markdown unchanged' do
+ expect(unescape(doc.to_s)).to eq(input)
+ end
+ end
+
+ private
+
+ # Nokogiri escapes the URLs, but we don't care about that
+ # distinction for the purposes of this filter
+ def unescape(html)
+ CGI.unescapeHTML(html)
+ end
+end
diff --git a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
index a99cd7d6076..745b9133529 100644
--- a/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
+++ b/spec/lib/banzai/filter/inline_metrics_redactor_filter_spec.rb
@@ -18,30 +18,48 @@ describe Banzai::Filter::InlineMetricsRedactorFilter do
end
context 'with a metrics charts placeholder' do
- let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) }
+ shared_examples_for 'a supported metrics dashboard url' do
+ context 'no user is logged in' do
+ it 'redacts the placeholder' do
+ expect(doc.to_s).to be_empty
+ end
+ end
- context 'no user is logged in' do
- it 'redacts the placeholder' do
- expect(doc.to_s).to be_empty
+ context 'the user does not have permission do see charts' do
+ let(:doc) { filter(input, current_user: build(:user)) }
+
+ it 'redacts the placeholder' do
+ expect(doc.to_s).to be_empty
+ end
end
- end
- context 'the user does not have permission do see charts' do
- let(:doc) { filter(input, current_user: build(:user)) }
+ context 'the user has requisite permissions' do
+ let(:user) { create(:user) }
+ let(:doc) { filter(input, current_user: user) }
- it 'redacts the placeholder' do
- expect(doc.to_s).to be_empty
+ it 'leaves the placeholder' do
+ project.add_maintainer(user)
+
+ expect(doc.to_s).to eq input
+ end
end
end
- context 'the user has requisite permissions' do
- let(:user) { create(:user) }
- let(:doc) { filter(input, current_user: user) }
+ let(:input) { %(<div class="js-render-metrics" data-dashboard-url="#{url}"></div>) }
- it 'leaves the placeholder' do
- project.add_maintainer(user)
+ it_behaves_like 'a supported metrics dashboard url'
+
+ context 'for a grafana dashboard' do
+ let(:url) { urls.project_grafana_api_metrics_dashboard_url(project, embedded: true) }
+
+ it_behaves_like 'a supported metrics dashboard url'
+ end
- expect(doc.to_s).to eq input
+ context 'for an internal non-dashboard url' do
+ let(:url) { urls.project_url(project) }
+
+ it 'leaves the placeholder' do
+ expect(doc.to_s).to be_empty
end
end
end
diff --git a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb
index 095d0a2df78..0d4562f78f1 100644
--- a/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/service_selector_spec.rb
@@ -75,6 +75,17 @@ describe Gitlab::Metrics::Dashboard::ServiceSelector do
it { is_expected.to be Metrics::Dashboard::CustomMetricEmbedService }
end
+
+ context 'with a grafana link' do
+ let(:arguments) do
+ {
+ embedded: true,
+ grafana_url: 'https://grafana.example.com'
+ }
+ end
+
+ it { is_expected.to be Metrics::Dashboard::GrafanaMetricEmbedService }
+ end
end
end
end
diff --git a/spec/lib/gitlab/metrics/dashboard/url_spec.rb b/spec/lib/gitlab/metrics/dashboard/url_spec.rb
index e0dc6d98efc..daaf66cba46 100644
--- a/spec/lib/gitlab/metrics/dashboard/url_spec.rb
+++ b/spec/lib/gitlab/metrics/dashboard/url_spec.rb
@@ -3,13 +3,41 @@
require 'spec_helper'
describe Gitlab::Metrics::Dashboard::Url do
- describe '#regex' do
- it 'returns a regular expression' do
- expect(described_class.regex).to be_a Regexp
- end
+ shared_examples_for 'a regex which matches the expected url' do
+ it { is_expected.to be_a Regexp }
it 'matches a metrics dashboard link with named params' do
- url = Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url(
+ expect(subject).to match url
+
+ subject.match(url) do |m|
+ expect(m.named_captures).to eq expected_params
+ end
+ end
+ end
+
+ shared_examples_for 'does not match non-matching urls' do
+ it 'does not match other gitlab urls that contain the term metrics' do
+ url = Gitlab::Routing.url_helpers.active_common_namespace_project_prometheus_metrics_url('foo', 'bar', :json)
+
+ expect(subject).not_to match url
+ end
+
+ it 'does not match other gitlab urls' do
+ url = Gitlab.config.gitlab.url
+
+ expect(subject).not_to match url
+ end
+
+ it 'does not match non-gitlab urls' do
+ url = 'https://www.super_awesome_site.com/'
+
+ expect(subject).not_to match url
+ end
+ end
+
+ describe '#regex' do
+ let(:url) do
+ Gitlab::Routing.url_helpers.metrics_namespace_project_environment_url(
'foo',
'bar',
1,
@@ -18,8 +46,10 @@ describe Gitlab::Metrics::Dashboard::Url do
group: 'awesome group',
anchor: 'title'
)
+ end
- expected_params = {
+ let(:expected_params) do
+ {
'url' => url,
'namespace' => 'foo',
'project' => 'bar',
@@ -27,31 +57,40 @@ describe Gitlab::Metrics::Dashboard::Url do
'query' => '?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z',
'anchor' => '#title'
}
-
- expect(described_class.regex).to match url
-
- described_class.regex.match(url) do |m|
- expect(m.named_captures).to eq expected_params
- end
end
- it 'does not match other gitlab urls that contain the term metrics' do
- url = Gitlab::Routing.url_helpers.active_common_namespace_project_prometheus_metrics_url('foo', 'bar', :json)
+ subject { described_class.regex }
- expect(described_class.regex).not_to match url
- end
+ it_behaves_like 'a regex which matches the expected url'
+ it_behaves_like 'does not match non-matching urls'
+ end
- it 'does not match other gitlab urls' do
- url = Gitlab.config.gitlab.url
+ describe '#grafana_regex' do
+ let(:url) do
+ Gitlab::Routing.url_helpers.namespace_project_grafana_api_metrics_dashboard_url(
+ 'foo',
+ 'bar',
+ start: '2019-08-02T05:43:09.000Z',
+ dashboard: 'config/prometheus/common_metrics.yml',
+ group: 'awesome group',
+ anchor: 'title'
+ )
+ end
- expect(described_class.regex).not_to match url
+ let(:expected_params) do
+ {
+ 'url' => url,
+ 'namespace' => 'foo',
+ 'project' => 'bar',
+ 'query' => '?dashboard=config%2Fprometheus%2Fcommon_metrics.yml&group=awesome+group&start=2019-08-02T05%3A43%3A09.000Z',
+ 'anchor' => '#title'
+ }
end
- it 'does not match non-gitlab urls' do
- url = 'https://www.super_awesome_site.com/'
+ subject { described_class.grafana_regex }
- expect(described_class.regex).not_to match url
- end
+ it_behaves_like 'a regex which matches the expected url'
+ it_behaves_like 'does not match non-matching urls'
end
describe '#build_dashboard_url' do
diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb
index 297367853f0..e1622888d79 100644
--- a/spec/models/release_spec.rb
+++ b/spec/models/release_spec.rb
@@ -57,14 +57,14 @@ RSpec.describe Release do
subject { release.assets_count }
it 'returns the number of sources' do
- is_expected.to eq(Releases::Source::FORMATS.count)
+ is_expected.to eq(Gitlab::Workhorse::ARCHIVE_FORMATS.count)
end
context 'when a links exists' do
let!(:link) { create(:release_link, release: release) }
it 'counts the link as an asset' do
- is_expected.to eq(1 + Releases::Source::FORMATS.count)
+ is_expected.to eq(1 + Gitlab::Workhorse::ARCHIVE_FORMATS.count)
end
it "excludes sources count when asked" do
diff --git a/spec/models/releases/source_spec.rb b/spec/models/releases/source_spec.rb
index c5213196962..c8ac8e31c97 100644
--- a/spec/models/releases/source_spec.rb
+++ b/spec/models/releases/source_spec.rb
@@ -11,7 +11,7 @@ describe Releases::Source do
it 'returns all formats of sources' do
expect(subject.map(&:format))
- .to match_array(described_class::FORMATS)
+ .to match_array(Gitlab::Workhorse::ARCHIVE_FORMATS)
end
end
diff --git a/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb b/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb
index 920fcbde483..21c32c9c04a 100644
--- a/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb
+++ b/spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
shared_examples 'archive download buttons' do
- let(:formats) { %w(zip tar.gz tar.bz2 tar) }
let(:path_to_visit) { project_path(project) }
let(:ref) { project.default_branch }
@@ -13,7 +12,7 @@ shared_examples 'archive download buttons' do
context 'private project' do
it 'shows archive download buttons with external storage URL prepended and user token appended to their href' do
- formats.each do |format|
+ Gitlab::Workhorse::ARCHIVE_FORMATS.each do |format|
path = archive_path(project, ref, format)
uri = URI('https://cdn.gitlab.com')
uri.path = path
@@ -28,7 +27,7 @@ shared_examples 'archive download buttons' do
let(:project) { create(:project, :repository, :public) }
it 'shows archive download buttons with external storage URL prepended to their href' do
- formats.each do |format|
+ Gitlab::Workhorse::ARCHIVE_FORMATS.each do |format|
path = archive_path(project, ref, format)
uri = URI('https://cdn.gitlab.com')
uri.path = path
@@ -45,7 +44,7 @@ shared_examples 'archive download buttons' do
end
it 'shows default archive download buttons' do
- formats.each do |format|
+ Gitlab::Workhorse::ARCHIVE_FORMATS.each do |format|
path = archive_path(project, ref, format)
expect(page).to have_link format, href: path