summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml20
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml3
-rw-r--r--app/assets/javascripts/manual_ordering.js2
-rw-r--r--app/assets/javascripts/tracking.js67
-rw-r--r--app/assets/stylesheets/framework/common.scss1
-rw-r--r--app/controllers/groups_controller.rb4
-rw-r--r--app/controllers/projects/issues_controller.rb4
-rw-r--r--app/models/application_setting_implementation.rb11
-rw-r--r--app/models/environment.rb2
-rw-r--r--app/models/note.rb4
-rw-r--r--app/services/application_settings/update_service.rb9
-rw-r--r--app/services/self_monitoring/project/create_service.rb32
-rw-r--r--app/views/projects/mirrors/_instructions.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml5
-rw-r--r--app/views/shared/issuable/_sort_dropdown.html.haml2
-rw-r--r--app/views/u2f/_register.html.haml2
-rw-r--r--changelogs/unreleased/61776-fixing-the-U2F-warning-message-text-colour.yml5
-rw-r--r--changelogs/unreleased/double-slash-64592.yml5
-rw-r--r--changelogs/unreleased/jramsay-fix-mirroring-help-text-typo.yml5
-rw-r--r--changelogs/unreleased/sh-fix-special-role-error-500.yml5
-rw-r--r--changelogs/unreleased/snowplow-ee-to-ce.yml5
-rw-r--r--doc/administration/auth/ldap-ee.md126
-rw-r--r--doc/administration/auth/ldap.md50
-rw-r--r--doc/administration/geo/replication/index.md67
-rw-r--r--doc/administration/gitaly/index.md91
-rw-r--r--doc/api/jobs.md6
-rw-r--r--doc/ci/ci_cd_for_external_repos/bitbucket_integration.md198
-rw-r--r--doc/ci/docker/using_docker_build.md342
-rw-r--r--doc/ci/docker/using_docker_images.md131
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md70
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md111
-rw-r--r--doc/ci/ssh_keys/README.md82
-rw-r--r--doc/ci/variables/README.md7
-rw-r--r--doc/ci/yaml/README.md16
-rw-r--r--doc/development/fe_guide/event_tracking.md93
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/topics/autodevops/index.md6
-rw-r--r--doc/user/application_security/dast/index.md5
-rw-r--r--doc/user/project/img/key_value_labels.pngbin6208 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_default.pngbin35620 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_default_v12_1.pngbin0 -> 207994 bytes
-rw-r--r--doc/user/project/img/labels_delete_v12_1.pngbin0 -> 29186 bytes
-rw-r--r--doc/user/project/img/labels_drag_priority_v12_1.gifbin0 -> 958437 bytes
-rw-r--r--doc/user/project/img/labels_epic_sidebar.pngbin47869 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_epic_sidebar_v12_1.pngbin0 -> 318960 bytes
-rw-r--r--doc/user/project/img/labels_generate_default.pngbin25797 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_generate_default_v12_1.pngbin0 -> 244739 bytes
-rw-r--r--doc/user/project/img/labels_group_issues.pngbin92070 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_group_issues_v12_1.pngbin0 -> 391121 bytes
-rw-r--r--doc/user/project/img/labels_key_value_v12_1.pngbin0 -> 332077 bytes
-rw-r--r--doc/user/project/img/labels_list.pngbin75215 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_list_v12_1.pngbin0 -> 360298 bytes
-rw-r--r--doc/user/project/img/labels_new_label_from_sidebar.gif (renamed from doc/user/project/img/new_label_from_sidebar.gif)bin759243 -> 759243 bytes
-rw-r--r--doc/user/project/img/labels_prioritized.pngbin56353 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_prioritized_v12_1.pngbin0 -> 178652 bytes
-rw-r--r--doc/user/project/img/labels_promotion.pngbin44021 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_promotion_v12_1.pngbin0 -> 29215 bytes
-rw-r--r--doc/user/project/img/labels_subscriptions.pngbin31716 -> 0 bytes
-rw-r--r--doc/user/project/img/labels_subscriptions_v12_1.pngbin0 -> 138684 bytes
-rw-r--r--doc/user/project/labels.md183
-rw-r--r--doc/user/project/packages/npm_registry.md30
-rw-r--r--lib/feature.rb7
-rw-r--r--lib/gitlab/profiler.rb3
-rw-r--r--lib/peek/views/rugged.rb8
-rw-r--r--locale/gitlab.pot8
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb34
-rwxr-xr-xscripts/review_apps/review-apps.sh25
-rw-r--r--spec/controllers/admin/clusters/applications_controller_spec.rb2
-rw-r--r--spec/controllers/groups/clusters/applications_controller_spec.rb2
-rw-r--r--spec/controllers/help_controller_spec.rb2
-rw-r--r--spec/factories/clusters/applications/helm.rb2
-rw-r--r--spec/frontend/tracking_spec.js123
-rw-r--r--spec/lib/feature_spec.rb16
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb2
-rw-r--r--spec/lib/peek/views/rugged_spec.rb10
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb10
-rw-r--r--spec/models/clusters/cluster_spec.rb2
-rw-r--r--spec/models/environment_spec.rb29
-rw-r--r--spec/models/note_spec.rb16
-rw-r--r--spec/models/project_spec.rb10
-rw-r--r--spec/services/application_settings/update_service_spec.rb48
-rw-r--r--spec/services/self_monitoring/project/create_service_spec.rb24
-rw-r--r--spec/support/shared_examples/application_setting_examples.rb62
85 files changed, 1481 insertions, 780 deletions
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index ee9e467886a..dcc681294d2 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -1,7 +1,6 @@
-package-and-qa:
+.package-and-qa-base:
image: ruby:2.6-alpine
stage: review # So even if review-deploy failed we can still run this
- when: manual
before_script: []
dependencies: []
cache: {}
@@ -13,5 +12,18 @@ package-and-qa:
- install_gitlab_gem
- ./scripts/trigger-build omnibus
only:
- - /.+/@gitlab-org/gitlab-ce
- - /.+/@gitlab-org/gitlab-ee
+ - branches@gitlab-org/gitlab-ce
+ - branches@gitlab-org/gitlab-ee
+
+package-and-qa:
+ extends: .package-and-qa-base
+ when: manual
+ except:
+ - /(^qa[\/-].*|.*-qa$)/
+
+package-and-qa-always:
+ extends: .package-and-qa-base
+ allow_failure: true
+ only:
+ - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-ce
+ - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-ee
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 41d52c4e095..aa722f6ef33 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -101,8 +101,7 @@ schedule:review-build-cng:
- install_tiller
- install_external_dns
- download_chart
- - deploy || display_deployment_debug
- - wait_for_review_app_to_be_accessible
+ - deploy || (display_deployment_debug && exit 1)
- add_license
artifacts:
paths: [review_app_url.txt]
diff --git a/app/assets/javascripts/manual_ordering.js b/app/assets/javascripts/manual_ordering.js
index 012d1e70410..29a0e5a904a 100644
--- a/app/assets/javascripts/manual_ordering.js
+++ b/app/assets/javascripts/manual_ordering.js
@@ -21,7 +21,7 @@ const updateIssue = (url, issueList, { move_before_id, move_after_id }) =>
const initManualOrdering = () => {
const issueList = document.querySelector('.manual-ordering');
- if (!issueList || !(gon.features && gon.features.manualSorting) || !(gon.current_user_id > 0)) {
+ if (!issueList || !(gon.current_user_id > 0)) {
return;
}
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
new file mode 100644
index 00000000000..2d0b099cf0b
--- /dev/null
+++ b/app/assets/javascripts/tracking.js
@@ -0,0 +1,67 @@
+import $ from 'jquery';
+
+const extractData = (el, opts = {}) => {
+ const { trackEvent, trackLabel = '', trackProperty = '' } = el.dataset;
+ let trackValue = el.dataset.trackValue || el.value || '';
+ if (el.type === 'checkbox' && !el.checked) trackValue = false;
+ return [
+ trackEvent + (opts.suffix || ''),
+ {
+ label: trackLabel,
+ property: trackProperty,
+ value: trackValue,
+ },
+ ];
+};
+
+export default class Tracking {
+ static enabled() {
+ return typeof window.snowplow === 'function';
+ }
+
+ static event(category = document.body.dataset.page, event = 'generic', data = {}) {
+ if (!this.enabled()) return false;
+ // eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
+ if (!category) throw new Error('Tracking: no category provided for tracking.');
+
+ return window.snowplow(
+ 'trackStructEvent',
+ category,
+ event,
+ Object.assign({}, { label: '', property: '', value: '' }, data),
+ );
+ }
+
+ constructor(category = document.body.dataset.page) {
+ this.category = category;
+ }
+
+ bind(container = document) {
+ if (!this.constructor.enabled()) return;
+ container.querySelectorAll(`[data-track-event]`).forEach(el => {
+ if (this.customHandlingFor(el)) return;
+ // jquery is required for select2, so we use it always
+ // see: https://github.com/select2/select2/issues/4686
+ $(el).on('click', this.eventHandler(this.category));
+ });
+ }
+
+ customHandlingFor(el) {
+ const classes = el.classList;
+
+ // bootstrap dropdowns
+ if (classes.contains('dropdown')) {
+ $(el).on('show.bs.dropdown', this.eventHandler(this.category, { suffix: '_show' }));
+ $(el).on('hide.bs.dropdown', this.eventHandler(this.category, { suffix: '_hide' }));
+ return true;
+ }
+
+ return false;
+ }
+
+ eventHandler(category = null, opts = {}) {
+ return e => {
+ this.constructor.event(category || this.category, ...extractData(e.currentTarget, opts));
+ };
+ }
+}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 6b44834cc52..f384a49e0ae 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -435,6 +435,7 @@ img.emoji {
/** COMMON SIZING CLASSES **/
.w-0 { width: 0; }
.w-8em { width: 8em; }
+.w-3rem { width: 3rem; }
.h-12em { height: 12em; }
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index dda321bac79..5472ef05d7c 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -7,10 +7,6 @@ class GroupsController < Groups::ApplicationController
include PreviewMarkdown
include RecordUserLastActivity
- before_action do
- push_frontend_feature_flag(:manual_sorting, default_enabled: true)
- end
-
respond_to :html
prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) }
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index db7ca7ef0d7..bc9166b9df3 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -10,10 +10,6 @@ class Projects::IssuesController < Projects::ApplicationController
include SpammableActions
include RecordUserLastActivity
- before_action do
- push_frontend_feature_flag(:manual_sorting, default_enabled: true)
- end
-
def issue_except_actions
%i[index calendar new create bulk_update import_csv]
end
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 6efd07a6008..4bb09bf3b53 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -158,9 +158,20 @@ module ApplicationSettingImplementation
end
def outbound_local_requests_whitelist_raw=(values)
+ clear_memoization(:outbound_local_requests_whitelist_arrays)
+
self.outbound_local_requests_whitelist = domain_strings_to_array(values)
end
+ def add_to_outbound_local_requests_whitelist(values_array)
+ clear_memoization(:outbound_local_requests_whitelist_arrays)
+
+ self.outbound_local_requests_whitelist ||= []
+ self.outbound_local_requests_whitelist += values_array
+
+ self.outbound_local_requests_whitelist.uniq!
+ end
+
def outbound_local_requests_whitelist_arrays
strong_memoize(:outbound_local_requests_whitelist_arrays) do
next [[], []] unless self.outbound_local_requests_whitelist
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 392481ea0cc..513427ac2c5 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -204,7 +204,7 @@ class Environment < ApplicationRecord
public_path = project.public_path_for_source_path(path, commit_sha)
return unless public_path
- [external_url, public_path].join('/')
+ [external_url.delete_suffix('/'), public_path.delete_prefix('/')].join('/')
end
def expire_etag_cache
diff --git a/app/models/note.rb b/app/models/note.rb
index 3f182c1f099..a12d1eb7243 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -27,6 +27,10 @@ class Note < ApplicationRecord
def values
constants.map {|const| self.const_get(const)}
end
+
+ def value?(val)
+ values.include?(val)
+ end
end
end
diff --git a/app/services/application_settings/update_service.rb b/app/services/application_settings/update_service.rb
index 7eeaf8aade1..471df6e2d0c 100644
--- a/app/services/application_settings/update_service.rb
+++ b/app/services/application_settings/update_service.rb
@@ -15,6 +15,8 @@ module ApplicationSettings
update_terms(@params.delete(:terms))
+ add_to_outbound_local_requests_whitelist(@params.delete(:add_to_outbound_local_requests_whitelist))
+
if params.key?(:performance_bar_allowed_group_path)
params[:performance_bar_allowed_group_id] = performance_bar_allowed_group_id
end
@@ -32,6 +34,13 @@ module ApplicationSettings
params.key?(:usage_ping_enabled) || params.key?(:version_check_enabled)
end
+ def add_to_outbound_local_requests_whitelist(values)
+ values_array = Array(values).reject(&:empty?)
+ return if values_array.empty?
+
+ @application_setting.add_to_outbound_local_requests_whitelist(values_array)
+ end
+
def update_terms(terms)
return unless terms.present?
diff --git a/app/services/self_monitoring/project/create_service.rb b/app/services/self_monitoring/project/create_service.rb
index e5ef8c15456..8ffd22de127 100644
--- a/app/services/self_monitoring/project/create_service.rb
+++ b/app/services/self_monitoring/project/create_service.rb
@@ -14,6 +14,7 @@ module SelfMonitoring
steps :validate_admins,
:create_project,
:add_project_members,
+ :add_to_whitelist,
:add_prometheus_manual_configuration
def initialize
@@ -59,15 +60,29 @@ module SelfMonitoring
end
end
- def add_prometheus_manual_configuration
+ def add_to_whitelist
return success unless prometheus_enabled?
return success unless prometheus_listen_address.present?
- # TODO: Currently, adding the internal prometheus server as a manual configuration
- # is only possible if the setting to allow webhooks and services to connect
- # to local network is on.
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/44496 will add
- # a whitelist that will allow connections to certain ips on the local network.
+ uri = parse_url(internal_prometheus_listen_address_uri)
+ return error(_('Prometheus listen_address is not a valid URI')) unless uri
+
+ result = ApplicationSettings::UpdateService.new(
+ Gitlab::CurrentSettings.current_application_settings,
+ project_owner,
+ outbound_local_requests_whitelist: [uri.normalized_host]
+ ).execute
+
+ if result
+ success
+ else
+ error(_('Could not add prometheus URL to whitelist'))
+ end
+ end
+
+ def add_prometheus_manual_configuration
+ return success unless prometheus_enabled?
+ return success unless prometheus_listen_address.present?
service = project.find_or_initialize_service('prometheus')
@@ -79,6 +94,11 @@ module SelfMonitoring
success
end
+ def parse_url(uri_string)
+ Addressable::URI.parse(uri_string)
+ rescue Addressable::URI::InvalidURIError, TypeError
+ end
+
def prometheus_enabled?
Gitlab.config.prometheus.enable
rescue Settingslogic::MissingSetting
diff --git a/app/views/projects/mirrors/_instructions.html.haml b/app/views/projects/mirrors/_instructions.html.haml
index 33e5a6e67c3..1a163cc4a54 100644
--- a/app/views/projects/mirrors/_instructions.html.haml
+++ b/app/views/projects/mirrors/_instructions.html.haml
@@ -2,7 +2,7 @@
%ul
%li
= _('The repository must be accessible over <code>http://</code>,
- <code>https://</code>, <code>ssh://</code> and <code>git://</code>.').html_safe
+ <code>https://</code>, <code>ssh://</code> or <code>git://</code>.').html_safe
%li= _('Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>.').html_safe
%li
- minutes = Gitlab.config.gitlab_shell.git_timeout / 60
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 2d108a1cba5..498a9744783 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -99,7 +99,7 @@
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
- %code ^TOTAL\s+\d+\s+\d+\s+(\d+\%)$
+ %code ^TOTAL.+?(\d+\%)$
%li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index e253413929a..c9458475aa5 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -1,6 +1,7 @@
- type = local_assigns.fetch(:type)
- board = local_assigns.fetch(:board, nil)
-- block_css_class = type != :boards_modal ? 'row-content-block second-block' : ''
+- is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics
+- block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : ''
- user_can_admin_list = board && can?(current_user, :admin_list, board.parent)
.issues-filters{ class: ("w-100" if type == :boards_modal) }
@@ -155,5 +156,5 @@
- if @project
#js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
#js-toggle-focus-btn
- - elsif type != :boards_modal
+ - elsif is_not_boards_modal_or_productivity_analytics
= render 'shared/issuable/sort_dropdown'
diff --git a/app/views/shared/issuable/_sort_dropdown.html.haml b/app/views/shared/issuable/_sort_dropdown.html.haml
index df0523595f5..8260915c2ab 100644
--- a/app/views/shared/issuable/_sort_dropdown.html.haml
+++ b/app/views/shared/issuable/_sort_dropdown.html.haml
@@ -1,7 +1,7 @@
- sort_value = @sort
- sort_title = issuable_sort_option_title(sort_value)
- viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues'
-- manual_sorting = viewing_issues && controller.controller_name != 'dashboard' && Feature.enabled?(:manual_sorting, default_enabled: true)
+- manual_sorting = viewing_issues && controller.controller_name != 'dashboard'
.dropdown.inline.prepend-left-10.issue-sort-dropdown
.btn-group{ role: 'group' }
diff --git a/app/views/u2f/_register.html.haml b/app/views/u2f/_register.html.haml
index f6724f72307..ef3835332a7 100644
--- a/app/views/u2f/_register.html.haml
+++ b/app/views/u2f/_register.html.haml
@@ -16,7 +16,7 @@
.col-md-4
%button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new U2F device")
.col-md-8
- %p.text-warning= _("You need to register a two-factor authentication app before you can set up a U2F device.")
+ %p= _("You need to register a two-factor authentication app before you can set up a U2F device.")
%script#js-register-u2f-in-progress{ type: "text/template" }
%p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
diff --git a/changelogs/unreleased/61776-fixing-the-U2F-warning-message-text-colour.yml b/changelogs/unreleased/61776-fixing-the-U2F-warning-message-text-colour.yml
new file mode 100644
index 00000000000..988eb77db12
--- /dev/null
+++ b/changelogs/unreleased/61776-fixing-the-U2F-warning-message-text-colour.yml
@@ -0,0 +1,5 @@
+---
+title: Remove the warning style from the U2F device message in user settings > account
+merge_request: 30119
+author: matejlatin
+type: other
diff --git a/changelogs/unreleased/double-slash-64592.yml b/changelogs/unreleased/double-slash-64592.yml
new file mode 100644
index 00000000000..e3b5b197ac5
--- /dev/null
+++ b/changelogs/unreleased/double-slash-64592.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent double slash in review apps path
+merge_request: 31212
+author:
+type: fixed
diff --git a/changelogs/unreleased/jramsay-fix-mirroring-help-text-typo.yml b/changelogs/unreleased/jramsay-fix-mirroring-help-text-typo.yml
new file mode 100644
index 00000000000..4c049dffc58
--- /dev/null
+++ b/changelogs/unreleased/jramsay-fix-mirroring-help-text-typo.yml
@@ -0,0 +1,5 @@
+---
+title: Fix mirroring help text
+merge_request: 31348
+author: jramsay
+type: other
diff --git a/changelogs/unreleased/sh-fix-special-role-error-500.yml b/changelogs/unreleased/sh-fix-special-role-error-500.yml
new file mode 100644
index 00000000000..9aed0710da3
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-special-role-error-500.yml
@@ -0,0 +1,5 @@
+---
+title: Fix first-time contributor notes not rendering
+merge_request: 31340
+author:
+type: fixed
diff --git a/changelogs/unreleased/snowplow-ee-to-ce.yml b/changelogs/unreleased/snowplow-ee-to-ce.yml
new file mode 100644
index 00000000000..85c959f0510
--- /dev/null
+++ b/changelogs/unreleased/snowplow-ee-to-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Moves snowplow tracking from ee to ce
+merge_request: 31160
+author: jejacks0n
+type: added
diff --git a/doc/administration/auth/ldap-ee.md b/doc/administration/auth/ldap-ee.md
index 1b7af2d945a..34f3cfa353f 100644
--- a/doc/administration/auth/ldap-ee.md
+++ b/doc/administration/auth/ldap-ee.md
@@ -4,37 +4,27 @@ type: reference
# LDAP Additions in GitLab EE **(STARTER ONLY)**
-This is a continuation of the main [LDAP documentation](ldap.md), detailing LDAP
-features specific to GitLab Enterprise Edition Starter, Premium and Ultimate.
+This section documents LDAP features specific to to GitLab Enterprise Edition
+[Starter](https://about.gitlab.com/pricing/#self-managed) and above.
-## Overview
-
-[LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
-stands for **Lightweight Directory Access Protocol**, which
-is a standard application protocol for
-accessing and maintaining distributed directory information services
-over an Internet Protocol (IP) network.
-
-GitLab integrates with LDAP to support **user authentication**. This integration
-works with most LDAP-compliant directory servers, including Microsoft Active
-Directory, Apple Open Directory, Open LDAP, and 389 Server.
-**GitLab Enterprise Edition** includes enhanced integration, including group
-membership syncing.
+For documentation relevant to both Community Edition and Enterprise Edition,
+see the main [LDAP documentation](ldap.md).
## Use cases
-- User sync: Once a day, GitLab will update users against LDAP
+- User sync: Once a day, GitLab will update users against LDAP.
- Group sync: Once an hour, GitLab will update group membership
- based on LDAP group members
+ based on LDAP group members.
-## Multiple LDAP servers
+## Multiple LDAP servers **(STARTER ONLY)**
With GitLab Enterprise Edition Starter, you can configure multiple LDAP servers
that your GitLab instance will connect to.
-To add another LDAP server, you can start by duplicating the settings under
-[the main configuration](ldap.md#configuration) and edit them to match the
-additional LDAP server.
+To add another LDAP server:
+
+1. Duplicating the settings under [the main configuration](ldap.md#configuration).
+1. Edit them to match the additional LDAP server.
Be sure to choose a different provider ID made of letters a-z and numbers 0-9.
This ID will be stored in the database so that GitLab can remember which LDAP
@@ -47,19 +37,19 @@ users against LDAP.
The process will execute the following access checks:
-1. Ensure the user is still present in LDAP
-1. If the LDAP server is Active Directory, ensure the user is active (not
- blocked/disabled state). This will only be checked if
- `active_directory: true` is set in the LDAP configuration [^1]
+- Ensure the user is still present in LDAP.
+- If the LDAP server is Active Directory, ensure the user is active (not
+ blocked/disabled state). This will only be checked if
+ `active_directory: true` is set in the LDAP configuration. [^1]
The user will be set to `ldap_blocked` state in GitLab if the above conditions
fail. This means the user will not be able to login or push/pull code.
The process will also update the following user information:
-1. Email address
-1. If `sync_ssh_keys` is set, SSH public keys
-1. If Kerberos is enabled, Kerberos identity
+- Email address.
+- If `sync_ssh_keys` is set, SSH public keys.
+- If Kerberos is enabled, Kerberos identity.
NOTE: **Note:**
The LDAP sync process updates existing users while new users will
@@ -72,9 +62,6 @@ first time GitLab will trigger a sync for groups the user should be a member of.
That way they don't need to wait for the hourly sync to be granted
access to their groups and projects.
-In GitLab Premium, we can also add a GitLab group to sync with one or multiple LDAP groups or we can
-also add a filter. The filter must comply with the syntax defined in [RFC 2254](https://tools.ietf.org/search/rfc2254).
-
A group sync process will run every hour on the hour, and `group_base` must be set
in LDAP configuration for LDAP synchronizations based on group CN to work. This allows
GitLab group membership to be automatically updated based on LDAP group members.
@@ -120,13 +107,26 @@ following.
1. [Restart GitLab][restart] for the changes to take effect.
----
-
To take advantage of group sync, group owners or maintainers will need to create an
-LDAP group link in their group **Settings > LDAP Groups** page. Multiple LDAP
-groups and/or filters can be linked with a single GitLab group. When the link is
-created, an access level/role is specified (Guest, Reporter, Developer, Maintainer,
-or Owner).
+LDAP group link in their group **Settings > LDAP Groups** page.
+
+Multiple LDAP groups and [filters](#filters-premium-only) can be linked with
+a single GitLab group. When the link is created, an access level/role is
+specified (Guest, Reporter, Developer, Maintainer, or Owner).
+
+### Filters **(PREMIUM ONLY)**
+
+In GitLab Premium, you can add an LDAP user filter for group synchronization.
+Filters allow for complex logic without creating a special LDAP group.
+
+To sync GitLab group membership based on an LDAP filter:
+
+1. Open the **LDAP Synchronization** page for the GitLab group.
+1. Select **LDAP user filter** as the **Sync method**.
+1. Enter an LDAP user filter in the **LDAP user filter** field.
+
+The filter must comply with the
+syntax defined in [RFC 2254](https://tools.ietf.org/search/rfc2254).
## Administrator sync
@@ -190,10 +190,13 @@ group, as opposed to the full DN.
## Global group memberships lock
"Lock memberships to LDAP synchronization" setting allows instance administrators
-to lock down user abilities to invite new members to a group. When enabled following happens:
+to lock down user abilities to invite new members to a group.
+
+When enabled, the following applies:
-1. Only administrator can manage memberships of any group including access levels.
-1. Users are not allowed to share project with other groups or invite members to a project created in a group.
+- Only administrator can manage memberships of any group including access levels.
+- Users are not allowed to share project with other groups or invite members to
+ a project created in a group.
## Adjusting LDAP user sync schedule
@@ -333,10 +336,18 @@ administrative duties.
### Supported LDAP group types/attributes
-GitLab supports LDAP groups that use member attributes `member`, `submember`,
-`uniquemember`, `memberof` and `memberuid`. This means group sync supports, at
-least, LDAP groups with object class `groupOfNames`, `posixGroup`, and
-`groupOfUniqueName`. Other object classes should work fine as long as members
+GitLab supports LDAP groups that use member attributes:
+
+- `member`
+- `submember`
+- `uniquemember`
+- `memberof`
+- `memberuid`.
+
+This means group sync supports, at least, LDAP groups with object class:
+`groupOfNames`, `posixGroup`, and `groupOfUniqueName`.
+
+Other object classes should work fine as long as members
are defined as one of the mentioned attributes. This also means GitLab supports
Microsoft Active Directory, Apple Open Directory, Open LDAP, and 389 Server.
Other LDAP servers should work, too.
@@ -344,11 +355,12 @@ Other LDAP servers should work, too.
Active Directory also supports nested groups. Group sync will recursively
resolve membership if `active_directory: true` is set in the configuration file.
-> **Note:** Nested group membership will only be resolved if the nested group
- also falls within the configured `group_base`. For example, if GitLab sees a
- nested group with DN `cn=nested_group,ou=special_groups,dc=example,dc=com` but
- the configured `group_base` is `ou=groups,dc=example,dc=com`, `cn=nested_group`
- will be ignored.
+NOTE: **Note:**
+Nested group membership will only be resolved if the nested group
+also falls within the configured `group_base`. For example, if GitLab sees a
+nested group with DN `cn=nested_group,ou=special_groups,dc=example,dc=com` but
+the configured `group_base` is `ou=groups,dc=example,dc=com`, `cn=nested_group`
+will be ignored.
### Queries
@@ -403,7 +415,7 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
[^1]: In Active Directory, a user is marked as disabled/blocked if the user
account control attribute (`userAccountControl:1.2.840.113556.1.4.803`)
- has bit 2 set. See https://ctogonewild.com/2009/09/03/bitmask-searches-in-ldap/
+ has bit 2 set. See <https://ctogonewild.com/2009/09/03/bitmask-searches-in-ldap/>
for more information.
### User DN has changed
@@ -423,10 +435,10 @@ things to check to debug the situation.
- Ensure LDAP configuration has a `group_base` specified. This configuration is
required for group sync to work properly.
- Ensure the correct LDAP group link is added to the GitLab group. Check group
- links by visiting the GitLab group, then **Settings dropdown -> LDAP groups**.
-- Check that the user has an LDAP identity
+ links by visiting the GitLab group, then **Settings dropdown > LDAP groups**.
+- Check that the user has an LDAP identity:
1. Sign in to GitLab as an administrator user.
- 1. Navigate to **Admin area -> Users**.
+ 1. Navigate to **Admin area > Users**.
1. Search for the user
1. Open the user, by clicking on their name. Do not click 'Edit'.
1. Navigate to the **Identities** tab. There should be an LDAP identity with
@@ -437,7 +449,7 @@ Often, the best way to learn more about why group sync is behaving a certain
way is to enable debug logging. There is verbose output that details every
step of the sync.
-1. Start a Rails console
+1. Start a Rails console:
```bash
# For Omnibus installations
@@ -446,6 +458,7 @@ step of the sync.
# For installations from source
sudo -u git -H bundle exec rails console production
```
+
1. Set the log level to debug (only for this session):
```ruby
@@ -540,8 +553,9 @@ and more DNs may be added, or existing entries modified, based on additional
LDAP group lookups. The very last occurrence of this entry should indicate
exactly which users GitLab believes should be added to the group.
-> **Note:** 10 is 'Guest', 20 is 'Reporter', 30 is 'Developer', 40 is 'Maintainer'
- and 50 is 'Owner'
+NOTE: **Note:**
+10 is 'Guest', 20 is 'Reporter', 30 is 'Developer', 40 is 'Maintainer'
+and 50 is 'Owner'.
```bash
Resolved 'my_group' group member access: {"uid=john0,ou=people,dc=example,dc=com"=>30,
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index be05a4d63a7..beacaa99d60 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -7,16 +7,29 @@ type: reference
# LDAP
GitLab integrates with LDAP to support user authentication.
-This integration works with most LDAP-compliant directory
-servers, including Microsoft Active Directory, Apple Open Directory, Open LDAP,
-and 389 Server. GitLab Enterprise Editions include enhanced integration,
+
+This integration works with most LDAP-compliant directory servers, including:
+
+- Microsoft Active Directory
+- Apple Open Directory
+- Open LDAP
+- 389 Server.
+
+GitLab Enterprise Editions (EE) include enhanced integration,
including group membership syncing as well as multiple LDAP servers support.
-## GitLab EE
+For more details about EE-specific LDAP features, see the
+[LDAP Enterprise Edition documentation](ldap-ee.md).
-The information on this page is relevant for both GitLab CE and EE. For more
-details about EE-specific LDAP features, see the
-[LDAP Enterprise Edition documentation](ldap-ee.md). **(STARTER ONLY)**
+NOTE: **Note:**
+The information on this page is relevant for both GitLab CE and EE.
+
+## Overview
+
+[LDAP](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
+stands for **Lightweight Directory Access Protocol**, which is a standard
+application protocol for accessing and maintaining distributed directory
+information services over an Internet Protocol (IP) network.
## Security
@@ -64,9 +77,12 @@ NOTE: **Note**:
In GitLab Enterprise Edition Starter, you can configure multiple LDAP servers
to connect to one GitLab server.
-For a complete guide on configuring LDAP with GitLab Community Edition, please check
-the admin guide [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md).
-For GitLab Enterprise Editions, see also [How to configure LDAP with GitLab EE](how_to_configure_ldap_gitlab_ee/index.md). **(STARTER ONLY)**
+For a complete guide on configuring LDAP with:
+
+- GitLab Community Edition, see
+ [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md).
+- Enterprise Editions, see
+ [How to configure LDAP with GitLab EE](how_to_configure_ldap_gitlab_ee/index.md). **(STARTER ONLY)**
To enable LDAP integration you need to add your LDAP server settings in
`/etc/gitlab/gitlab.rb` or `/home/git/gitlab/config/gitlab.yml` for Omnibus
@@ -384,7 +400,7 @@ production:
Tip: If you want to limit access to the nested members of an Active Directory
group, you can use the following syntax:
-```
+```text
(memberOf:1.2.840.113556.1.4.1941:=CN=My Group,DC=Example,DC=com)
```
@@ -402,13 +418,13 @@ The `user_filter` DN can contain special characters. For example:
- A comma:
- ```
+ ```text
OU=GitLab, Inc,DC=gitlab,DC=com
```
- Open and close brackets:
- ```
+ ```text
OU=Gitlab (Inc),DC=gitlab,DC=com
```
@@ -417,13 +433,13 @@ The `user_filter` DN can contain special characters. For example:
- Escape commas with `\2C`. For example:
- ```
+ ```text
OU=GitLab\2C Inc,DC=gitlab,DC=com
```
- Escape open and close brackets with `\28` and `\29`, respectively. For example:
- ```
+ ```text
OU=Gitlab \28Inc\29,DC=gitlab,DC=com
```
@@ -507,11 +523,11 @@ timeout), the login is rejected and a message will be logged to
### Debug LDAP user filter with ldapsearch
-This example uses ldapsearch and assumes you are using ActiveDirectory. The
+This example uses `ldapsearch` and assumes you are using ActiveDirectory. The
following query returns the login names of the users that will be allowed to
log in to GitLab if you configure your own user_filter.
-```
+```sh
ldapsearch -H ldaps://$host:$port -D "$bind_dn" -y bind_dn_password.txt -b "$base" "$user_filter" sAMAccountName
```
diff --git a/doc/administration/geo/replication/index.md b/doc/administration/geo/replication/index.md
index b5789c87e47..dc49a95e008 100644
--- a/doc/administration/geo/replication/index.md
+++ b/doc/administration/geo/replication/index.md
@@ -245,35 +245,48 @@ This list of limitations only reflects the latest version of GitLab. If you are
- Object pools for forked project deduplication work only on the **primary** node, and are duplicated on the **secondary** node.
- [External merge request diffs](../../merge_request_diffs.md) will not be replicated if they are on-disk, and viewing merge requests will fail. However, external MR diffs in object storage **are** supported. The default configuration (in-database) does work.
-### Limitations on replication
-
-Only the following items are replicated to the **secondary** node:
-
-- All database content. For example, snippets, epics, issues, merge requests, groups, and project metadata.
-- Project repositories.
-- Project wiki repositories.
-- User uploads. For example, attachments to issues, merge requests, epics, and avatars.
-- CI job artifacts and traces.
+### Limitations on replication/verification
+
+The following table lists the GitLab features along with their replication
+and verification status on a **secondary** node.
+
+You can keep track of the progress to include the missing items in:
+
+- [ee-893](https://gitlab.com/groups/gitlab-org/-/epics/893).
+- [ee-1430](https://gitlab.com/groups/gitlab-org/-/epics/1430).
+
+| Feature | Replicated | Verified |
+|-----------|------------|----------|
+| All database content (e.g. snippets, epics, issues, merge requests, groups, and project metadata) | Yes | Yes |
+| Project repository | Yes | Yes |
+| Project wiki repository | Yes | Yes |
+| Project designs repository | No | No |
+| Uploads (e.g. attachments to issues, merge requests, epics, and avatars) | Yes | Yes, only on transfer, or manually (1) |
+| LFS Objects | Yes | Yes, only on transfer, or manually (1) |
+| CI job artifacts (other than traces) | Yes | No, only manually (1) |
+| Archived traces | Yes | Yes, only on transfer, or manually (1) |
+| Personal snippets | Yes | Yes |
+| Version-controlled personal snippets ([unsupported](https://gitlab.com/gitlab-org/gitlab-ce/issues/13426)) | No | No |
+| Project snippets | Yes | Yes |
+| Version-controlled project snippets ([unsupported](https://gitlab.com/gitlab-org/gitlab-ce/issues/13426)) | No | No |
+| Object pools for forked project deduplication | No | No |
+| [Server-side Git Hooks](../../custom_hooks.md) | No | No |
+| [Elasticsearch integration](../../../integration/elasticsearch.md) | No | No |
+| [GitLab Pages](../../pages/index.md) | No | No |
+| [Container Registry](../../container_registry.md) ([track progress](https://gitlab.com/gitlab-org/gitlab-ee/issues/2870)) | No | No |
+| [NPM Registry](../../npm_registry.md) | No | No |
+| [Maven Packages](../../maven_packages.md) | No | No |
+| [External merge request diffs](../../merge_request_diffs.md) | No, if they are on-disk | No |
+| Content in object storage ([track progress](https://gitlab.com/groups/gitlab-org/-/epics/1526)) | No | No |
+
+1. The integrity can be verified manually using [Integrity Check Rake Task](../../raketasks/check.md) on both nodes and comparing the output between them.
DANGER: **DANGER**
-Data not on this list is unavailable on the **secondary** node. Failing over without manually replicating data not on this list will cause the data to be **lost**.
-
-### Examples of data not replicated
-
-Take special note that these examples of GitLab features are both:
-
-- Commonly used.
-- **Not** replicated by Geo at present.
-
-Examples include:
-
-- [Elasticsearch integration](../../../integration/elasticsearch.md).
-- [Container Registry](../../container_registry.md). [Object Storage](object_storage.md) can mitigate this.
-- [GitLab Pages](../../pages/index.md).
-- [Mattermost integration](https://docs.gitlab.com/omnibus/gitlab-mattermost/).
-
-CAUTION: **Caution:**
-If you wish to use them on a **secondary** node, or to execute a failover successfully, you will need to replicate their data using some other means.
+Features not on this list, or with **No** in the **Replicated** column,
+are not replicated on the **secondary** node. Failing over without manually
+replicating data from those features will cause the data to be **lost**.
+If you wish to use those features on a **secondary** node, or to execute a failover
+successfully, you must replicate their data using some other means.
## Frequently Asked Questions
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 0f547ef03bf..f6f02221fe3 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -510,3 +510,94 @@ implemented as calls to `gitaly-ruby`:
```
sum(rate(grpc_client_handled_total[5m])) by (grpc_method) > 0
```
+
+### Repository changes fail with a `401 Unauthorized` error
+
+If you're running Gitaly on its own server and notice that users can
+successfully clone and fetch repositories (via both SSH and HTTPS), but can't
+push to them or make changes to the repository in the web UI without getting a
+`401 Unauthorized` message, then it's possible Gitaly is failing to authenticate
+with the other nodes due to having the [wrong secrets file](#3-gitaly-server-configuration).
+
+Confirm the following are all true:
+
+- When any user performs a `git push` to any repository on this Gitaly node, it
+ fails with the following error (note the `401 Unauthorized`):
+
+ ```sh
+ remote: GitLab: 401 Unauthorized
+ To <REMOTE_URL>
+ ! [remote rejected] branch-name -> branch-name (pre-receive hook declined)
+ error: failed to push some refs to '<REMOTE_URL>'
+ ```
+
+- When any user adds or modifies a file from the repository using the GitLab
+ UI, it immediatley fails with a red `401 Unauthorized` banner.
+- Creating a new project and [initializing it with a README](../../gitlab-basics/create-project.md#blank-projects)
+ successfully creates the project but doesn't create the README.
+- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.md#tail-logs-in-a-console-on-the-server) on an app node and reproducing the error, you get `401` errors
+ when reaching the `/api/v4/internal/allowed` endpoint:
+
+ ```sh
+ # api_json.log
+ {
+ "time": "2019-07-18T00:30:14.967Z",
+ "severity": "INFO",
+ "duration": 0.57,
+ "db": 0,
+ "view": 0.57,
+ "status": 401,
+ "method": "POST",
+ "path": "\/api\/v4\/internal\/allowed",
+ "params": [
+ {
+ "key": "action",
+ "value": "git-receive-pack"
+ },
+ {
+ "key": "changes",
+ "value": "REDACTED"
+ },
+ {
+ "key": "gl_repository",
+ "value": "REDACTED"
+ },
+ {
+ "key": "project",
+ "value": "\/path\/to\/project.git"
+ },
+ {
+ "key": "protocol",
+ "value": "web"
+ },
+ {
+ "key": "env",
+ "value": "{\"GIT_ALTERNATE_OBJECT_DIRECTORIES\":[],\"GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE\":[],\"GIT_OBJECT_DIRECTORY\":null,\"GIT_OBJECT_DIRECTORY_RELATIVE\":null}"
+ },
+ {
+ "key": "user_id",
+ "value": "2"
+ },
+ {
+ "key": "secret_token",
+ "value": "[FILTERED]"
+ }
+ ],
+ "host": "gitlab.example.com",
+ "ip": "REDACTED",
+ "ua": "Ruby",
+ "route": "\/api\/:version\/internal\/allowed",
+ "queue_duration": 4.24,
+ "gitaly_calls": 0,
+ "gitaly_duration": 0,
+ "correlation_id": "XPUZqTukaP3"
+ }
+
+ # nginx_access.log
+ [IP] - - [18/Jul/2019:00:30:14 +0000] "POST /api/v4/internal/allowed HTTP/1.1" 401 30 "" "Ruby"
+ ```
+
+To fix this problem, confirm that your [`gitlab-secrets.json` file](#3-gitaly-server-configuration)
+on the Gitaly node matches the one on all other nodes. If it doesn't match,
+update the secrets file on the Gitaly node to match the others, then
+[reconfigure the node](../restart_gitlab.md#omnibus-gitlab-reconfigure).
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 0e45ee1a583..2a1c1b5f6f3 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -491,7 +491,7 @@ Parameters
Example request:
```sh
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf"
+curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/5/artifacts/some/release/file.pdf"
```
Possible response status codes:
@@ -526,7 +526,7 @@ Parameters:
Example request:
```sh
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf"
+curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/artifacts/master/raw/some/release/file.pdf?job=pdf"
```
Possible response status codes:
@@ -551,7 +551,7 @@ GET /projects/:id/jobs/:job_id/trace
| job_id | integer | yes | ID of a job. |
```sh
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
+curl --location --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/jobs/8/trace"
```
Possible response status codes:
diff --git a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
index b3110b435db..8fe11140cc7 100644
--- a/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
+++ b/doc/ci/ci_cd_for_external_repos/bitbucket_integration.md
@@ -14,9 +14,9 @@ To use GitLab CI/CD with a Bitbucket Cloud repository:
1. In GitLab create a **CI/CD for external repo**, select **Repo by URL** and
create the project.
- ![Create project](img/external_repository.png)
+ ![Create project](img/external_repository.png)
- GitLab will import the repository and enable [Pull Mirroring][pull-mirroring].
+ GitLab will import the repository and enable [Pull Mirroring][pull-mirroring].
1. In GitLab create a
[Personal Access Token](../../user/profile/personal_access_tokens.md)
@@ -26,19 +26,19 @@ To use GitLab CI/CD with a Bitbucket Cloud repository:
1. In Bitbucket, from **Settings > Webhooks**, create a new web hook to notify
GitLab of new commits.
- The web hook URL should be set to the GitLab API to trigger pull mirroring,
- using the Personal Access Token we just generated for authentication.
+ The web hook URL should be set to the GitLab API to trigger pull mirroring,
+ using the Personal Access Token we just generated for authentication.
- ```text
- https://gitlab.com/api/v4/projects/<NAMESPACE>%2F<PROJECT>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN>
- ```
+ ```text
+ https://gitlab.com/api/v4/projects/<NAMESPACE>%2F<PROJECT>/mirror/pull?private_token=<PERSONAL_ACCESS_TOKEN>
+ ```
- The web hook Trigger should be set to 'Repository Push'.
+ The web hook Trigger should be set to 'Repository Push'.
- ![Bitbucket Cloud webhook](img/bitbucket_webhook.png)
+ ![Bitbucket Cloud webhook](img/bitbucket_webhook.png)
- After saving, test the web hook by pushing a change to your Bitbucket
- repository.
+ After saving, test the web hook by pushing a change to your Bitbucket
+ repository.
1. In Bitbucket, create an **App Password** from **Bitbucket Settings > App
Passwords** to authenticate the build status script setting commit build
@@ -49,104 +49,104 @@ To use GitLab CI/CD with a Bitbucket Cloud repository:
1. In GitLab, from **Settings > CI/CD > Environment variables**, add variables to allow
communication with Bitbucket via the Bitbucket API:
- `BITBUCKET_ACCESS_TOKEN`: the Bitbucket app password created above.
+ `BITBUCKET_ACCESS_TOKEN`: the Bitbucket app password created above.
- `BITBUCKET_USERNAME`: the username of the Bitbucket account.
+ `BITBUCKET_USERNAME`: the username of the Bitbucket account.
- `BITBUCKET_NAMESPACE`: set this if your GitLab and Bitbucket namespaces differ.
+ `BITBUCKET_NAMESPACE`: set this if your GitLab and Bitbucket namespaces differ.
- `BITBUCKET_REPOSITORY`: set this if your GitLab and Bitbucket project names differ.
+ `BITBUCKET_REPOSITORY`: set this if your GitLab and Bitbucket project names differ.
1. In Bitbucket, add a script to push the pipeline status to Bitbucket.
- > Note: changes made in GitLab will be overwritten by any changes made
- > upstream in Bitbucket.
-
- Create a file `build_status` and insert the script below and run
- `chmod +x build_status` in your terminal to make the script executable.
-
- ```bash
- #!/usr/bin/env bash
-
- # Push GitLab CI/CD build status to Bitbucket Cloud
-
- if [ -z "$BITBUCKET_ACCESS_TOKEN" ]; then
- echo "ERROR: BITBUCKET_ACCESS_TOKEN is not set"
- exit 1
- fi
- if [ -z "$BITBUCKET_USERNAME" ]; then
- echo "ERROR: BITBUCKET_USERNAME is not set"
- exit 1
- fi
- if [ -z "$BITBUCKET_NAMESPACE" ]; then
- echo "Setting BITBUCKET_NAMESPACE to $CI_PROJECT_NAMESPACE"
- BITBUCKET_NAMESPACE=$CI_PROJECT_NAMESPACE
- fi
- if [ -z "$BITBUCKET_REPOSITORY" ]; then
- echo "Setting BITBUCKET_REPOSITORY to $CI_PROJECT_NAME"
- BITBUCKET_REPOSITORY=$CI_PROJECT_NAME
- fi
-
- BITBUCKET_API_ROOT="https://api.bitbucket.org/2.0"
- BITBUCKET_STATUS_API="$BITBUCKET_API_ROOT/repositories/$BITBUCKET_NAMESPACE/$BITBUCKET_REPOSITORY/commit/$CI_COMMIT_SHA/statuses/build"
- BITBUCKET_KEY="ci/gitlab-ci/$CI_JOB_NAME"
-
- case "$BUILD_STATUS" in
- running)
- BITBUCKET_STATE="INPROGRESS"
- BITBUCKET_DESCRIPTION="The build is running!"
- ;;
- passed)
- BITBUCKET_STATE="SUCCESSFUL"
- BITBUCKET_DESCRIPTION="The build passed!"
- ;;
- failed)
- BITBUCKET_STATE="FAILED"
- BITBUCKET_DESCRIPTION="The build failed."
- ;;
- esac
-
- echo "Pushing status to $BITBUCKET_STATUS_API..."
- curl --request POST $BITBUCKET_STATUS_API \
- --user $BITBUCKET_USERNAME:$BITBUCKET_ACCESS_TOKEN \
- --header "Content-Type:application/json" \
- --silent \
- --data "{ \"state\": \"$BITBUCKET_STATE\", \"key\": \"$BITBUCKET_KEY\", \"description\":
- \"$BITBUCKET_DESCRIPTION\",\"url\": \"$CI_PROJECT_URL/-/jobs/$CI_JOB_ID\" }"
- ```
+ > Note: changes made in GitLab will be overwritten by any changes made
+ > upstream in Bitbucket.
+
+ Create a file `build_status` and insert the script below and run
+ `chmod +x build_status` in your terminal to make the script executable.
+
+ ```bash
+ #!/usr/bin/env bash
+
+ # Push GitLab CI/CD build status to Bitbucket Cloud
+
+ if [ -z "$BITBUCKET_ACCESS_TOKEN" ]; then
+ echo "ERROR: BITBUCKET_ACCESS_TOKEN is not set"
+ exit 1
+ fi
+ if [ -z "$BITBUCKET_USERNAME" ]; then
+ echo "ERROR: BITBUCKET_USERNAME is not set"
+ exit 1
+ fi
+ if [ -z "$BITBUCKET_NAMESPACE" ]; then
+ echo "Setting BITBUCKET_NAMESPACE to $CI_PROJECT_NAMESPACE"
+ BITBUCKET_NAMESPACE=$CI_PROJECT_NAMESPACE
+ fi
+ if [ -z "$BITBUCKET_REPOSITORY" ]; then
+ echo "Setting BITBUCKET_REPOSITORY to $CI_PROJECT_NAME"
+ BITBUCKET_REPOSITORY=$CI_PROJECT_NAME
+ fi
+
+ BITBUCKET_API_ROOT="https://api.bitbucket.org/2.0"
+ BITBUCKET_STATUS_API="$BITBUCKET_API_ROOT/repositories/$BITBUCKET_NAMESPACE/$BITBUCKET_REPOSITORY/commit/$CI_COMMIT_SHA/statuses/build"
+ BITBUCKET_KEY="ci/gitlab-ci/$CI_JOB_NAME"
+
+ case "$BUILD_STATUS" in
+ running)
+ BITBUCKET_STATE="INPROGRESS"
+ BITBUCKET_DESCRIPTION="The build is running!"
+ ;;
+ passed)
+ BITBUCKET_STATE="SUCCESSFUL"
+ BITBUCKET_DESCRIPTION="The build passed!"
+ ;;
+ failed)
+ BITBUCKET_STATE="FAILED"
+ BITBUCKET_DESCRIPTION="The build failed."
+ ;;
+ esac
+
+ echo "Pushing status to $BITBUCKET_STATUS_API..."
+ curl --request POST $BITBUCKET_STATUS_API \
+ --user $BITBUCKET_USERNAME:$BITBUCKET_ACCESS_TOKEN \
+ --header "Content-Type:application/json" \
+ --silent \
+ --data "{ \"state\": \"$BITBUCKET_STATE\", \"key\": \"$BITBUCKET_KEY\", \"description\":
+ \"$BITBUCKET_DESCRIPTION\",\"url\": \"$CI_PROJECT_URL/-/jobs/$CI_JOB_ID\" }"
+ ```
1. Still in Bitbucket, create a `.gitlab-ci.yml` file to use the script to push
pipeline success and failures to Bitbucket.
- ```yaml
- stages:
- - test
- - ci_status
-
- unit-tests:
- script:
- - echo "Success. Add your tests!"
-
- success:
- stage: ci_status
- before_script:
- - ""
- after_script:
- - ""
- script:
- - BUILD_STATUS=passed BUILD_KEY=push ./build_status
- when: on_success
-
- failure:
- stage: ci_status
- before_script:
- - ""
- after_script:
- - ""
- script:
- - BUILD_STATUS=failed BUILD_KEY=push ./build_status
- when: on_failure
- ```
+ ```yaml
+ stages:
+ - test
+ - ci_status
+
+ unit-tests:
+ script:
+ - echo "Success. Add your tests!"
+
+ success:
+ stage: ci_status
+ before_script:
+ - ""
+ after_script:
+ - ""
+ script:
+ - BUILD_STATUS=passed BUILD_KEY=push ./build_status
+ when: on_success
+
+ failure:
+ stage: ci_status
+ before_script:
+ - ""
+ after_script:
+ - ""
+ script:
+ - BUILD_STATUS=failed BUILD_KEY=push ./build_status
+ when: on_failure
+ ```
GitLab is now configured to mirror changes from Bitbucket, run CI/CD pipelines
configured in `.gitlab-ci.yml` and push the status to Bitbucket.
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 10a21edbd34..278a0d6e934 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -48,42 +48,42 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
1. During GitLab Runner installation select `shell` as method of executing job scripts or use command:
- ```bash
- sudo gitlab-runner register -n \
- --url https://gitlab.com/ \
- --registration-token REGISTRATION_TOKEN \
- --executor shell \
- --description "My Runner"
- ```
+ ```bash
+ sudo gitlab-runner register -n \
+ --url https://gitlab.com/ \
+ --registration-token REGISTRATION_TOKEN \
+ --executor shell \
+ --description "My Runner"
+ ```
1. Install Docker Engine on server.
- For more information how to install Docker Engine on different systems
- checkout the [Supported installations](https://docs.docker.com/engine/installation/).
+ For more information how to install Docker Engine on different systems
+ checkout the [Supported installations](https://docs.docker.com/engine/installation/).
1. Add `gitlab-runner` user to `docker` group:
- ```bash
- sudo usermod -aG docker gitlab-runner
- ```
+ ```bash
+ sudo usermod -aG docker gitlab-runner
+ ```
1. Verify that `gitlab-runner` has access to Docker:
- ```bash
- sudo -u gitlab-runner -H docker info
- ```
+ ```bash
+ sudo -u gitlab-runner -H docker info
+ ```
- You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml`:
+ You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml`:
- ```yaml
- before_script:
- - docker info
+ ```yaml
+ before_script:
+ - docker info
- build_image:
- script:
- - docker build -t my-docker-image .
- - docker run my-docker-image /script/to/run/tests
- ```
+ build_image:
+ script:
+ - docker build -t my-docker-image .
+ - docker run my-docker-image /script/to/run/tests
+ ```
1. You can now use `docker` command (and **install** `docker-compose` if needed).
@@ -107,83 +107,83 @@ In order to do that, follow the steps:
1. Register GitLab Runner from the command line to use `docker` and `privileged`
mode:
- ```bash
- sudo gitlab-runner register -n \
- --url https://gitlab.com/ \
- --registration-token REGISTRATION_TOKEN \
- --executor docker \
- --description "My Docker Runner" \
- --docker-image "docker:stable" \
- --docker-privileged
- ```
-
- The above command will register a new Runner to use the special
- `docker:stable` image which is provided by Docker. **Notice that it's using
- the `privileged` mode to start the build and service containers.** If you
- want to use [docker-in-docker] mode, you always have to use `privileged = true`
- in your Docker containers.
-
- DANGER: **Danger:**
- By enabling `--docker-privileged`, you are effectively disabling all of
- the security mechanisms of containers and exposing your host to privilege
- escalation which can lead to container breakout. For more information, check
- out the official Docker documentation on
- [Runtime privilege and Linux capabilities][docker-cap].
-
- The above command will create a `config.toml` entry similar to this:
-
- ```toml
- [[runners]]
- url = "https://gitlab.com/"
- token = TOKEN
- executor = "docker"
- [runners.docker]
- tls_verify = false
- image = "docker:stable"
- privileged = true
- disable_cache = false
- volumes = ["/cache"]
- [runners.cache]
- Insecure = false
- ```
+ ```bash
+ sudo gitlab-runner register -n \
+ --url https://gitlab.com/ \
+ --registration-token REGISTRATION_TOKEN \
+ --executor docker \
+ --description "My Docker Runner" \
+ --docker-image "docker:stable" \
+ --docker-privileged
+ ```
+
+ The above command will register a new Runner to use the special
+ `docker:stable` image which is provided by Docker. **Notice that it's using
+ the `privileged` mode to start the build and service containers.** If you
+ want to use [docker-in-docker] mode, you always have to use `privileged = true`
+ in your Docker containers.
+
+ DANGER: **Danger:**
+ By enabling `--docker-privileged`, you are effectively disabling all of
+ the security mechanisms of containers and exposing your host to privilege
+ escalation which can lead to container breakout. For more information, check
+ out the official Docker documentation on
+ [Runtime privilege and Linux capabilities][docker-cap].
+
+ The above command will create a `config.toml` entry similar to this:
+
+ ```toml
+ [[runners]]
+ url = "https://gitlab.com/"
+ token = TOKEN
+ executor = "docker"
+ [runners.docker]
+ tls_verify = false
+ image = "docker:stable"
+ privileged = true
+ disable_cache = false
+ volumes = ["/cache"]
+ [runners.cache]
+ Insecure = false
+ ```
1. You can now use `docker` in the build script (note the inclusion of the
`docker:dind` service):
- ```yaml
- image: docker:stable
-
- variables:
- # When using dind service we need to instruct docker, to talk with the
- # daemon started inside of the service. The daemon is available with
- # a network connection instead of the default /var/run/docker.sock socket.
- #
- # The 'docker' hostname is the alias of the service container as described at
- # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
- #
- # Note that if you're using the Kubernetes executor, the variable should be set to
- # tcp://localhost:2375/ because of how the Kubernetes executor connects services
- # to the job container
- # DOCKER_HOST: tcp://localhost:2375/
- #
- # For non-Kubernetes executors, we use tcp://docker:2375/
- DOCKER_HOST: tcp://docker:2375/
- # When using dind, it's wise to use the overlayfs driver for
- # improved performance.
- DOCKER_DRIVER: overlay2
-
- services:
- - docker:dind
-
- before_script:
- - docker info
-
- build:
- stage: build
- script:
- - docker build -t my-docker-image .
- - docker run my-docker-image /script/to/run/tests
- ```
+ ```yaml
+ image: docker:stable
+
+ variables:
+ # When using dind service we need to instruct docker, to talk with the
+ # daemon started inside of the service. The daemon is available with
+ # a network connection instead of the default /var/run/docker.sock socket.
+ #
+ # The 'docker' hostname is the alias of the service container as described at
+ # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services
+ #
+ # Note that if you're using the Kubernetes executor, the variable should be set to
+ # tcp://localhost:2375/ because of how the Kubernetes executor connects services
+ # to the job container
+ # DOCKER_HOST: tcp://localhost:2375/
+ #
+ # For non-Kubernetes executors, we use tcp://docker:2375/
+ DOCKER_HOST: tcp://docker:2375/
+ # When using dind, it's wise to use the overlayfs driver for
+ # improved performance.
+ DOCKER_DRIVER: overlay2
+
+ services:
+ - docker:dind
+
+ before_script:
+ - docker info
+
+ build:
+ stage: build
+ script:
+ - docker build -t my-docker-image .
+ - docker run my-docker-image /script/to/run/tests
+ ```
Docker-in-Docker works well, and is the recommended configuration, but it is
not without its own challenges:
@@ -202,14 +202,14 @@ not without its own challenges:
and use it as your mount point (for a more thorough explanation, check [issue
#41227](https://gitlab.com/gitlab-org/gitlab-ce/issues/41227)):
- ```yaml
- variables:
- MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt
+ ```yaml
+ variables:
+ MOUNT_POINT: /builds/$CI_PROJECT_PATH/mnt
- script:
- - mkdir -p "$MOUNT_POINT"
- - docker run -v "$MOUNT_POINT:/mnt" my-docker-image
- ```
+ script:
+ - mkdir -p "$MOUNT_POINT"
+ - docker run -v "$MOUNT_POINT:/mnt" my-docker-image
+ ```
An example project using this approach can be found here: <https://gitlab.com/gitlab-examples/docker>.
@@ -230,54 +230,54 @@ In order to do that, follow the steps:
1. Register GitLab Runner from the command line to use `docker` and share `/var/run/docker.sock`:
- ```bash
- sudo gitlab-runner register -n \
- --url https://gitlab.com/ \
- --registration-token REGISTRATION_TOKEN \
- --executor docker \
- --description "My Docker Runner" \
- --docker-image "docker:stable" \
- --docker-volumes /var/run/docker.sock:/var/run/docker.sock
- ```
-
- The above command will register a new Runner to use the special
- `docker:stable` image which is provided by Docker. **Notice that it's using
- the Docker daemon of the Runner itself, and any containers spawned by docker
- commands will be siblings of the Runner rather than children of the runner.**
- This may have complications and limitations that are unsuitable for your workflow.
-
- The above command will create a `config.toml` entry similar to this:
-
- ```toml
- [[runners]]
- url = "https://gitlab.com/"
- token = REGISTRATION_TOKEN
- executor = "docker"
- [runners.docker]
- tls_verify = false
- image = "docker:stable"
- privileged = false
- disable_cache = false
- volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
- [runners.cache]
- Insecure = false
- ```
+ ```bash
+ sudo gitlab-runner register -n \
+ --url https://gitlab.com/ \
+ --registration-token REGISTRATION_TOKEN \
+ --executor docker \
+ --description "My Docker Runner" \
+ --docker-image "docker:stable" \
+ --docker-volumes /var/run/docker.sock:/var/run/docker.sock
+ ```
+
+ The above command will register a new Runner to use the special
+ `docker:stable` image which is provided by Docker. **Notice that it's using
+ the Docker daemon of the Runner itself, and any containers spawned by docker
+ commands will be siblings of the Runner rather than children of the runner.**
+ This may have complications and limitations that are unsuitable for your workflow.
+
+ The above command will create a `config.toml` entry similar to this:
+
+ ```toml
+ [[runners]]
+ url = "https://gitlab.com/"
+ token = REGISTRATION_TOKEN
+ executor = "docker"
+ [runners.docker]
+ tls_verify = false
+ image = "docker:stable"
+ privileged = false
+ disable_cache = false
+ volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
+ [runners.cache]
+ Insecure = false
+ ```
1. You can now use `docker` in the build script (note that you don't need to
include the `docker:dind` service as when using the Docker in Docker executor):
- ```yaml
- image: docker:stable
+ ```yaml
+ image: docker:stable
- before_script:
- - docker info
+ before_script:
+ - docker info
- build:
- stage: build
- script:
- - docker build -t my-docker-image .
- - docker run my-docker-image /script/to/run/tests
- ```
+ build:
+ stage: build
+ script:
+ - docker build -t my-docker-image .
+ - docker run my-docker-image /script/to/run/tests
+ ```
While the above method avoids using Docker in privileged mode, you should be
aware of the following implications:
@@ -293,9 +293,9 @@ aware of the following implications:
work as expected since volume mounting is done in the context of the host
machine, not the build container. For example:
- ```sh
- docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
- ```
+ ```sh
+ docker run --rm -t -i -v $(pwd)/src:/home/app/src test-image:latest run_app_tests
+ ```
## Making docker-in-docker builds faster with Docker layer caching
@@ -366,23 +366,23 @@ which can be avoided if a different driver is used, for example `overlay2`.
1. Make sure a recent kernel is used, preferably `>= 4.2`.
1. Check whether the `overlay` module is loaded:
- ```sh
- sudo lsmod | grep overlay
- ```
+ ```sh
+ sudo lsmod | grep overlay
+ ```
- If you see no result, then it isn't loaded. To load it use:
+ If you see no result, then it isn't loaded. To load it use:
- ```sh
- sudo modprobe overlay
- ```
+ ```sh
+ sudo modprobe overlay
+ ```
- If everything went fine, you need to make sure module is loaded on reboot.
- On Ubuntu systems, this is done by editing `/etc/modules`. Just add the
- following line into it:
+ If everything went fine, you need to make sure module is loaded on reboot.
+ On Ubuntu systems, this is done by editing `/etc/modules`. Just add the
+ following line into it:
- ```text
- overlay
- ```
+ ```text
+ overlay
+ ```
### Use driver per project
@@ -450,9 +450,9 @@ For all projects, mostly suitable for public ones:
your Docker images and has read/write access to the Registry. This is ephemeral,
so it's only valid for one job. You can use the following example as-is:
- ```sh
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- ```
+ ```sh
+ docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+ ```
For private and internal projects:
@@ -465,9 +465,9 @@ For private and internal projects:
Replace the `<username>` and `<access_token>` in the following example:
- ```sh
- docker login -u <username> -p <access_token> $CI_REGISTRY
- ```
+ ```sh
+ docker login -u <username> -p <access_token> $CI_REGISTRY
+ ```
- **Using the GitLab Deploy Token**: You can create and use a
[special deploy token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token)
@@ -475,9 +475,9 @@ For private and internal projects:
Once created, you can use the special environment variables, and GitLab CI/CD
will fill them in for you. You can use the following example as-is:
- ```sh
- docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
- ```
+ ```sh
+ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
+ ```
### Container Registry examples
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index f3896c5232c..d5056568dff 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -305,25 +305,25 @@ For example, the following two definitions are equal:
1. Using a string as an option to `image` and `services`:
- ```yaml
- image: "registry.example.com/my/image:latest"
+ ```yaml
+ image: "registry.example.com/my/image:latest"
- services:
- - postgresql:9.4
- - redis:latest
- ```
+ services:
+ - postgresql:9.4
+ - redis:latest
+ ```
1. Using a map as an option to `image` and `services`. The use of `image:name` is
required:
- ```yaml
- image:
- name: "registry.example.com/my/image:latest"
+ ```yaml
+ image:
+ name: "registry.example.com/my/image:latest"
- services:
- - name: postgresql:9.4
- - name: redis:latest
- ```
+ services:
+ - name: postgresql:9.4
+ - name: redis:latest
+ ```
### Available settings for `image`
@@ -526,6 +526,7 @@ it's provided as an environment variable. This is because GitLab Runnner uses **
runtime.
### Using statically-defined credentials
+
There are two approaches that you can take in order to access a
private registry. Both require setting the environment variable
`DOCKER_AUTH_CONFIG` with appropriate authentication info.
@@ -555,18 +556,18 @@ There are two ways to determine the value of `DOCKER_AUTH_CONFIG`:
- **First way -** Do a `docker login` on your local machine:
- ```bash
- docker login registry.example.com:5000 --username my_username --password my_password
- ```
+ ```bash
+ docker login registry.example.com:5000 --username my_username --password my_password
+ ```
- Then copy the content of `~/.docker/config.json`.
+ Then copy the content of `~/.docker/config.json`.
- If you don't need access to the registry from your computer, you
- can do a `docker logout`:
+ If you don't need access to the registry from your computer, you
+ can do a `docker logout`:
- ```bash
- docker logout registry.example.com:5000
- ```
+ ```bash
+ docker logout registry.example.com:5000
+ ```
- **Second way -** In some setups, it's possible that Docker client
will use the available system keystore to store the result of `docker
@@ -575,12 +576,12 @@ There are two ways to determine the value of `DOCKER_AUTH_CONFIG`:
`${username}:${password}` manually. Open a terminal and execute the
following command:
- ```bash
- echo -n "my_username:my_password" | base64
+ ```bash
+ echo -n "my_username:my_password" | base64
- # Example output to copy
- bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
- ```
+ # Example output to copy
+ bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
+ ```
#### Configuring a job
@@ -590,25 +591,25 @@ follow these steps:
1. Create a [variable](../variables/README.md#gitlab-cicd-environment-variables) `DOCKER_AUTH_CONFIG` with the content of the
Docker configuration file as the value:
- ```json
- {
- "auths": {
- "registry.example.com:5000": {
- "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
- }
- }
- }
- ```
+ ```json
+ {
+ "auths": {
+ "registry.example.com:5000": {
+ "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
+ }
+ }
+ }
+ ```
1. You can now use any private image from `registry.example.com:5000` defined in
`image` and/or `services` in your `.gitlab-ci.yml` file:
- ```yaml
- image: registry.example.com:5000/namespace/image:tag
- ```
+ ```yaml
+ image: registry.example.com:5000/namespace/image:tag
+ ```
- In the example above, GitLab Runner will look at `registry.example.com:5000` for the
- image `namespace/image:tag`.
+ In the example above, GitLab Runner will look at `registry.example.com:5000` for the
+ image `namespace/image:tag`.
You can add configuration for as many registries as you want, adding more
registries to the `"auths"` hash as described above.
@@ -637,10 +638,10 @@ To add `DOCKER_AUTH_CONFIG` to a Runner:
1. Modify the Runner's `config.toml` file as follows:
- ```toml
- [[runners]]
- environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
- ```
+ ```toml
+ [[runners]]
+ environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
+ ```
1. Restart the Runner service.
@@ -662,16 +663,17 @@ To configure credentials store, follow these steps:
Make sure helper program is available in GitLab Runner `$PATH`.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
+
- Create a
[variable](../variables/README.md#gitlab-cicd-environment-variables)
`DOCKER_AUTH_CONFIG` with the content of the
- Docker configuration file as the value:
+ Docker configuration file as the value:
- ```json
- {
- "credsStore": "osxkeychain"
- }
- ```
+ ```json
+ {
+ "credsStore": "osxkeychain"
+ }
+ ```
- Or, if you are running self-hosted Runners, add the above JSON to
`${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner will read this config file
@@ -693,17 +695,18 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
1. Make sure `docker-credential-ecr-login` is available in GitLab Runner's `$PATH`.
1. Make GitLab Runner use it. There are two ways to accomplish this. Either:
+
- Create a [variable](../variables/README.md#gitlab-cicd-environment-variables)
`DOCKER_AUTH_CONFIG` with the content of the
- Docker configuration file as the value:
+ Docker configuration file as the value:
- ```json
- {
- "credHelpers": {
- "aws_account_id.dkr.ecr.region.amazonaws.com": "ecr-login"
- }
- }
- ```
+ ```json
+ {
+ "credHelpers": {
+ "aws_account_id.dkr.ecr.region.amazonaws.com": "ecr-login"
+ }
+ }
+ ```
- Or, if you are running self-hosted Runners,
add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`.
@@ -713,12 +716,12 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th
1. You can now use any private image from `aws_account_id.dkr.ecr.region.amazonaws.com` defined in
`image` and/or `services` in your `.gitlab-ci.yml` file:
- ```yaml
- image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest
- ```
+ ```yaml
+ image: aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest
+ ```
- In the example above, GitLab Runner will look at `aws_account_id.dkr.ecr.region.amazonaws.com` for the
- image `private/image:latest`.
+ In the example above, GitLab Runner will look at `aws_account_id.dkr.ecr.region.amazonaws.com` for the
+ image `private/image:latest`.
You can add configuration for as many registries as you want, adding more
registries to the `"credHelpers"` hash as described above.
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index c9f700ed190..940c4711132 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -39,9 +39,10 @@ project:
1. Create a new project by selecting **Import project from ➔ Repo by URL**
1. Add the following URL:
- ```
- https://gitlab.com/gitlab-examples/maven/simple-maven-dep.git
- ```
+ ```
+ https://gitlab.com/gitlab-examples/maven/simple-maven-dep.git
+ ```
+
1. Click **Create project**
This application is nothing more than a basic class with a stub for a JUnit based test suite.
@@ -63,15 +64,15 @@ The application is ready to use, but you need some additional steps to deploy it
1. Copy the snippet in the `pom.xml` file for your project, just after the
`dependencies` section. The snippet should look like this:
- ```xml
- <distributionManagement>
- <repository>
- <id>central</id>
- <name>83d43b5afeb5-releases</name>
- <url>${env.MAVEN_REPO_URL}/libs-release-local</url>
- </repository>
- </distributionManagement>
- ```
+ ```xml
+ <distributionManagement>
+ <repository>
+ <id>central</id>
+ <name>83d43b5afeb5-releases</name>
+ <url>${env.MAVEN_REPO_URL}/libs-release-local</url>
+ </repository>
+ </distributionManagement>
+ ```
Another step you need to do before you can deploy the dependency to Artifactory
is to configure the authentication data. It is a simple task, but Maven requires
@@ -86,18 +87,18 @@ parameter in `.gitlab-ci.yml` to use the custom location instead of the default
1. Create a file called `settings.xml` in the `.m2` folder
1. Copy the following content into a `settings.xml` file:
- ```xml
- <settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd"
- xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <servers>
- <server>
- <id>central</id>
- <username>${env.MAVEN_REPO_USER}</username>
- <password>${env.MAVEN_REPO_PASS}</password>
- </server>
- </servers>
- </settings>
- ```
+ ```xml
+ <settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd"
+ xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <servers>
+ <server>
+ <id>central</id>
+ <username>${env.MAVEN_REPO_USER}</username>
+ <password>${env.MAVEN_REPO_PASS}</password>
+ </server>
+ </servers>
+ </settings>
+ ```
Username and password will be replaced by the correct values using variables.
@@ -187,9 +188,10 @@ We'll use again a Maven app that can be cloned from our example project:
1. Create a new project by selecting **Import project from ➔ Repo by URL**
1. Add the following URL:
- ```
- https://gitlab.com/gitlab-examples/maven/simple-maven-app.git
- ```
+ ```
+ https://gitlab.com/gitlab-examples/maven/simple-maven-app.git
+ ```
+
1. Click **Create project**
This one is a simple app as well. If you look at the `src/main/java/com/example/app/App.java`
@@ -204,13 +206,13 @@ Since Maven doesn't know how to resolve the dependency, you need to modify the c
1. Copy the snippet in the `dependencies` section of the `pom.xml` file.
The snippet should look like this:
- ```xml
- <dependency>
- <groupId>com.example.dep</groupId>
- <artifactId>simple-maven-dep</artifactId>
- <version>1.0</version>
- </dependency>
- ```
+ ```xml
+ <dependency>
+ <groupId>com.example.dep</groupId>
+ <artifactId>simple-maven-dep</artifactId>
+ <version>1.0</version>
+ </dependency>
+ ```
### Configure the Artifactory repository location
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
index a5fed00972f..0e595e1a0be 100644
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
@@ -188,28 +188,27 @@ when running our Phoenix in our `localhost`.
- Open `hello_gitlab_ci/config/test.exs` on your favorite code editor
- Go to **Configure your database** session and edit the block to include `System.get_env`:
- ```elixir
- # Configure your database
- config :hello_gitlab_ci, HelloGitlabCi.Repo,
- adapter: Ecto.Adapters.Postgres,
- username: System.get_env("POSTGRES_USER") || "postgres",
- password: System.get_env("POSTGRES_PASSWORD") || "postgres",
- database: System.get_env("POSTGRES_DB") || "hello_gitlab_ci_test",
- hostname: System.get_env("POSTGRES_HOST") || "localhost",
- pool: Ecto.Adapters.SQL.Sandbox
- ```
-
- We'll need these system variables later on.
+ ```elixir
+ # Configure your database
+ config :hello_gitlab_ci, HelloGitlabCi.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: System.get_env("POSTGRES_USER") || "postgres",
+ password: System.get_env("POSTGRES_PASSWORD") || "postgres",
+ database: System.get_env("POSTGRES_DB") || "hello_gitlab_ci_test",
+ hostname: System.get_env("POSTGRES_HOST") || "localhost",
+ pool: Ecto.Adapters.SQL.Sandbox
+ ```
+
+ We'll need these system variables later on.
- Create an empty file named `.gitkeep` into `hello_gitlab_ci/priv/repo/migrations`
- As our project is still fresh, we don't have any data on our database, so, the `migrations`
-directory will be empty.
- Without `.gitkeep`, git will not upload this empty directory and we'll got an error when running our
-test on GitLab.
+ As our project is still fresh, we don't have any data on our database, so, the `migrations`
+ directory will be empty.
+ Without `.gitkeep`, git will not upload this empty directory and we'll got an error when running our
+ test on GitLab.
- > **Note:**
- If we add a folder via the GitLab UI, GitLab itself will add the `.gitkeep` to that new dir.
+ > **Note:** If we add a folder via the GitLab UI, GitLab itself will add the `.gitkeep` to that new dir.
Now, let's run a local test and see if everything we did didn't break anything.
@@ -248,64 +247,64 @@ project.
- The fastest and easiest way to do this, is to click on **Set up CI** on project's main page:
- ![Set up CI](img/setup-ci.png)
+ ![Set up CI](img/setup-ci.png)
- On next screen, we can select a template ready to go. Click on **Apply a GitLab CI/CD Yaml
template** and select **Elixir**:
- ![Select template](img/select-template.png)
+ ![Select template](img/select-template.png)
- This template file tells GitLab CI/CD about what we wish to do every time a new commit is made.
- However, we have to adapt it to run a Phoenix app.
+ This template file tells GitLab CI/CD about what we wish to do every time a new commit is made.
+ However, we have to adapt it to run a Phoenix app.
- The first line tells GitLab what Docker image will be used.
- Remember when we learn about Runners, the isolated virtual machine where GitLab CI/CD build and test
- our application? This virtual machine must have all dependencies to run our application. This is
- where a Docker image is needed. The correct image will provide the entire system for us.
+ Remember when we learn about Runners, the isolated virtual machine where GitLab CI/CD build and test
+ our application? This virtual machine must have all dependencies to run our application. This is
+ where a Docker image is needed. The correct image will provide the entire system for us.
- As a suggestion, you can use [trenpixster's elixir image][docker-image], which already has all
- dependencies for Phoenix installed, such as Elixir, Erlang, NodeJS and PostgreSQL:
+ As a suggestion, you can use [trenpixster's elixir image][docker-image], which already has all
+ dependencies for Phoenix installed, such as Elixir, Erlang, NodeJS and PostgreSQL:
- ```yml
- image: trenpixster/elixir:latest
- ```
+ ```yml
+ image: trenpixster/elixir:latest
+ ```
- At `services` session, we'll only use `postgres`, so we'll delete `mysql` and `redis` lines:
- ```yml
- services:
- - postgres:latest
- ```
+ ```yml
+ services:
+ - postgres:latest
+ ```
- Now, we'll create a new entry called `variables`, before `before_script` session:
- ```yml
- variables:
- POSTGRES_DB: hello_gitlab_ci_test
- POSTGRES_HOST: postgres
- POSTGRES_USER: postgres
- POSTGRES_PASSWORD: "postgres"
- MIX_ENV: "test"
- ```
+ ```yml
+ variables:
+ POSTGRES_DB: hello_gitlab_ci_test
+ POSTGRES_HOST: postgres
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: "postgres"
+ MIX_ENV: "test"
+ ```
- Here, we are setting up the values for GitLab CI/CD authenticate into PostgreSQL, as we did on
- `config/test.exs` earlier.
+ Here, we are setting up the values for GitLab CI/CD authenticate into PostgreSQL, as we did on
+ `config/test.exs` earlier.
- In `before_script` session, we'll add some commands to prepare everything to the test:
- ```yml
- before_script:
- - apt-get update && apt-get -y install postgresql-client
- - mix local.hex --force
- - mix deps.get --only test
- - mix ecto.create
- - mix ecto.migrate
- ```
-
- It's important to install `postgresql-client` to let GitLab CI/CD access PostgreSQL and create our
- database with the login information provided earlier. More important is to respect the indentation,
- to avoid syntax errors when running the build.
+ ```yml
+ before_script:
+ - apt-get update && apt-get -y install postgresql-client
+ - mix local.hex --force
+ - mix deps.get --only test
+ - mix ecto.create
+ - mix ecto.migrate
+ ```
+
+ It's important to install `postgresql-client` to let GitLab CI/CD access PostgreSQL and create our
+ database with the login information provided earlier. More important is to respect the indentation,
+ to avoid syntax errors when running the build.
- And finally, we'll let `mix` session intact.
diff --git a/doc/ci/ssh_keys/README.md b/doc/ci/ssh_keys/README.md
index 69591ed605c..d9f022a7125 100644
--- a/doc/ci/ssh_keys/README.md
+++ b/doc/ci/ssh_keys/README.md
@@ -57,44 +57,44 @@ to access it. This is where an SSH key pair comes in handy.
1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following
example, a Debian based image is assumed. Edit to your needs:
- ```yaml
- before_script:
- ##
- ## Install ssh-agent if not already installed, it is required by Docker.
- ## (change apt-get to yum if you use an RPM-based image)
- ##
- - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
-
- ##
- ## Run ssh-agent (inside the build environment)
- ##
- - eval $(ssh-agent -s)
-
- ##
- ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
- ## We're using tr to fix line endings which makes ed25519 keys work
- ## without extra base64 encoding.
- ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
- ##
- - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
-
- ##
- ## Create the SSH directory and give it the right permissions
- ##
- - mkdir -p ~/.ssh
- - chmod 700 ~/.ssh
-
- ##
- ## Optionally, if you will be using any Git commands, set the user name and
- ## and email.
- ##
- #- git config --global user.email "user@example.com"
- #- git config --global user.name "User name"
- ```
-
- NOTE: **Note:**
- The [`before_script`](../yaml/README.md#before_script-and-after_script) can be set globally
- or per-job.
+ ```yaml
+ before_script:
+ ##
+ ## Install ssh-agent if not already installed, it is required by Docker.
+ ## (change apt-get to yum if you use an RPM-based image)
+ ##
+ - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
+
+ ##
+ ## Run ssh-agent (inside the build environment)
+ ##
+ - eval $(ssh-agent -s)
+
+ ##
+ ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
+ ## We're using tr to fix line endings which makes ed25519 keys work
+ ## without extra base64 encoding.
+ ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
+ ##
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
+
+ ##
+ ## Create the SSH directory and give it the right permissions
+ ##
+ - mkdir -p ~/.ssh
+ - chmod 700 ~/.ssh
+
+ ##
+ ## Optionally, if you will be using any Git commands, set the user name and
+ ## and email.
+ ##
+ #- git config --global user.email "user@example.com"
+ #- git config --global user.name "User name"
+ ```
+
+ NOTE: **Note:**
+ The [`before_script`](../yaml/README.md#before_script-and-after_script) can be set globally
+ or per-job.
1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).
@@ -118,9 +118,9 @@ on, and use that key for all projects that are run on this machine.
1. Then from the terminal login as the `gitlab-runner` user:
- ```
- sudo su - gitlab-runner
- ```
+ ```
+ sudo su - gitlab-runner
+ ```
1. Generate the SSH key pair as described in the instructions to
[generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 4d6ca8cff6d..c48817a5e30 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -370,8 +370,11 @@ variables take precedence over those defined in `.gitlab-ci.yml`.
## Unsupported variables
There are cases where some variables cannot be used in the context of a
-`.gitlab-ci.yml` definition (for example under `script`). Read more
-about which variables are [not supported](where_variables_can_be_used.md).
+`.gitlab-ci.yml` definition (for example under `script`). Read more about which variables are [not supported](where_variables_can_be_used.md).
+
+## Where variables can be used
+
+Click [here](where_variables_can_be_used.md) for a section that describes where and how the different types of variables can be used.
## Advanced use
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 201047b70b9..a6051e87366 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -2468,20 +2468,20 @@ There are three possible values: `none`, `normal`, and `recursive`:
- `normal` means that only the top-level submodules will be included. It is
equivalent to:
- ```
- git submodule sync
- git submodule update --init
- ```
+ ```
+ git submodule sync
+ git submodule update --init
+ ```
- `recursive` means that all submodules (including submodules of submodules)
will be included. This feature needs Git v1.8.1 and later. When using a
GitLab Runner with an executor not based on Docker, make sure the Git version
meets that requirement. It is equivalent to:
- ```
- git submodule sync --recursive
- git submodule update --init --recursive
- ```
+ ```
+ git submodule sync --recursive
+ git submodule update --init --recursive
+ ```
Note that for this feature to work correctly, the submodules must be configured
(in `.gitmodules`) with either:
diff --git a/doc/development/fe_guide/event_tracking.md b/doc/development/fe_guide/event_tracking.md
index 716f6ad7f92..1e6287d8f6d 100644
--- a/doc/development/fe_guide/event_tracking.md
+++ b/doc/development/fe_guide/event_tracking.md
@@ -1,79 +1,76 @@
# Event Tracking
-We use [Snowplow](https://github.com/snowplow/snowplow) for tracking custom events (available in GitLab [Enterprise Edition](https://about.gitlab.com/pricing/) only).
+We use a tracking interface that wraps up [Snowplow](https://github.com/snowplow/snowplow) for tracking custom events. Snowplow implements page tracking, but also exposes custom event tracking.
-## Generic tracking function
-
-In addition to Snowplow's built-in method for tracking page views, we use a generic tracking function which enables us to selectively apply listeners to events.
-
-The generic tracking function can be imported in EE-specific JS files as follows:
+The tracking interface can be imported in JS files as follows:
```javascript
-import { trackEvent } from `ee/stats`;
+import Tracking from `~/tracking`;
```
-This gives the user access to the `trackEvent` method, which takes the following parameters:
+## Tracking in HAML or Vue templates
-| parameter | type | description | required |
-| ---------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
-| `category` | string | Describes the page that you're capturing click events on. Unless infeasible, please use the Rails page attribute `document.body.dataset.page` by default. | true |
-| `eventName` | string | Describes the action the user is taking. The first word should always describe the action. For example, clicks should be `click` and activations should be `activate`. Use underscores to describe what was acted on. For example, activating a form field would be `activate_form_input`. Clicking on a dropdown is `click_dropdown`. | true |
-| `additionalData` | object | Additional data such as `label`, `property`, and `value` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy). | false |
+To avoid having to do create a bunch of custom javascript event handlers, when working within HAML or Vue templates, we can add `data-track-*` attributes to elements of interest. This way, all elements that have a `data-track-event` attribute to automatically have event tracking bound.
-Read more about instrumentation and the taxonomy in the [Product Handbook](https://about.gitlab.com/handbook/product/feature-instrumentation).
-
-### Tracking in `.js` and `.vue` files
+Below is an example of `data-track-*` attributes assigned to a button in HAML:
-The most simple use case is to add tracking programmatically to an event of interest in Javascript.
+```haml
+%button.btn{ data: { track_event: "click_button", track_label: "template_preview", track_property: "my-template", track_value: "" } }
+```
-The following example demonstrates how to track a click on a button in Javascript by calling the `trackEvent` method explicitly:
+We can then setup tracking for large sections of a page, or an entire page by telling the Tracking interface to bind to it.
```javascript
-import { trackEvent } from `ee/stats`;
+import Tracking from '~/tracking';
-trackEvent('dashboard:projects:index', 'click_button', {
- label: 'create_from_template',
- property: 'template_preview',
- value: 'rails',
+// for the entire document
+new Tracking().bind();
+
+// for a container element
+document.addEventListener('DOMContentLoaded', () => {
+ new Tracking('my_category').bind(document.getElementById('my-container'));
});
+
```
-### Tracking in HAML templates
+When you instantiate a Tracking instance you can provide a category. If none is provided, `document.body.dataset.page` will be used. When you bind the Tracking instance you can provide an element. If no element is provided to bind to, the `document` is assumed.
-Sometimes we want to track clicks for multiple elements on a page. Creating event handlers for all elements could soon turn into a tedious task.
+Below is a list of supported `data-track-*` attributes:
-There's a more convenient solution to this problem. When working with HAML templates, we can add `data-track-*` attributes to elements of interest. This way, all elements that have both `data-track-label` and `data-track-event` attributes assigned get marked for event tracking. All we have to do is call the `bindTrackableContainer` method on a container which allows for better scoping.
+| attribute | required | description |
+|:----------------------|:---------|:------------|
+| `data-track-event` | true | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
+| `data-track-label` | false | The `label` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy) |
+| `data-track-property` | false | The `property` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy)
+| `data-track-value` | false | The `value` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy). If omitted, this will be the elements `value` property or an empty string. For checkboxes, the default value will be the element's checked attribute or `false` when unchecked.
-Below is an example of `data-track-*` attributes assigned to a button in HAML:
-```ruby
-%button.btn{ data: { track_label: "template_preview", track_property: "my-template", track_event: "click_button", track_value: "" } }
-```
-
-By calling `bindTrackableContainer('.my-container')`, click handlers get bound to all elements located in `.my-container` provided that they have the necessary `data-track-*` attributes assigned to them.
+## Tracking in raw Javascript
-```javascript
-import Stats from 'ee/stats';
+Custom events can be tracked by directly calling the `Tracking.event` static function, which accepts the following arguments:
-document.addEventListener('DOMContentLoaded', () => {
- Stats.bindTrackableContainer('.my-container', 'category');
-});
-```
+| argument | type | default value | description |
+|:-----------|:-------|:---------------------------|:------------|
+| `category` | string | document.body.dataset.page | Page or subsection of a page that events are being captured within. |
+| `event` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. |
+| `data` | object | {} | Additional data such as `label`, `property`, and `value` as described [in our Feature Instrumentation taxonomy](https://about.gitlab.com/handbook/product/feature-instrumentation/#taxonomy). These will be set as empty strings if you don't provide them. |
-The second parameter in `bindTrackableContainer` is optional. If omitted, the value of `document.body.dataset.page` will be used as category instead.
+Tracking can be programmatically added to an event of interest in Javascript, and the following example demonstrates tracking a click on a button by calling `Tracking.event` manually.
-Below is a list of supported `data-track-*` attributes:
+```javascript
+import Tracking from `~/tracking`;
-| attribute | description | required |
-| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
-| `data-track-label` | The `label` in `trackEvent` | true |
-| `data-track-event` | The `eventName` in `trackEvent` | true |
-| `data-track-property` | The `property` in `trackEvent`. If omitted, an empty string will be used as a default value. | false |
-| `data-track-value` | The `value` in `trackEvent`. If omitted, this will be `target.value` or empty string. For checkboxes, the default value being tracked will be the element's checked attribute if `data-track-value` is omitted. | false |
+document.getElementById('my_button').addEventListener('click', () => {
+ Tracking.event('dashboard:projects:index', 'click_button', {
+ label: 'create_from_template',
+ property: 'template_preview',
+ value: 'rails',
+ });
+})
+```
-Since Snowplow is an Enterprise Edition feature, it's necessary to create a CE backport when adding `data-track-*` attributes to HAML templates in most cases.
-## Testing
+## Toggling tracking on or off
Snowplow can be enabled by navigating to:
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 46ee980841b..a12edef4e41 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -938,7 +938,7 @@ To use GitLab with Puma:
cd /home/git/gitlab
# Copy config file for the web server
- sudo -u git -H config/puma.rb.example config/puma.rb
+ sudo -u git -H cp config/puma.rb.example config/puma.rb
```
1. Edit the system `init.d` script to use `EXPERIMENTAL_PUMA=1` flag. If you have `/etc/default/gitlab`, then you should edit it instead.
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 1687a3aee72..63a72f8f193 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -1069,6 +1069,12 @@ Container Registry. **Restarting a pod, scaling a service, or other actions whic
require on-going access to the registry may fail**. On-going secure access is
planned for a subsequent release.
+### Private registry support
+
+There is no documented way of using private container registry with Auto DevOps.
+We strongly advise using GitLab Container Registry with Auto DevOps in order to
+simplify configuration and prevent any unforeseen issues.
+
## Troubleshooting
- Auto Build and Auto Test may fail in detecting your language/framework. There
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 88e2d1ef22b..fa84f995e58 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -7,6 +7,11 @@ type: reference, howto
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/4348)
in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
+NOTE: **4 of the top 6 attacks were application based.**
+Download our whitepaper,
+["A Seismic Shift in Application Security"](https://about.gitlab.com/resources/whitepaper-seismic-shift-application-security/)
+to learn how to protect your organization.
+
Running [static checks](../sast/index.md) on your code is the first step to detect
vulnerabilities that can put the security of your code at risk. Yet, once
deployed, your application is exposed to a new category of possible attacks,
diff --git a/doc/user/project/img/key_value_labels.png b/doc/user/project/img/key_value_labels.png
deleted file mode 100644
index bec901f127f..00000000000
--- a/doc/user/project/img/key_value_labels.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_default.png b/doc/user/project/img/labels_default.png
deleted file mode 100644
index 221c5cf55a2..00000000000
--- a/doc/user/project/img/labels_default.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_default_v12_1.png b/doc/user/project/img/labels_default_v12_1.png
new file mode 100644
index 00000000000..4a0a6ba9ce0
--- /dev/null
+++ b/doc/user/project/img/labels_default_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_delete_v12_1.png b/doc/user/project/img/labels_delete_v12_1.png
new file mode 100644
index 00000000000..2e0ea934519
--- /dev/null
+++ b/doc/user/project/img/labels_delete_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_drag_priority_v12_1.gif b/doc/user/project/img/labels_drag_priority_v12_1.gif
new file mode 100644
index 00000000000..a568490da5f
--- /dev/null
+++ b/doc/user/project/img/labels_drag_priority_v12_1.gif
Binary files differ
diff --git a/doc/user/project/img/labels_epic_sidebar.png b/doc/user/project/img/labels_epic_sidebar.png
deleted file mode 100644
index f8162d89e9d..00000000000
--- a/doc/user/project/img/labels_epic_sidebar.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_epic_sidebar_v12_1.png b/doc/user/project/img/labels_epic_sidebar_v12_1.png
new file mode 100644
index 00000000000..7e05c6d1ce4
--- /dev/null
+++ b/doc/user/project/img/labels_epic_sidebar_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_generate_default.png b/doc/user/project/img/labels_generate_default.png
deleted file mode 100644
index 982a4df999c..00000000000
--- a/doc/user/project/img/labels_generate_default.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_generate_default_v12_1.png b/doc/user/project/img/labels_generate_default_v12_1.png
new file mode 100644
index 00000000000..48adc9a5699
--- /dev/null
+++ b/doc/user/project/img/labels_generate_default_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_group_issues.png b/doc/user/project/img/labels_group_issues.png
deleted file mode 100644
index cea1d304d31..00000000000
--- a/doc/user/project/img/labels_group_issues.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_group_issues_v12_1.png b/doc/user/project/img/labels_group_issues_v12_1.png
new file mode 100644
index 00000000000..bfe425f20ac
--- /dev/null
+++ b/doc/user/project/img/labels_group_issues_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_key_value_v12_1.png b/doc/user/project/img/labels_key_value_v12_1.png
new file mode 100644
index 00000000000..81d5c416c95
--- /dev/null
+++ b/doc/user/project/img/labels_key_value_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_list.png b/doc/user/project/img/labels_list.png
deleted file mode 100644
index 6940dde68bf..00000000000
--- a/doc/user/project/img/labels_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_list_v12_1.png b/doc/user/project/img/labels_list_v12_1.png
new file mode 100644
index 00000000000..c414ab42fbc
--- /dev/null
+++ b/doc/user/project/img/labels_list_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/new_label_from_sidebar.gif b/doc/user/project/img/labels_new_label_from_sidebar.gif
index 572b29a86e1..572b29a86e1 100644
--- a/doc/user/project/img/new_label_from_sidebar.gif
+++ b/doc/user/project/img/labels_new_label_from_sidebar.gif
Binary files differ
diff --git a/doc/user/project/img/labels_prioritized.png b/doc/user/project/img/labels_prioritized.png
deleted file mode 100644
index 7ce2d08b38c..00000000000
--- a/doc/user/project/img/labels_prioritized.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_prioritized_v12_1.png b/doc/user/project/img/labels_prioritized_v12_1.png
new file mode 100644
index 00000000000..8ea69949d8e
--- /dev/null
+++ b/doc/user/project/img/labels_prioritized_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_promotion.png b/doc/user/project/img/labels_promotion.png
deleted file mode 100644
index 762a3773692..00000000000
--- a/doc/user/project/img/labels_promotion.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_promotion_v12_1.png b/doc/user/project/img/labels_promotion_v12_1.png
new file mode 100644
index 00000000000..238d50981ae
--- /dev/null
+++ b/doc/user/project/img/labels_promotion_v12_1.png
Binary files differ
diff --git a/doc/user/project/img/labels_subscriptions.png b/doc/user/project/img/labels_subscriptions.png
deleted file mode 100644
index f3c4235d051..00000000000
--- a/doc/user/project/img/labels_subscriptions.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/labels_subscriptions_v12_1.png b/doc/user/project/img/labels_subscriptions_v12_1.png
new file mode 100644
index 00000000000..57c437ac8a4
--- /dev/null
+++ b/doc/user/project/img/labels_subscriptions_v12_1.png
Binary files differ
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index fdfeb4aa4cd..a00c1c980d2 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -2,43 +2,52 @@
## Overview
-Labels allow you to categorize issues or merge requests using descriptive titles like `bug`, `feature request`, or `docs`. Each label also has a customizable color. They allow you to quickly and dynamically filter and manage issues or merge requests you care about, and are visible throughout GitLab in most places where issues and merge requests are located.
+Labels allow you to categorize issues or merge requests using descriptive titles like
+`bug`, `feature request`, or `docs`. Each label also has a customizable color. They
+allow you to quickly and dynamically filter and manage issues or merge requests you
+care about, and are visible throughout GitLab in most places where issues and merge
+requests are located.
## Project labels and group labels
In GitLab, you can create project and group labels:
- **Project labels** can be assigned to issues or merge requests in that project only.
-- **Group labels** can be assigned to any issue or merge request of any project in that group or any subgroups of the group.
+- **Group labels** can be assigned to any issue or merge request in any project in
+ that group, or any subgroups of the group.
## Scoped labels **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9175) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.10.
-Scoped labels allow teams to use the simple and familiar feature of labels to
+Scoped labels allow teams to use the simple and familiar label feature to
annotate their issues, merge requests, and epics to achieve custom fields and
custom workflow states by leveraging a special label title syntax.
-A scoped label is a kind of label defined only by a special double-colon syntax
+A scoped label is a kind of label defined by a special double-colon syntax
in the label’s title, using the format `key::value`. For example:
-![A sample scoped label](img/key_value_labels.png)
+![A sample scoped label](img/labels_key_value_v12_1.png)
An issue, epic, or merge request cannot have two scoped labels with the same key.
-For example, if an issue is already labeled `priority::3` and you apply the label `priority::2` to it,
-`priority::3` is automatically removed.
+For example, if an issue is already labeled `priority::3`, and then you apply the
+`priority::2` label to it, `priority::3` is automatically removed.
This functionality is demonstrated in a video titled [Use scoped labels in GitLab 11.10 for custom fields and custom workflows](https://www.youtube.com/watch?v=4BCBby6du3c).
### Labels with multiple colon pairs
-If labels have multiple instances of `::`, the longest path from left to right, until the last `::`, is considered the "key" or the "scope".
+If labels have multiple instances of `::`, the longest path from left to right, until
+the last `::`, is considered the "key" or the "scope".
-For example, `nested::key1::value1` and `nested::key1::value2` cannot both exist on the same issue. Adding the latter label will automatically remove the former due to the shared scope of `nested::key1`.
+For example, `nested::key1::value1` and `nested::key1::value2` cannot both exist on
+the same issue. Adding the latter label will automatically remove the former due to
+the shared scope of `nested::key1`.
-`nested::key1::value1` and `nested::key2::value1` can both exist on the same issue, as these are considered to use two different label scopes, `nested::key1` and `nested::key2`.
+`nested::key1::value1` and `nested::key2::value1` can both exist on the same issue,
+as these are considered to use two different label scopes, `nested::key1` and `nested::key2`.
-### Workflows with scoped labels **(PREMIUM)**
+### Workflows with scoped labels
Suppose you wanted a custom field in issues to track the platform operating system
that your features target, where each issue should only target one platform. You
@@ -58,101 +67,154 @@ be able to advance workflow states consistently in issues themselves.
## Creating labels
->**Note:**
+NOTE: **Note:**
A permission level of Reporter or higher is required to create labels.
### New project label
To create a **project label**, navigate to **Issues > Labels** in the project.
-This page only shows project labels in this project and group labels of this project's parent group.
+This page only shows the project labels in this project, and the group labels of the
+project's parent group.
-Click the **New label** button. Enter the title, an optional description, and the background color. Click **Create label** to create the label.
+Click the **New label** button. Enter the title, an optional description, and the
+background color. Click **Create label** to create the label.
-If a project has no labels, you can generate a default set of project labels from its empty label list page:
+If a project has no labels, you can generate a default set of project labels from
+its empty label list page:
-![Labels generate default](img/labels_generate_default.png)
+![Labels generate default](img/labels_generate_default_v12_1.png)
GitLab will add the following default labels to the project:
-![Labels default](img/labels_default.png)
+![Labels default](img/labels_default_v12_1.png)
### New group label
-To create a **group label**, follow similar steps from above to project labels. Navigate to **Issues > Labels** in the group and create it from there.
-This page only shows group labels in this group.
-Alternatively, you can create group labels also from Epic sidebar. Please note that the created label will belong to the immediate group to which epic belongs.
+To create a **group label**, navigate to **Issues > Labels** in the **group** and create
+it from there. This page only shows group labels in this group.
+
+Alternatively, you can create group labels from the Epic sidebar. Please note that the
+created label will belong to the immediate group to which the epic belongs. **(ULTIMATE)**
-![Create Labels from Epic](img/labels_epic_sidebar.png)
+![Create Labels from Epic](img/labels_epic_sidebar_v12_1.png)
Group labels appear in every label list page of the group's child projects.
-![Labels list](img/labels_list.png)
+![Labels list](img/labels_list_v12_1.png)
### New project label from sidebar
-From the sidebar of an issue or a merge request, you can create a new **project label** inline immediately, instead of navigating to the project label list page.
+From the sidebar of an issue or a merge request, you can create a new **project label**
+inline immediately, instead of navigating to the project label list page.
-![Labels inline](img/new_label_from_sidebar.gif)
+![Labels inline](img/labels_new_label_from_sidebar.gif)
## Editing labels
NOTE: **Note:**
A permission level of Reporter or higher is required to edit labels.
-You can update a label by navigating to **Issues > Labels** in the project or group and clicking the pencil icon.
+To update a label, navigate to **Issues > Labels** in the project or group
+and click the pencil icon. The title, description and color can be changed.
-You can delete a label by clicking the trash icon.
+To delete a label, click the three dots next to the `Subscribe` button, and select
+**Delete**.
+
+![Delete label](img/labels_delete_v12_1.png)
### Promoting project labels to group labels
-If you are expanding from a few projects to a larger number of projects within the same group, you may want to share the same label among multiple projects in the same group. If you previously created a project label and now want to make it available for other projects, you can promote it to a group label.
+If you are expanding from a few projects to a larger number of projects within the
+same group, you may want to share the same label among multiple projects in the same
+group. If you previously created a project label and now want to make it available
+for other projects, you can promote it to a group label.
-From the project label list page, you can promote a project label to a group label. This will merge all project labels across all projects in this group with the same name into a single group label. All issues and merge requests that previously were assigned one of these project labels will now be assigned the new group label. This action cannot be reversed and the changes are permanent.
+From the project label list page, you can promote a project label to a group label.
+This will merge all project labels with the same name into a single group label, across
+all projects in this group. All issues and merge requests that were previously
+assigned one of these project labels will now be assigned the new group label. This
+action cannot be reversed and the changes are permanent.
-![Labels promotion](img/labels_promotion.png)
+![Labels promotion](img/labels_promotion_v12_1.png)
## Assigning labels from the sidebar
-Every issue and merge request can be assigned any number of labels. The labels are visible on every issue and merge request page, in the sidebar. They are also visible in the issue board. From the sidebar, you can assign or unassign a label to the object (i.e. label or unlabel it). You can also perform this as a [quick action](quick_actions.md) in a comment.
+Every issue and merge request can be assigned any number of labels. The labels are
+visible on every issue and merge request page, in the sidebar. They are also visible on:
+
+- Every issue and merge request page in the sidebar.
+- The issue board.
+
+From the sidebar, you can assign or unassign a label to the object (i.e. label or
+unlabel it). You can also perform this as a [quick action](quick_actions.md),
+in a comment.
| View labels in sidebar | Assign labels from sidebar |
-|:---:|:---:|
+|:----------------------:|:--------------------------:|
| ![Labels sidebar](img/labels_sidebar.png) | ![Labels sidebar assign](img/labels_sidebar_assign.png) |
## Searching for project labels
-You can search for project labels by navigating from the left sidebar to your
-project's **Issues > Labels** and entering your query to the search bar on the
-top-right:
+To search for project labels, go to **Issues > Labels** in the left sidebar, and enter
+your search query in the **Filter** field.
![Labels project list search](img/labels_project_list_search.png)
-GitLab will consider the label title and description for the search.
+GitLab will check both the label titles and descriptions for the search.
+
+## Filtering by label
+
+The following can be filtered labels:
-## Filtering issues, merge requests and epics by label
+- Issue lists
+- Merge Request lists
+- Epic lists **(ULTIMATE)**
+- Issue Boards
### Filtering in list pages
-From the project issue list page and the project merge request list page, you can [filter](../search/index.md#issues-and-merge-requests) by both group (including subgroup ancestors) labels and project labels.
+- From the project issue list page and the project merge request list page, you can
+ [filter](../search/index.md#issues-and-merge-requests) by:
+ - Group labels (including subgroup ancestors)
+ - Project labels
-From the group issue list page and the group merge request list page, you can [filter](../search/index.md#issues-and-merge-requests) by both group labels (including subgroup ancestors and subgroup descendants) and project labels.
+- From the group issue list page and the group merge request list page, you can
+ [filter](../search/index.md#issues-and-merge-requests) by:
+ - Group labels (including subgroup ancestors and subgroup descendants)
+ - Project labels
-From the group epic list page, you can [filter](../search/index.md#issues-and-merge-requests) by both current group labels as well as descendant group labels.
+- You can [filter](../search/index.md#issues-and-merge-requests) the group epic list
+ page by: **(ULTIMATE)**
+ - Current group labels
+ - Descendant group labels
-![Labels group issues](img/labels_group_issues.png)
+![Labels group issues](img/labels_group_issues_v12_1.png)
### Filtering in issue boards
-- From [project boards](issue_board.md), you can filter by both group labels and project labels in the [search and filter bar](../search/index.md#issue-boards).
-- From [group issue boards](issue_board.md#group-issue-boards-premium), you can filter by only group labels in the [search and filter bar](../search/index.md#issue-boards). **(PREMIUM)**
-- From [project boards](issue_board.md), you can filter by both group labels and project labels in the [issue board configuration](issue_board.md#configurable-issue-boards-starter). **(STARTER)**
-- From [group issue boards](issue_board.md#group-issue-boards-premium), you can filter by only group labels in the [issue board configuration](issue_board.md#configurable-issue-boards-starter). **(STARTER)**
+- From [project boards](issue_board.md), you can use the [search and filter bar](../search/index.md#issue-boards)
+ to filter by:
+ - Group labels
+ - Project labels
+
+- From [group issue boards](issue_board.md#group-issue-boards-premium), you can use the
+ [search and filter bar](../search/index.md#issue-boards) to filter by group labels only. **(PREMIUM)**
+
+- From [project boards](issue_board.md), in the [issue board configuration](issue_board.md#configurable-issue-boards-starter),
+ you can filter by: **(STARTER)**
+ - Group labels
+ - Project labels
+
+- From [group issue boards](issue_board.md#group-issue-boards-premium), in the [issue board configuration](issue_board.md#configurable-issue-boards-starter),
+ you can filter by group labels only. **(STARTER)**
## Subscribing to labels
-From the project label list page and the group label list page, you can subscribe to [notifications](../../workflow/notifications.md) of a given label, to alert you that the label has been assigned to an issue or merge request.
+From the project label list page and the group label list page, you can subscribe
+to [notifications](../../workflow/notifications.md) of a given label, to alert you
+that the label has been assigned to an issue or merge request.
-![Labels subscriptions](img/labels_subscriptions.png)
+![Labels subscriptions](img/labels_subscriptions_v12_1.png)
## Label priority
@@ -161,26 +223,43 @@ From the project label list page and the group label list page, you can subscrib
> - Introduced in GitLab 8.9.
> - Priority sorting is based on the highest priority label only. [This discussion](https://gitlab.com/gitlab-org/gitlab-ce/issues/18554) considers changing this.
-Labels can have relative priorities, which are used in the "Label priority" and "Priority" sort orders of the issue and merge request list pages.
+Labels can have relative priorities, which are used in the "Label priority" and
+"Priority" sort orders of the issue and merge request list pages.
+
+From the project label list page, star a label to indicate that it has a priority.
+
+![Labels prioritized](img/labels_prioritized_v12_1.png)
+
+Drag starred labels up and down the list to change their priority. Higher in the list
+means higher priority. Prioritization happens at the project level, only on the project
+label list page, and not on the group label list page.
-From the project label list page, star a label to indicate that it has a priority. Drag starred labels up and down to change their priority. Higher means higher priority. Prioritization happens at the project level, only on the project label list page, and not on the group label list page. However, both project and group labels can be prioritized on the project label list page since both types are displayed on the project label list page.
+However, both project and group
+labels can be prioritized on the project label list page since both types are displayed
+on the project label list page.
-![Labels prioritized](img/labels_prioritized.png)
+![Drag to change label priority](img/labels_drag_priority_v12_1.gif)
-On the project and group issue and merge request list pages, you can sort by `Label priority` and `Priority`, which account for objects (issues and merge requests) that have prioritized labels assigned to them.
+On the merge request and issue pages, for both groups and projects, you can sort by `Label priority`
+and `Priority`, which account for objects (issues and merge requests) that have prioritized
+labels assigned to them.
If you sort by `Label priority`, GitLab considers this sort comparison order:
- Object with a higher priority prioritized label.
- Object without a prioritized label.
-Ties are broken arbitrarily. (Note that we _only_ consider the highest prioritized label in an object, and not any of the lower prioritized labels. [This discussion](https://gitlab.com/gitlab-org/gitlab-ce/issues/18554) considers changing this.)
+Ties are broken arbitrarily. Note that we _only_ consider the highest prioritized label
+in an object, and not any of the lower prioritized labels. [This discussion](https://gitlab.com/gitlab-org/gitlab-ce/issues/18554)
+considers changing this.
![Labels sort label priority](img/labels_sort_label_priority.png)
If you sort by `Priority`, GitLab considers this sort comparison order:
-- Object's assigned [milestone](milestones/index.md)'s due date is sooner, provided the object has a milestone and the milestone has a due date. If this isn't the case, consider the object having a due date in the infinite future.
+- Due date of the assigned [milestone](milestones/index.md) is sooner, provided
+ the object has a milestone and the milestone has a due date. If this isn't the case,
+ consider the object having a due date in the infinite future.
- Object with a higher priority prioritized label.
- Object without a prioritized label.
diff --git a/doc/user/project/packages/npm_registry.md b/doc/user/project/packages/npm_registry.md
index ca0aa9965ef..e01bac6b26f 100644
--- a/doc/user/project/packages/npm_registry.md
+++ b/doc/user/project/packages/npm_registry.md
@@ -81,6 +81,10 @@ domain name.
You should now be able to download and upload NPM packages to your project.
+NOTE: **Note:**
+If you encounter an error message with [Yarn](https://yarnpkg.com/en/), see the
+[troubleshooting section](#troubleshooting).
+
## Uploading packages
Before you will be able to upload a package, you need to specify the registry
@@ -116,3 +120,29 @@ a given scope, you will receive a `403 Forbidden!` error.
If you upload a package with a same name and version twice, GitLab will show
both packages in the UI, but the GitLab NPM Registry will expose the most recent
one as it supports only one package per version for `npm install`.
+
+## Troubleshooting
+
+### Error running yarn with NPM registry
+
+If you are using [yarn](https://yarnpkg.com/en/) with the NPM registry, you may get
+an error message like:
+
+```sh
+yarn install v1.15.2
+warning package.json: No license field
+info No lockfile found.
+warning XXX: No license field
+[1/4] 🔍 Resolving packages...
+[2/4] 🚚 Fetching packages...
+error An unexpected error occurred: "https://gitlab.com/api/v4/projects/XXX/packages/npm/XXX/XXX/-/XXX/XXX-X.X.X.tgz: Request failed \"404 Not Found\"".
+info If you think this is a bug, please open a bug report with the information provided in "/Users/XXX/gitlab-migration/module-util/yarn-error.log".
+info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command
+```
+
+In this case, try adding this to your `.npmrc` file (and replace `<your_oauth_token>`
+with your with your OAuth or personal access token):
+
+```text
+//gitlab.com/api/v4/projects/:_authToken=<your_oauth_token>
+```
diff --git a/lib/feature.rb b/lib/feature.rb
index e28333aa58e..c70a6980f19 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -80,6 +80,13 @@ class Feature
get(key).disable_group(group)
end
+ def remove(key)
+ feature = get(key)
+ return unless persisted?(feature)
+
+ feature.remove
+ end
+
def flipper
if Gitlab::SafeRequestStore.active?
Gitlab::SafeRequestStore[:flipper] ||= build_flipper_instance
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index 615c0ec374c..ec7671f9a8b 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -21,6 +21,9 @@ module Gitlab
lib/gitlab/profiler.rb
lib/gitlab/correlation_id.rb
lib/gitlab/webpack/dev_server_middleware.rb
+ lib/gitlab/sidekiq_status/
+ lib/gitlab/sidekiq_logging/
+ lib/gitlab/sidekiq_middleware/
].freeze
# Takes a URL to profile (can be a fully-qualified URL, or an absolute path)
diff --git a/lib/peek/views/rugged.rb b/lib/peek/views/rugged.rb
index 6b9d3e7b1a3..18b3f422852 100644
--- a/lib/peek/views/rugged.rb
+++ b/lib/peek/views/rugged.rb
@@ -29,8 +29,12 @@ module Peek
def format_args(args)
args.map do |arg|
- # Needed to avoid infinite as_json calls
- if arg.is_a?(Gitlab::Git::Repository)
+ # ActiveSupport::JSON recursively calls as_json on all
+ # instance variables, and if that instance variable points to
+ # something that refers back to the same instance, we can wind
+ # up in an infinite loop. Currently this only seems to happen with
+ # Gitlab::Git::Repository and ::Repository.
+ if arg.instance_variables.present?
arg.to_s
else
arg
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 709226e686c..4921b3c835b 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3282,6 +3282,9 @@ msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not add prometheus URL to whitelist"
+msgstr ""
+
msgid "Could not authorize chat nickname. Try again!"
msgstr ""
@@ -8732,6 +8735,9 @@ msgstr ""
msgid "ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}"
msgstr ""
+msgid "Prometheus listen_address is not a valid URI"
+msgstr ""
+
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -10969,7 +10975,7 @@ msgstr ""
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
msgstr ""
-msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> or <code>git://</code>."
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
index a118176eb8a..db99488160b 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_oauth_spec.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module QA
- context 'Manage', :orchestrated, :oauth do
+ # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/121
+ context 'Manage', :orchestrated, :oauth, :quarantine do
describe 'OAuth login' do
it 'User logs in to GitLab with GitHub OAuth' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
index 11fd570d131..2027a3c16aa 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
module QA
- # Failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/113
- context 'Create', :requires_admin, :quarantine do
+ context 'Create', :requires_admin do
describe 'push after setting the file size limit via admin/application_settings' do
before(:context) do
@project = Resource::Project.fabricate_via_api! do |p|
@@ -21,14 +20,21 @@ module QA
it 'push successful when the file size is under the limit' do
set_file_size_limit(5)
- push = push_new_file('oversize_file_1.bin', wait_for_push: true)
- expect(push.output).not_to have_content 'remote: fatal: pack exceeds maximum allowed size'
+
+ retry_on_fail do
+ push = push_new_file('oversize_file_1.bin', wait_for_push: true)
+
+ expect(push.output).not_to have_content 'remote: fatal: pack exceeds maximum allowed size'
+ end
end
it 'push fails when the file size is above the limit' do
set_file_size_limit(1)
- expect { push_new_file('oversize_file_2.bin', wait_for_push: false) }
- .to raise_error(QA::Git::Repository::RepositoryCommandError, /remote: fatal: pack exceeds maximum allowed size/)
+
+ retry_on_fail do
+ expect { push_new_file('oversize_file_2.bin', wait_for_push: false) }
+ .to raise_error(QA::Git::Repository::RepositoryCommandError, /remote: fatal: pack exceeds maximum allowed size/)
+ end
end
def set_file_size_limit(limit)
@@ -54,6 +60,22 @@ module QA
output
end
+
+ # Application settings are cached for up to a minute. So when we change
+ # the `receive_max_input_size` setting, the setting might not be applied
+ # for minute. This caused the tests to intermittently fail.
+ # See https://gitlab.com/gitlab-org/quality/nightly/issues/113
+ #
+ # Instead of waiting a minute after changing the setting, we retry the
+ # attempt to push if it fails. Most of the time the setting is updated in
+ # under a minute, i.e., in fewer than 6 attempts with a 10 second sleep
+ # between attempts.
+ # See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/30233#note_188616863
+ def retry_on_fail
+ Support::Retrier.retry_on_exception(max_attempts: 6, reload_page: nil, sleep_interval: 10) do
+ yield
+ end
+ end
end
end
end
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 408a0595f9e..4935c1342a3 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -340,31 +340,6 @@ function display_deployment_debug() {
fi
}
-function wait_for_review_app_to_be_accessible() {
- echoinfo "Waiting for the Review App at ${CI_ENVIRONMENT_URL} to be accessible..." true
-
- local interval=5
- local elapsed_seconds=0
- local max_seconds=$((2 * 60))
- while true; do
- local review_app_http_code
- review_app_http_code=$(curl --silent --output /dev/null --max-time 5 --write-out "%{http_code}" "${CI_ENVIRONMENT_URL}/users/sign_in")
- if [[ "${review_app_http_code}" -eq "200" ]] || [[ "${elapsed_seconds}" -gt "${max_seconds}" ]]; then
- break
- fi
-
- let "elapsed_seconds+=interval"
- sleep ${interval}
- done
-
- if [[ "${review_app_http_code}" -eq "200" ]]; then
- echoinfo "The Review App at ${CI_ENVIRONMENT_URL} is ready after ${elapsed_seconds} seconds!"
- else
- echoerr "The Review App at ${CI_ENVIRONMENT_URL} isn't ready after ${max_seconds} seconds of polling..."
- exit 1
- fi
-}
-
function add_license() {
if [ -z "${REVIEW_APPS_EE_LICENSE}" ]; then echo "License not found" && return; fi
diff --git a/spec/controllers/admin/clusters/applications_controller_spec.rb b/spec/controllers/admin/clusters/applications_controller_spec.rb
index cf202d88acc..9d6edcd80c0 100644
--- a/spec/controllers/admin/clusters/applications_controller_spec.rb
+++ b/spec/controllers/admin/clusters/applications_controller_spec.rb
@@ -84,7 +84,7 @@ describe Admin::Clusters::ApplicationsController do
patch :update, params: params
end
- let!(:application) { create(:clusters_applications_cert_managers, :installed, cluster: cluster) }
+ let!(:application) { create(:clusters_applications_cert_manager, :installed, cluster: cluster) }
let(:application_name) { application.name }
let(:params) { { application: application_name, id: cluster.id, email: "new-email@example.com" } }
diff --git a/spec/controllers/groups/clusters/applications_controller_spec.rb b/spec/controllers/groups/clusters/applications_controller_spec.rb
index 16a63536ea6..21533d1c89a 100644
--- a/spec/controllers/groups/clusters/applications_controller_spec.rb
+++ b/spec/controllers/groups/clusters/applications_controller_spec.rb
@@ -91,7 +91,7 @@ describe Groups::Clusters::ApplicationsController do
patch :update, params: params.merge(group_id: group)
end
- let!(:application) { create(:clusters_applications_cert_managers, :installed, cluster: cluster) }
+ let!(:application) { create(:clusters_applications_cert_manager, :installed, cluster: cluster) }
let(:application_name) { application.name }
let(:params) { { application: application_name, id: cluster.id, email: "new-email@example.com" } }
diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb
index dbfacf4e42e..43c910da7a5 100644
--- a/spec/controllers/help_controller_spec.rb
+++ b/spec/controllers/help_controller_spec.rb
@@ -111,7 +111,7 @@ describe HelpController do
it 'renders the raw file' do
get :show,
params: {
- path: 'user/project/img/labels_default'
+ path: 'user/project/img/labels_default_v12_1'
},
format: :png
expect(response).to be_success
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index 7fe9ea6801a..24c22ef3928 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -60,7 +60,7 @@ FactoryBot.define do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
- factory :clusters_applications_cert_managers, class: Clusters::Applications::CertManager do
+ factory :clusters_applications_cert_manager, class: Clusters::Applications::CertManager do
email 'admin@example.com'
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js
new file mode 100644
index 00000000000..7e462e9a6ce
--- /dev/null
+++ b/spec/frontend/tracking_spec.js
@@ -0,0 +1,123 @@
+import $ from 'jquery';
+import { setHTMLFixture } from './helpers/fixtures';
+
+import Tracking from '~/tracking';
+
+describe('Tracking', () => {
+ beforeEach(() => {
+ window.snowplow = window.snowplow || (() => {});
+ });
+
+ describe('.event', () => {
+ let snowplowSpy = null;
+
+ beforeEach(() => {
+ snowplowSpy = jest.spyOn(window, 'snowplow');
+ });
+
+ it('tracks to snowplow (our current tracking system)', () => {
+ Tracking.event('_category_', '_eventName_', { label: '_label_' });
+
+ expect(snowplowSpy).toHaveBeenCalledWith('trackStructEvent', '_category_', '_eventName_', {
+ label: '_label_',
+ property: '',
+ value: '',
+ });
+ });
+
+ it('skips tracking if snowplow is unavailable', () => {
+ window.snowplow = false;
+ Tracking.event('_category_', '_eventName_');
+
+ expect(snowplowSpy).not.toHaveBeenCalled();
+ });
+
+ it('skips tracking if ', () => {
+ window.snowplow = false;
+ Tracking.event('_category_', '_eventName_');
+
+ expect(snowplowSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('tracking interface events', () => {
+ let eventSpy = null;
+ let subject = null;
+
+ beforeEach(() => {
+ eventSpy = jest.spyOn(Tracking, 'event');
+ subject = new Tracking('_category_');
+ setHTMLFixture(`
+ <input data-track-event="click_input1" data-track-label="_label_" value="_value_"/>
+ <input data-track-event="click_input2" data-track-value="_value_override_" value="_value_"/>
+ <input type="checkbox" data-track-event="toggle_checkbox" value="_value_" checked/>
+ <input class="dropdown" data-track-event="toggle_dropdown"/>
+ <div class="js-projects-list-holder"></div>
+ `);
+ });
+
+ it('binds to clicks on elements matching [data-track-event]', () => {
+ subject.bind(document);
+ $('[data-track-event="click_input1"]').click();
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input1', {
+ label: '_label_',
+ value: '_value_',
+ property: '',
+ });
+ });
+
+ it('allows value override with the data-track-value attribute', () => {
+ subject.bind(document);
+ $('[data-track-event="click_input2"]').click();
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'click_input2', {
+ label: '',
+ value: '_value_override_',
+ property: '',
+ });
+ });
+
+ it('handles checkbox values correctly', () => {
+ subject.bind(document);
+ const $checkbox = $('[data-track-event="toggle_checkbox"]');
+
+ $checkbox.click(); // unchecking
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', {
+ label: '',
+ property: '',
+ value: false,
+ });
+
+ $checkbox.click(); // checking
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_checkbox', {
+ label: '',
+ property: '',
+ value: '_value_',
+ });
+ });
+
+ it('handles bootstrap dropdowns', () => {
+ new Tracking('_category_').bind(document);
+ const $dropdown = $('[data-track-event="toggle_dropdown"]');
+
+ $dropdown.trigger('show.bs.dropdown'); // showing
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_dropdown_show', {
+ label: '',
+ property: '',
+ value: '',
+ });
+
+ $dropdown.trigger('hide.bs.dropdown'); // hiding
+
+ expect(eventSpy).toHaveBeenCalledWith('_category_', 'toggle_dropdown_hide', {
+ label: '',
+ property: '',
+ value: '',
+ });
+ });
+ });
+});
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 185abacf8e7..3d59b1f35a9 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -254,6 +254,22 @@ describe Feature do
end
end
+ describe '.remove' do
+ context 'for a non-persisted feature' do
+ it 'returns nil' do
+ expect(described_class.remove(:non_persisted_feature_flag)).to be_nil
+ end
+ end
+
+ context 'for a persisted feature' do
+ it 'returns true' do
+ described_class.enable(:persisted_feature_flag)
+
+ expect(described_class.remove(:persisted_feature_flag)).to be_truthy
+ end
+ end
+ end
+
describe Feature::Target do
describe '#targets' do
let(:project) { create(:project) }
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 6d0a2098b2e..297c4f0b683 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -24,7 +24,7 @@ describe Gitlab::UsageData do
create(:cluster, :group, :disabled)
create(:clusters_applications_helm, :installed, cluster: gcp_cluster)
create(:clusters_applications_ingress, :installed, cluster: gcp_cluster)
- create(:clusters_applications_cert_managers, :installed, cluster: gcp_cluster)
+ create(:clusters_applications_cert_manager, :installed, cluster: gcp_cluster)
create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster)
create(:clusters_applications_runner, :installed, cluster: gcp_cluster)
create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
diff --git a/spec/lib/peek/views/rugged_spec.rb b/spec/lib/peek/views/rugged_spec.rb
index 8bf996fc6bc..d07d6b51a1f 100644
--- a/spec/lib/peek/views/rugged_spec.rb
+++ b/spec/lib/peek/views/rugged_spec.rb
@@ -24,7 +24,7 @@ describe Peek::Views::Rugged, :request_store do
args: [project.repository.raw, 'HEAD'],
duration: 0.123)
::Gitlab::RuggedInstrumentation.add_call_details(feature: :rugged_test2,
- args: [project.repository.raw, 'refs/heads/master'],
+ args: [project.repository, 'refs/heads/master'],
duration: 0.456)
results = subject.results
@@ -32,7 +32,11 @@ describe Peek::Views::Rugged, :request_store do
expect(results[:duration]).to eq('1234.00ms')
expect(results[:details].count).to eq(2)
- expect(results[:details][0][:args]).to eq([project.repository.raw.to_s, "refs/heads/master"])
- expect(results[:details][1][:args]).to eq([project.repository.raw.to_s, "HEAD"])
+ expected = [
+ [project.repository.raw.to_s, "HEAD"],
+ [project.repository.to_s, "refs/heads/master"]
+ ]
+
+ expect(results[:details].map { |data| data[:args] }).to match_array(expected)
end
end
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
index 6e1f80cadc2..e956a2355db 100644
--- a/spec/models/clusters/applications/cert_manager_spec.rb
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -3,11 +3,11 @@
require 'rails_helper'
describe Clusters::Applications::CertManager do
- let(:cert_manager) { create(:clusters_applications_cert_managers) }
+ let(:cert_manager) { create(:clusters_applications_cert_manager) }
- include_examples 'cluster application core specs', :clusters_applications_cert_managers
- include_examples 'cluster application status specs', :clusters_applications_cert_managers
- include_examples 'cluster application version specs', :clusters_applications_cert_managers
+ include_examples 'cluster application core specs', :clusters_applications_cert_manager
+ include_examples 'cluster application status specs', :clusters_applications_cert_manager
+ include_examples 'cluster application version specs', :clusters_applications_cert_manager
include_examples 'cluster application initial status specs'
describe '#can_uninstall?' do
@@ -72,7 +72,7 @@ describe Clusters::Applications::CertManager do
end
context 'application failed to install previously' do
- let(:cert_manager) { create(:clusters_applications_cert_managers, :errored, version: '0.0.1') }
+ let(:cert_manager) { create(:clusters_applications_cert_manager, :errored, version: '0.0.1') }
it 'is initialized with the locked version' do
expect(subject.version).to eq('v0.5.2')
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 761695bfe91..96212d0c864 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -451,7 +451,7 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
context 'when applications are created' do
let!(:helm) { create(:clusters_applications_helm, cluster: cluster) }
let!(:ingress) { create(:clusters_applications_ingress, cluster: cluster) }
- let!(:cert_manager) { create(:clusters_applications_cert_managers, cluster: cluster) }
+ let!(:cert_manager) { create(:clusters_applications_cert_manager, cluster: cluster) }
let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
let!(:runner) { create(:clusters_applications_runner, cluster: cluster) }
let!(:jupyter) { create(:clusters_applications_jupyter, cluster: cluster) }
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index ce0681c4331..d2e0bed721e 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe Environment, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
+ using RSpec::Parameterized::TableSyntax
let(:project) { create(:project, :stubbed_repository) }
subject(:environment) { create(:environment, project: project) }
@@ -782,12 +783,9 @@ describe Environment, :use_clean_rails_memory_store_caching do
let(:source_path) { 'source/file.html' }
let(:sha) { RepoHelpers.sample_commit.id }
- before do
- environment.external_url = 'http://example.com'
- end
-
context 'when the public path is not known' do
before do
+ environment.external_url = 'http://example.com'
allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return(nil)
end
@@ -797,12 +795,23 @@ describe Environment, :use_clean_rails_memory_store_caching do
end
context 'when the public path is known' do
- before do
- allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return('file.html')
- end
-
- it 'returns the full external URL' do
- expect(environment.external_url_for(source_path, sha)).to eq('http://example.com/file.html')
+ where(:external_url, :public_path, :full_url) do
+ 'http://example.com' | 'file.html' | 'http://example.com/file.html'
+ 'http://example.com/' | 'file.html' | 'http://example.com/file.html'
+ 'http://example.com' | '/file.html' | 'http://example.com/file.html'
+ 'http://example.com/' | '/file.html' | 'http://example.com/file.html'
+ 'http://example.com/subpath' | 'public/file.html' | 'http://example.com/subpath/public/file.html'
+ 'http://example.com/subpath/' | 'public/file.html' | 'http://example.com/subpath/public/file.html'
+ 'http://example.com/subpath' | '/public/file.html' | 'http://example.com/subpath/public/file.html'
+ 'http://example.com/subpath/' | '/public/file.html' | 'http://example.com/subpath/public/file.html'
+ end
+ with_them do
+ it 'returns the full external URL' do
+ environment.external_url = external_url
+ allow(project).to receive(:public_path_for_source_path).with(source_path, sha).and_return(public_path)
+
+ expect(environment.external_url_for(source_path, sha)).to eq(full_url)
+ end
end
end
end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 03003e3dd7d..bfd0e5f0558 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -913,6 +913,22 @@ describe Note do
end
end
+ describe '#special_role=' do
+ let(:role) { Note::SpecialRole::FIRST_TIME_CONTRIBUTOR }
+
+ it 'assigns role' do
+ subject.special_role = role
+
+ expect(subject.special_role).to eq(role)
+ end
+
+ it 'does not assign unknown role' do
+ expect { subject.special_role = :bogus }.to raise_error(/Role is undefined/)
+
+ expect(subject.special_role).to be_nil
+ end
+ end
+
describe '#parent' do
it 'returns project for project notes' do
project = create(:project)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 32fb0c0ff73..157103123ad 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2950,6 +2950,16 @@ describe Project do
expect(project.public_path_for_source_path('file.html', sha)).to be_nil
end
end
+
+ it 'returns a public path with a leading slash unmodified' do
+ route_map = Gitlab::RouteMap.new(<<-MAP.strip_heredoc)
+ - source: 'source/file.html'
+ public: '/public/file'
+ MAP
+ allow(project).to receive(:route_map_for).with(sha).and_return(route_map)
+
+ expect(project.public_path_for_source_path('source/file.html', sha)).to eq('/public/file')
+ end
end
context 'when there is no route map' do
diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb
index 33cd1f37ff6..adb5219d691 100644
--- a/spec/services/application_settings/update_service_spec.rb
+++ b/spec/services/application_settings/update_service_spec.rb
@@ -62,6 +62,54 @@ describe ApplicationSettings::UpdateService do
end
end
+ describe 'updating outbound_local_requests_whitelist' do
+ context 'when params is blank' do
+ let(:params) { {} }
+
+ it 'does not add to whitelist' do
+ expect { subject.execute }.not_to change {
+ application_settings.outbound_local_requests_whitelist
+ }
+ end
+ end
+
+ context 'when param add_to_outbound_local_requests_whitelist contains values' do
+ before do
+ application_settings.outbound_local_requests_whitelist = ['127.0.0.1']
+ end
+
+ let(:params) { { add_to_outbound_local_requests_whitelist: ['example.com', ''] } }
+
+ it 'adds to whitelist' do
+ expect { subject.execute }.to change {
+ application_settings.outbound_local_requests_whitelist
+ }
+
+ expect(application_settings.outbound_local_requests_whitelist).to contain_exactly(
+ '127.0.0.1', 'example.com'
+ )
+ end
+ end
+
+ context 'when param outbound_local_requests_whitelist_raw is passed' do
+ before do
+ application_settings.outbound_local_requests_whitelist = ['127.0.0.1']
+ end
+
+ let(:params) { { outbound_local_requests_whitelist_raw: 'example.com;gitlab.com' } }
+
+ it 'overwrites the existing whitelist' do
+ expect { subject.execute }.to change {
+ application_settings.outbound_local_requests_whitelist
+ }
+
+ expect(application_settings.outbound_local_requests_whitelist).to contain_exactly(
+ 'example.com', 'gitlab.com'
+ )
+ end
+ end
+ end
+
describe 'performance bar settings' do
using RSpec::Parameterized::TableSyntax
diff --git a/spec/services/self_monitoring/project/create_service_spec.rb b/spec/services/self_monitoring/project/create_service_spec.rb
index d11e27c6d52..a1e7aaf45f2 100644
--- a/spec/services/self_monitoring/project/create_service_spec.rb
+++ b/spec/services/self_monitoring/project/create_service_spec.rb
@@ -90,19 +90,17 @@ describe SelfMonitoring::Project::CreateService do
)
end
- # This should pass when https://gitlab.com/gitlab-org/gitlab-ce/issues/44496
- # is complete and the prometheus listen address is added to the whitelist.
- # context 'when local requests from hooks and services are not allowed' do
- # before do
- # allow(ApplicationSetting)
- # .to receive(:current)
- # .and_return(
- # ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: false)
- # )
- # end
-
- # it_behaves_like 'has prometheus service', 'http://localhost:9090'
- # end
+ context 'when local requests from hooks and services are not allowed' do
+ before do
+ allow(ApplicationSetting)
+ .to receive(:current)
+ .and_return(
+ ApplicationSetting.build_from_defaults(allow_local_requests_from_hooks_and_services: false)
+ )
+ end
+
+ it_behaves_like 'has prometheus service', 'http://localhost:9090'
+ end
context 'with non default prometheus address' do
before do
diff --git a/spec/support/shared_examples/application_setting_examples.rb b/spec/support/shared_examples/application_setting_examples.rb
index 0e6a8059376..a43d2a75082 100644
--- a/spec/support/shared_examples/application_setting_examples.rb
+++ b/spec/support/shared_examples/application_setting_examples.rb
@@ -63,6 +63,19 @@ RSpec.shared_examples 'application settings examples' do
context 'outbound_local_requests_whitelist' do
it_behaves_like 'string of domains', :outbound_local_requests_whitelist
+
+ it 'clears outbound_local_requests_whitelist_arrays memoization' do
+ setting.outbound_local_requests_whitelist_raw = 'example.com'
+
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ [], ['example.com']
+ )
+
+ setting.outbound_local_requests_whitelist_raw = 'gitlab.com'
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ [], ['gitlab.com']
+ )
+ end
end
context 'outbound_local_requests_whitelist_arrays' do
@@ -78,7 +91,54 @@ RSpec.shared_examples 'application settings examples' do
]
domain_whitelist = ['www.example.com', 'example.com', 'subdomain.example.com']
- expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(ip_whitelist, domain_whitelist)
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ ip_whitelist, domain_whitelist
+ )
+ end
+ end
+
+ context 'add_to_outbound_local_requests_whitelist' do
+ it 'adds entry to outbound_local_requests_whitelist' do
+ setting.outbound_local_requests_whitelist = ['example.com']
+
+ setting.add_to_outbound_local_requests_whitelist(
+ ['example.com', '127.0.0.1', 'gitlab.com']
+ )
+
+ expect(setting.outbound_local_requests_whitelist).to contain_exactly(
+ 'example.com',
+ '127.0.0.1',
+ 'gitlab.com'
+ )
+ end
+
+ it 'clears outbound_local_requests_whitelist_arrays memoization' do
+ setting.outbound_local_requests_whitelist = ['example.com']
+
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ [],
+ ['example.com']
+ )
+
+ setting.add_to_outbound_local_requests_whitelist(
+ ['example.com', 'gitlab.com']
+ )
+
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ [],
+ ['example.com', 'gitlab.com']
+ )
+ end
+
+ it 'does not raise error with nil' do
+ setting.outbound_local_requests_whitelist = nil
+
+ setting.add_to_outbound_local_requests_whitelist(['gitlab.com'])
+
+ expect(setting.outbound_local_requests_whitelist).to contain_exactly('gitlab.com')
+ expect(setting.outbound_local_requests_whitelist_arrays).to contain_exactly(
+ [], ['gitlab.com']
+ )
end
it 'does not raise error with nil' do