diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index cd1d2e94f31d7c63aa19967c2627230038786a10..8b22a322d0fea3dbc820b5777633551e43653a3b 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-8.0.1
+8.0.2
diff --git a/app/assets/javascripts/error_tracking/index.js b/app/assets/javascripts/error_tracking/index.js
index 808ae2c9a410884ba53868947d7961ddd540d89a..3d609448efe4c949b117c18a12182145ae4c6aef 100644
--- a/app/assets/javascripts/error_tracking/index.js
+++ b/app/assets/javascripts/error_tracking/index.js
@@ -4,10 +4,6 @@ import store from './store';
import ErrorTrackingList from './components/error_tracking_list.vue';
export default () => {
- if (!gon.features.errorTracking) {
- return;
- }
-
// eslint-disable-next-line no-new
new Vue({
el: '#js-error_tracking',
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 65f85314fa083d5a23011433d022b4c7c0e07f40..2105a62cecb085c6af7f95c706f206330d5d95a7 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -415,12 +415,13 @@ export const submitSuggestion = (
commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId });
callback();
})
- .catch(() => {
- Flash(
- __('Something went wrong while applying the suggestion. Please try again.'),
- 'alert',
- flashContainer,
+ .catch(err => {
+ const defaultMessage = __(
+ 'Something went wrong while applying the suggestion. Please try again.',
);
+ const flashMessage = err.response.data ? `${err.response.data.message}.` : defaultMessage;
+
+ Flash(__(flashMessage), 'alert', flashContainer);
callback();
});
};
diff --git a/app/assets/javascripts/pages/projects/tags/releases/index.js b/app/assets/javascripts/pages/projects/tags/releases/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d6afc71fb031d7655d831892578b27e2a2d802e8
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/tags/releases/index.js
@@ -0,0 +1,8 @@
+import $ from 'jquery';
+import ZenMode from '~/zen_mode';
+import GLForm from '~/gl_form';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ZenMode(); // eslint-disable-line no-new
+ new GLForm($('.release-form')); // eslint-disable-line no-new
+});
diff --git a/app/controllers/projects/error_tracking_controller.rb b/app/controllers/projects/error_tracking_controller.rb
index 4596b6c91f2af87df6741c8fc2c888c7ea61cd4f..9e403e1d25b1ab03b940ec938d0189b3aaf272de 100644
--- a/app/controllers/projects/error_tracking_controller.rb
+++ b/app/controllers/projects/error_tracking_controller.rb
@@ -1,9 +1,7 @@
# frozen_string_literal: true
class Projects::ErrorTrackingController < Projects::ApplicationController
- before_action :check_feature_flag!
before_action :authorize_read_sentry_issue!
- before_action :push_feature_flag_to_frontend
POLLING_INTERVAL = 10_000
@@ -43,12 +41,4 @@ def serialize_errors(errors)
.new(project: project, user: current_user)
.represent(errors)
end
-
- def check_feature_flag!
- render_404 unless Feature.enabled?(:error_tracking, project)
- end
-
- def push_feature_flag_to_frontend
- push_frontend_feature_flag(:error_tracking, current_user)
- end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 035d2d49bc554e63c98ebf65b023c5d820a0f80f..e71f1760aba708cbfaf98af4379bb00c75663998 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -287,7 +287,7 @@ def show_issue_count?(disabled: false, compact_mode: false)
# overridden in EE
def settings_operations_available?
- Feature.enabled?(:error_tracking, @project) && can?(current_user, :read_environment, @project)
+ can?(current_user, :read_environment, @project)
end
private
@@ -330,7 +330,7 @@ def get_project_nav_tabs(project, current_user)
def external_nav_tabs(project)
[].tap do |tabs|
tabs << :external_issue_tracker if project.external_issue_tracker
- tabs << :external_wiki if project.has_external_wiki?
+ tabs << :external_wiki if project.external_wiki
end
end
diff --git a/app/models/appearance.rb b/app/models/appearance.rb
index d918add2147fb47fbddc30071226a8d13136b66c..12fa112cd5034a2208bb442313dcebe95696123f 100644
--- a/app/models/appearance.rb
+++ b/app/models/appearance.rb
@@ -44,7 +44,11 @@ def favicon_path
private
def logo_system_path(logo, mount_type)
- return unless logo&.upload
+ # Legacy attachments may not have have an associated Upload record,
+ # so fallback to the AttachmentUploader#url if this is the
+ # case. AttachmentUploader#path doesn't work because for a local
+ # file, this is an absolute path to the file.
+ return logo&.url unless logo&.upload
# If we're using a CDN, we need to use the full URL
asset_host = ActionController::Base.asset_host
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 39c8619147725e72c0c84d320370b3f15d8e7dda..cddf6576c25648913d5796d03ea3c6d832ad443d 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -525,6 +525,8 @@ def blob_at(sha, path)
# items is an Array like: [[oid, path], [oid1, path1]]
def blobs_at(items)
+ return [] unless exists?
+
raw_repository.batch_blobs(items).map { |blob| Blob.decorate(blob, project) }
end
diff --git a/app/models/ssh_host_key.rb b/app/models/ssh_host_key.rb
index 99a0c54a26a38738f2ca7c0c8e3b3da1b3fa292f..f318d32c71cb31c1cf5477581037274c8ba1fcc5 100644
--- a/app/models/ssh_host_key.rb
+++ b/app/models/ssh_host_key.rb
@@ -54,7 +54,7 @@ def initialize(project:, url:, compare_host_keys: nil)
# Needed for reactive caching
def self.primary_key
- 'id'
+ :id
end
def id
diff --git a/app/services/suggestions/apply_service.rb b/app/services/suggestions/apply_service.rb
index cc47b46b527a563eeb1222077ba7ad47cfec0168..1f720fc835f153e3d7180c38cb500ea8007fb53e 100644
--- a/app/services/suggestions/apply_service.rb
+++ b/app/services/suggestions/apply_service.rb
@@ -11,7 +11,7 @@ def execute(suggestion)
return error('Suggestion is not appliable')
end
- unless latest_diff_refs?(suggestion)
+ unless latest_source_head?(suggestion)
return error('The file has been changed')
end
@@ -29,12 +29,13 @@ def execute(suggestion)
private
- # Checks whether the latest diff refs for the branch matches with
- # the position refs we're using to update the file content. Since
- # the persisted refs are updated async (for MergeRequest),
- # it's more consistent to fetch this data directly from the repository.
- def latest_diff_refs?(suggestion)
- suggestion.position.diff_refs == suggestion.noteable.repository_diff_refs
+ # Checks whether the latest source branch HEAD matches with
+ # the position HEAD we're using to update the file content. Since
+ # the persisted HEAD is updated async (for MergeRequest),
+ # it's more consistent to fetch this data directly from the
+ # repository.
+ def latest_source_head?(suggestion)
+ suggestion.position.head_sha == suggestion.noteable.source_branch_sha
end
def file_update_params(suggestion)
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index c5246f94c63e1cb2c8725f16a7dc646af4f283ba..29de51526f900a9ac1bdf0dbb32bd7b2476aeb9b 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -227,7 +227,7 @@
%span
= _('Environments')
- - if project_nav_tab?(:error_tracking) && Feature.enabled?(:error_tracking, @project)
+ - if project_nav_tab?(:error_tracking)
= nav_link(controller: :error_tracking) do
= link_to project_error_tracking_index_path(@project), title: _('Error Tracking'), class: 'shortcuts-tracking qa-operations-tracking-link' do
%span
diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml
index 31f1cf560e22354929334859155044023f903faa..12da62f4c64ddd4d41f10b6237b9027c441dfbd4 100644
--- a/app/views/projects/_activity.html.haml
+++ b/app/views/projects/_activity.html.haml
@@ -1,5 +1,5 @@
%div{ class: container_class }
- .nav-block.d-none.d-sm-block.activities
+ .nav-block.d-none.d-sm-flex.activities
= render 'shared/event_filter'
.controls
= link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn d-none d-sm-inline-block has-tooltip' do
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index 871b60f05bab8b58ddac05b6409006a82b9faa39..4911e8d37706d6bf6ddb242793f674d4d398dd57 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -1,4 +1,4 @@
-- return unless Feature.enabled?(:error_tracking, @project) && can?(current_user, :read_environment, @project)
+- return unless can?(current_user, :read_environment, @project)
- setting = error_tracking_setting
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index f55202c2c5f05ae0a16c116e9c37e76e24af5581..cc203cfad86fb2e9c48d9ead1d2b8e31481089cc 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -28,7 +28,7 @@
= render 'projects/buttons/download', project: @project, ref: tag.name, pipeline: @tags_pipelines[tag.name]
- if can?(current_user, :push_code, @project)
- = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
+ = link_to edit_project_tag_release_path(@project, tag.name), class: 'btn btn-edit has-tooltip', title: s_('TagsPage|Edit release notes'), data: { container: "body" } do
= icon("pencil")
- if can?(current_user, :admin_project, @project)
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index 15a960f81b877791ef78d3fd007d5d2e2b6d80c7..feeaf799f513c3773941ac209337d6d0347dad24 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -20,7 +20,7 @@
.nav-controls.controls-flex
- if can?(current_user, :push_code, @project)
- = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
+ = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do
= icon("pencil")
= link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do
= icon('files-o')
diff --git a/changelogs/unreleased/56424-fix-gl-form-init-tag-editing.yml b/changelogs/unreleased/56424-fix-gl-form-init-tag-editing.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b19b4d650fdbf0084d5a7e62b89f1ffc824bb276
--- /dev/null
+++ b/changelogs/unreleased/56424-fix-gl-form-init-tag-editing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix form functionality for edit tag page
+merge_request: 24645
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-regression-external-wiki-url.yml b/changelogs/unreleased/fj-regression-external-wiki-url.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d4f21dab9823b919cca7d899645047ba1235f170
--- /dev/null
+++ b/changelogs/unreleased/fj-regression-external-wiki-url.yml
@@ -0,0 +1,5 @@
+---
+title: Changed external wiki query method to prevent attribute caching
+merge_request: 24907
+author:
+type: fixed
diff --git a/changelogs/unreleased/osw-adjusts-suggestions-unable-to-be-applied.yml b/changelogs/unreleased/osw-adjusts-suggestions-unable-to-be-applied.yml
new file mode 100644
index 0000000000000000000000000000000000000000..3ba62b924134ae1f968f17ce740d54f23eb18d17
--- /dev/null
+++ b/changelogs/unreleased/osw-adjusts-suggestions-unable-to-be-applied.yml
@@ -0,0 +1,5 @@
+---
+title: Adjusts suggestions unable to be applied
+merge_request: 24603
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-detect-host-keys.yml b/changelogs/unreleased/sh-fix-detect-host-keys.yml
new file mode 100644
index 0000000000000000000000000000000000000000..993d7c35b1825930a8c465b99b1829f8c1dfc56c
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-detect-host-keys.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Detect Host Keys not working
+merge_request: 24884
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-9357.yml b/changelogs/unreleased/sh-fix-issue-9357.yml
new file mode 100644
index 0000000000000000000000000000000000000000..756cd6047b8f0cd5e84feccc71c4dcf94c8ea683
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-9357.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 500 errors with legacy appearance logos
+merge_request: 24615
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-oauth2-callback-caps.yml b/changelogs/unreleased/sh-fix-oauth2-callback-caps.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8d17900cb79934cc2a42dee234dfe797ffcafbb4
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-oauth2-callback-caps.yml
@@ -0,0 +1,5 @@
+---
+title: Downcase aliased OAuth2 callback providers
+merge_request: 24877
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-bitbucket-mirror-constant.yml b/changelogs/unreleased/sh-remove-bitbucket-mirror-constant.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8c0b000220fb11627b28690a079fb8f98774a6ed
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-bitbucket-mirror-constant.yml
@@ -0,0 +1,5 @@
+---
+title: Fix import handling errors in Bitbucket Server importer
+merge_request: 24499
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-workhorse-8-0-2.yml b/changelogs/unreleased/update-workhorse-8-0-2.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d62e1575a0c44272091fe50805fb257b77ef093b
--- /dev/null
+++ b/changelogs/unreleased/update-workhorse-8-0-2.yml
@@ -0,0 +1,5 @@
+---
+title: Update Workhorse to v8.0.2
+merge_request: 24870
+author:
+type: fixed
diff --git a/config/routes/import.rb b/config/routes/import.rb
index 69df82611f29c1ea7873cae7804106eeea84c952..da5c31d0062492381a0e88ddda3b3ed5da2af178 100644
--- a/config/routes/import.rb
+++ b/config/routes/import.rb
@@ -1,7 +1,7 @@
# Alias import callbacks under the /users/auth endpoint so that
# the OAuth2 callback URL can be restricted under http://example.com/users/auth
# instead of http://example.com.
-Devise.omniauth_providers.each do |provider|
+Devise.omniauth_providers.map(&:downcase).each do |provider|
next if provider == 'ldapmain'
get "/users/auth/-/import/#{provider}/callback", to: "import/#{provider}#callback", as: "users_import_#{provider}_callback"
diff --git a/doc/update/11.6-to-11.7.md b/doc/update/11.6-to-11.7.md
index f5f671c1946e0ace203c0f650e378ea047ac2e6a..f9e3f565e0b0e9a284f83b3e90c14209eb3e6d13 100644
--- a/doc/update/11.6-to-11.7.md
+++ b/doc/update/11.6-to-11.7.md
@@ -66,7 +66,7 @@ from source at the nodejs.org website.
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
+GitLab also requires the use of yarn `>= v1.10.0` to manage JavaScript
dependencies.
```bash
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index e46e0f3f29ed8344608ee2a3b1c03ec414dea36e..5342c8197eabc484c9eddf792efcae3b71e486a9 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -41,7 +41,7 @@ NOTE: **Note:**
When you add an issue or an epic to an epic that's already associated with another epic,
the issue or the epic is automatically removed from the previous epic.
-## Child epics
+## Multi-level child epics
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/8333) in GitLab Ultimate 11.7.
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 1df2fe5f3cef23f1f1f0debe79d69fe331bd7cf9..fb4cc3d56dc99d9b350d6ab827b64cac4ce7b005 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -178,8 +178,11 @@ When creating a cluster in GitLab, you will be asked if you would like to create
[Attribute-based access control (ABAC)](https://kubernetes.io/docs/admin/authorization/abac/) cluster, or
a [Role-based access control (RBAC)](https://kubernetes.io/docs/admin/authorization/rbac/) one.
-Whether ABAC or RBAC is enabled, GitLab will create the necessary
-service accounts and privileges in order to install and run
+NOTE: **Note:**
+[RBAC](#role-based-access-control-rbac) is recommended and the GitLab default.
+
+Whether [ABAC](#attribute-based-access-control-abac) or [RBAC](#role-based-access-control-rbac) is enabled,
+GitLab will create the necessary service accounts and privileges in order to install and run
[GitLab managed applications](#installing-applications):
- If GitLab is creating the cluster, a `gitlab` service account with
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index b031ccce622cb39d1bcdc5e281da2524bad963cb..5d7c1c65a140692f9219b991d9b48bf3ee253ea5 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -170,3 +170,17 @@ When [renaming a user](../profile/index.md#changing-your-username),
work after a rename, making any transition a lot smoother.
- The redirects will be available as long as the original path is not claimed by
another group, user or project.
+
+## Use your project as a Go package
+
+Any project can be used as a Go package including private projects in subgroups. To use packages
+hosted in private projects with the `go get` command, use a [`.netrc` file](https://ec.haxx.se/usingcurl-netrc.html)
+and a personal access token in the password field.
+
+For example:
+
+```text
+machine example.gitlab.com
+login
+password
+```
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index 9b9b4f6c8ca05b5fa1a14848ed8e8db21458ab0f..a79bc2bce06645af88a35d5912298c7c289f4735 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -10,7 +10,8 @@ Currently supported exporters are:
- [Kubernetes](kubernetes.md)
- [NGINX](nginx.md)
-- [NGINX Ingress Controller](nginx_ingress.md)
+- [NGINX Ingress Controller 0.9.0-0.15.x](nginx_ingress_vts.md)
+- [NGINX Ingress Controller 0.16.0+](nginx_ingress.md)
- [HAProxy](haproxy.md)
- [Amazon Cloud Watch](cloudwatch.md)
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index 40ac855c74fdc3090f0c8516e76b1f819a3fc9c8..7755ba8e2e881748b936dbc8cee1d7e6d1fe55ab 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -1,8 +1,10 @@
# Monitoring NGINX Ingress Controller
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438) in GitLab 9.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22133) in GitLab 11.7.
-GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the built in Prometheus metrics included in [version 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1) and above of the ingress.
+NOTE: **Note:** NGINX Ingress versions prior to 0.16.0 offer an included [VTS Prometheus metrics exporter](nginx_ingress_vts.md), which exports metrics different than the built-in metrics.
+
+GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the built-in Prometheus metrics included starting with [version 0.16.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0160).
## Requirements
@@ -12,27 +14,29 @@ GitLab has support for automatically detecting and monitoring the Kubernetes NGI
| Name | Query |
| ---- | ----- |
-| Throughput (req/sec) | sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code) |
-| Latency (ms) | avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}) |
-| HTTP Error Rate (%) | sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100 |
+| Throughput (req/sec) | sum(label_replace(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m]), "status_code", "${1}xx", "status", "(.)..")) by (status_code) |
+| Latency (ms) | sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_sum{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_ingress_upstream_latency_seconds_count{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 1000 |
+| HTTP Error Rate (%) | sum(rate(nginx_ingress_controller_requests{status=~"5.*",namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) / sum(rate(nginx_ingress_controller_requests{namespace="%{kube_namespace}",ingress=~".*%{ci_environment_slug}.*"}[2m])) * 100 |
## Configuring NGINX ingress monitoring
If you have deployed NGINX Ingress using GitLab's [Kubernetes cluster integration](../../clusters/index.md#installing-applications), it will [automatically be monitored](#about-managed-nginx-ingress-deployments) by Prometheus.
For other deployments, there is [some configuration](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) required depending on your installation:
-* NGINX Ingress should be version 0.9.0 or above, with metrics enabled
-* NGINX Ingress should be annotated for Prometheus monitoring
-* Prometheus should be configured to monitor annotated pods
+
+- NGINX Ingress should be version 0.16.0 or above, with metrics enabled.
+- NGINX Ingress should be annotated for Prometheus monitoring.
+- Prometheus should be configured to monitor annotated pods.
### About managed NGINX Ingress deployments
NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's IP](../../clusters/index.md#getting-the-external-ip-address).
NGINX is configured for Prometheus monitoring, by setting:
-* `enable-vts-status: "true"`, to export Prometheus metrics
-* `prometheus.io/scrape: "true"`, to enable automatic discovery
-* `prometheus.io/port: "10254"`, to specify the metrics port
+
+- `enable-vts-status: "true"`, to export Prometheus metrics.
+- `prometheus.io/scrape: "true"`, to enable automatic discovery.
+- `prometheus.io/port: "10254"`, to specify the metrics port.
When used in conjunction with the GitLab deployed Prometheus service, response metrics will be automatically collected.
@@ -49,6 +53,6 @@ Managing these settings depends on how NGINX ingress has been deployed. If you h
## Specifying the Environment label
-In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do this, GitLab will search for metrics with appropriate labels. In this case, the `upstream` label must be of the form `--*`.
+In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do this, GitLab will search for metrics with appropriate labels. In this case, the `ingress` label must ``.
If you have used [Auto Deploy](../../../../topics/autodevops/index.md#auto-deploy) to deploy your app, this format will be used automatically and metrics will be detected with no action on your part.
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
new file mode 100644
index 0000000000000000000000000000000000000000..081eb8732ad3343a3c1cbe0adf3297a3690e8aca
--- /dev/null
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress_vts.md
@@ -0,0 +1,58 @@
+# Monitoring NGINX Ingress Controller with VTS metrics
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438) in GitLab 9.5.
+
+NOTE: **Note:** [NGINX Ingress version 0.16](nginx_ingress.md) and above have built-in Prometheus metrics, which are different than the VTS based metrics.
+
+GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the included VTS Prometheus metrics exporter in [version 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1) through [0.15.x](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#0150).
+
+## Requirements
+
+[Prometheus integration](../prometheus.md) must be active.
+
+## Metrics supported
+
+| Name | Query |
+| ---- | ----- |
+| Throughput (req/sec) | sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) by (status_code) |
+| Latency (ms) | avg(nginx_upstream_response_msecs_avg{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}) |
+| HTTP Error Rate (%) | sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"%{kube_namespace}-%{ci_environment_slug}-.*"}[2m])) * 100 |
+
+## Configuring NGINX ingress monitoring
+
+If you have deployed NGINX Ingress using GitLab's [Kubernetes cluster integration](../../clusters/index.md#installing-applications), it will [automatically be monitored](#about-managed-nginx-ingress-deployments) by Prometheus.
+
+For other deployments, there is [some configuration](#manually-setting-up-nginx-ingress-for-prometheus-monitoring) required depending on your installation:
+
+- NGINX Ingress should be version 0.9.0 or above, with metrics enabled.
+- NGINX Ingress should be annotated for Prometheus monitoring.
+- Prometheus should be configured to monitor annotated pods.
+
+### About managed NGINX Ingress deployments
+
+NGINX Ingress is deployed into the `gitlab-managed-apps` namespace, using the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress). NGINX Ingress will be [externally reachable via the Load Balancer's IP](../../clusters/index.md#getting-the-external-ip-address).
+
+NGINX is configured for Prometheus monitoring, by setting:
+
+- `enable-vts-status: "true"`, to export Prometheus metrics.
+- `prometheus.io/scrape: "true"`, to enable automatic discovery.
+- `prometheus.io/port: "10254"`, to specify the metrics port.
+
+When used in conjunction with the GitLab deployed Prometheus service, response metrics will be automatically collected.
+
+### Manually setting up NGINX Ingress for Prometheus monitoring
+
+Version 0.9.0 and above of [NGINX ingress](https://github.com/kubernetes/ingress-nginx) have built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint will start running on port 10254.
+
+Next, the ingress needs to be annotated for Prometheus monitoring. Two new annotations need to be added:
+
+- `prometheus.io/scrape: "true"`
+- `prometheus.io/port: "10254"`
+
+Managing these settings depends on how NGINX ingress has been deployed. If you have deployed via the [official Helm chart](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress), metrics can be enabled with `controller.stats.enabled` along with the required annotations. Alternatively it is possible edit the NGINX ingress YML directly in the [Kubernetes dashboard](https://github.com/kubernetes/dashboard).
+
+## Specifying the Environment label
+
+In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do this, GitLab will search for metrics with appropriate labels. In this case, the `upstream` label must be of the form `--*`.
+
+If you have used [Auto Deploy](../../../../topics/autodevops/index.md#auto-deploy) to deploy your app, this format will be used automatically and metrics will be detected with no action on your part.
diff --git a/doc/user/project/operations/error_tracking.md b/doc/user/project/operations/error_tracking.md
index 2b5abc7233f6f8b2c66553c2ef899e54e224c7e7..c79fbad57658d9a14ab44305186e46697e04f93a 100644
--- a/doc/user/project/operations/error_tracking.md
+++ b/doc/user/project/operations/error_tracking.md
@@ -1,6 +1,6 @@
# Error Tracking
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/169) in GitLab 11.7.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/169) in GitLab 11.8.
Error tracking allows developers to easily discover and view the errors that their application may be generating. By surfacing error information where the code is being developed, efficiency and awareness can be increased.
diff --git a/ee/app/assets/javascripts/related_issues/components/related_issues_block.vue b/ee/app/assets/javascripts/related_issues/components/related_issues_block.vue
index 89c6f1de180c7c45248fc1b54bd3cc317a163a93..ec9e868a2f2052cf11cb4839363cded46a2c536e 100644
--- a/ee/app/assets/javascripts/related_issues/components/related_issues_block.vue
+++ b/ee/app/assets/javascripts/related_issues/components/related_issues_block.vue
@@ -6,6 +6,7 @@ import sortableConfig from 'ee/sortable/sortable_config';
import { GlLoadingIcon } from '@gitlab/ui';
import issueItem from './issue_item.vue';
import addIssuableForm from './add_issuable_form.vue';
+import { issuableIconMap, issuableQaClassMap } from '../constants';
export default {
name: 'RelatedIssuesBlock',
@@ -99,6 +100,12 @@ export default {
hasHelpPath() {
return this.helpPath.length > 0;
},
+ issuableTypeIcon() {
+ return issuableIconMap[this.issuableType];
+ },
+ qaClass() {
+ return issuableQaClassMap[this.issuableType];
+ },
},
mounted() {
if (this.canReorder) {
@@ -168,7 +175,8 @@ export default {
v-if="canAdmin"
ref="issueCountBadgeAddButton"
type="button"
- class="js-issue-count-badge-add-button issue-count-badge-add-button btn btn-sm btn-default qa-add-issues-button"
+ :class="qaClass"
+ class="js-issue-count-badge-add-button issue-count-badge-add-button btn btn-sm btn-default"
aria-label="Add an issue"
data-placement="top"
@click="$emit('toggleAddRelatedIssuesForm', $event);"
diff --git a/ee/app/assets/javascripts/related_issues/constants.js b/ee/app/assets/javascripts/related_issues/constants.js
index 2c88809cb77da489c1a5efa24b380fe5213f8615..97433a86a7054981140e09b2f8cfce371a483c5f 100644
--- a/ee/app/assets/javascripts/related_issues/constants.js
+++ b/ee/app/assets/javascripts/related_issues/constants.js
@@ -30,3 +30,23 @@ export const addRelatedIssueErrorMap = {
issue: __("We can't find an issue that matches what you are looking for."),
epic: __("We can't find an epic that matches what you are looking for."),
};
+
+/**
+ * These are used to map issuableType to the correct icon.
+ * Since these are never used for any display purposes, don't wrap
+ * them inside i18n functions.
+ */
+export const issuableIconMap = {
+ issue: 'issues',
+ epic: 'epic',
+};
+
+/**
+ * These are used to map issuableType to the correct QA class.
+ * Since these are never used for any display purposes, don't wrap
+ * them inside i18n functions.
+ */
+export const issuableQaClassMap = {
+ issue: 'qa-add-issues-button',
+ epic: 'qa-add-epics-button',
+};
diff --git a/ee/app/assets/stylesheets/pages/boards.scss b/ee/app/assets/stylesheets/pages/boards.scss
index 58bb5d004788cbf308830ead9e00aba6da2cb8aa..25d9aca95fec0f4bea766518c8a89be4d5b91141 100644
--- a/ee/app/assets/stylesheets/pages/boards.scss
+++ b/ee/app/assets/stylesheets/pages/boards.scss
@@ -109,4 +109,10 @@
$search-box-height: 50px;
max-height: calc(#{$dropdown-max-height} - #{$search-box-height});
}
+
+ // the following is a workaround until we have it fixed in gitlab-ui
+ // see https://gitlab.com/gitlab-org/gitlab-ui/issues/156
+ .sticky-top {
+ top: 0;
+ }
}
diff --git a/ee/app/helpers/ee/kerberos_spnego_helper.rb b/ee/app/helpers/ee/kerberos_spnego_helper.rb
index b592a3e3c333be4ee41ffd4ab7a7644884d80d15..1f7317a9332403c088ab9c3a6350f1ebca64dfa0 100644
--- a/ee/app/helpers/ee/kerberos_spnego_helper.rb
+++ b/ee/app/helpers/ee/kerberos_spnego_helper.rb
@@ -66,7 +66,7 @@ def spnego_credentials!(spnego_token)
# pass service name to acquire_credentials explicitly to support the special meaning of nil
gss_service_name =
if ::Gitlab.config.kerberos.service_principal_name.present?
- gss.import_name(Gitlab.config.kerberos.service_principal_name)
+ gss.import_name(::Gitlab.config.kerberos.service_principal_name)
else
nil # accept any valid service principal name from keytab
end
diff --git a/ee/app/views/projects/settings/operations/_tracing.html.haml b/ee/app/views/projects/settings/operations/_tracing.html.haml
index 5a849c13be764cb9665c83e21c361640d12a391f..a3a4fd458677e8c46b8babd61cd2b9a5b2845c5c 100644
--- a/ee/app/views/projects/settings/operations/_tracing.html.haml
+++ b/ee/app/views/projects/settings/operations/_tracing.html.haml
@@ -4,7 +4,7 @@
- has_jaeger_url = setting.external_url.present?
%section.settings.expanded.border-0.no-animate
- .settings-header{ :class => ("border-top" unless not Feature.enabled?(:error_tracking, @project)) }
+ .settings-header{ :class => "border-top" }
%h4
= _("Jaeger tracing")
%p
diff --git a/ee/changelogs/unreleased/1979-blobs-at.yml b/ee/changelogs/unreleased/1979-blobs-at.yml
new file mode 100644
index 0000000000000000000000000000000000000000..75edc4e4b12433b586aef12523e3c1208e9bd81f
--- /dev/null
+++ b/ee/changelogs/unreleased/1979-blobs-at.yml
@@ -0,0 +1,5 @@
+---
+title: Fix background migration error when project repository is missing
+merge_request: 9392
+author:
+type: fixed
diff --git a/ee/changelogs/unreleased/9519-kerberos-spnego-authentication-is-broken-since-a-code-refactoring.yml b/ee/changelogs/unreleased/9519-kerberos-spnego-authentication-is-broken-since-a-code-refactoring.yml
new file mode 100644
index 0000000000000000000000000000000000000000..0ff5954dafcdd3be793ae985372815b191b1a83a
--- /dev/null
+++ b/ee/changelogs/unreleased/9519-kerberos-spnego-authentication-is-broken-since-a-code-refactoring.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Kerberos authentication
+merge_request: 9390
+author:
+type: fixed
diff --git a/ee/spec/helpers/ee/appearances_helper_spec.rb b/ee/spec/helpers/ee/appearances_helper_spec.rb
index 00607d5f25b6c694272dc8e5bfc19cd3d864138e..2d44043f462b2d7ec038b87b6e7545da5a33be0c 100644
--- a/ee/spec/helpers/ee/appearances_helper_spec.rb
+++ b/ee/spec/helpers/ee/appearances_helper_spec.rb
@@ -60,6 +60,28 @@
end
end
+ describe '#brand_image' do
+ let!(:appearance) { create(:appearance, :with_logo) }
+
+ context 'when there is a logo' do
+ it 'returns a path' do
+ expect(helper.brand_image).to match(%r(img data-src="/uploads/-/system/appearance/.*png))
+ end
+ end
+
+ context 'when there is a logo but no associated upload' do
+ before do
+ # Legacy attachments were not tracked in the uploads table
+ appearance.logo.upload.destroy
+ appearance.reload
+ end
+
+ it 'falls back to using the original path' do
+ expect(helper.brand_image).to match(%r(img data-src="/uploads/-/system/appearance/.*png))
+ end
+ end
+ end
+
describe '#brand_title' do
it 'returns the default EE title when no appearance is present' do
allow(helper)
diff --git a/ee/spec/helpers/kerberos_spnego_helper_spec.rb b/ee/spec/helpers/kerberos_spnego_helper_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..48f785c9c163594516d9d5bb0bddf993039af82b
--- /dev/null
+++ b/ee/spec/helpers/kerberos_spnego_helper_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+require 'gssapi'
+
+describe KerberosSpnegoHelper do
+ describe '#spnego_credentials!' do
+ let(:gss) { double('GSSAPI::Simple') }
+ let(:gss_service_name) { 'gss_service_name' }
+ subject { Class.new { include KerberosSpnegoHelper }.new }
+
+ before do
+ expect(GSSAPI::Simple).to receive(:new)
+ .with(nil, nil, ::Gitlab.config.kerberos.keytab)
+ .and_return(gss)
+ end
+
+ shared_examples 'a method that decodes a spnego token' do
+ let(:gss_result) { true }
+ let(:spnego_response_token) { nil }
+
+ it 'decodes the given spnego token' do
+ token = 'abc123'
+ gss_display_name = 'gss_display_name'
+
+ expect(gss).to receive(:acquire_credentials).with(gss_service_name)
+ expect(gss).to receive(:accept_context).with(token).and_return(gss_result)
+ expect(gss).to receive(:display_name).and_return(gss_display_name)
+
+ expect(subject.spnego_credentials!(token)).to eq(gss_display_name)
+ expect(subject.spnego_response_token).to eq(spnego_response_token)
+ end
+ end
+
+ context 'with Kerberos service_principal_name present' do
+ before do
+ kerberos_service_principal_name = 'default'
+ stub_kerberos_setting(service_principal_name: kerberos_service_principal_name)
+ expect(gss).to receive(:import_name).with(kerberos_service_principal_name).and_return(gss_service_name)
+ end
+
+ it_behaves_like 'a method that decodes a spnego token'
+
+ context 'when gss_result is not true' do
+ it_behaves_like 'a method that decodes a spnego token' do
+ let(:gss_result) { 'gss_result' }
+ let(:spnego_response_token) { gss_result }
+ end
+ end
+ end
+
+ context 'with Kerberos service_principal_name missing' do
+ before do
+ expect(gss).not_to receive(:import_name)
+ end
+
+ it_behaves_like 'a method that decodes a spnego token' do
+ let(:gss_service_name) { nil }
+ end
+ end
+ end
+end
diff --git a/ee/spec/lib/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb b/ee/spec/lib/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb
index 04268c4670c01a85b08dacfc92010d3744bf7bfc..53e3c76234748ecda9290ab4faea6f7f87fb9bac 100644
--- a/ee/spec/lib/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb
+++ b/ee/spec/lib/gitlab/background_migration/migrate_approver_to_approval_rules_spec.rb
@@ -253,4 +253,16 @@ def create_member_in(member, *populate_in)
end.not_to raise_error
end
end
+
+ context 'when project has no repository' do
+ let(:project_without_repository) { create(:project) }
+ let(:target) { create(:merge_request, target_project: project_without_repository, source_project: project_without_repository) }
+ let(:target_type) { 'MergeRequest' }
+
+ it "does not err" do
+ expect do
+ described_class.new.perform(target_type, target.id)
+ end.not_to raise_error
+ end
+ end
end
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index 28cfb46e2d4984da6ff611df909c9e44929d7815..dbbedd5dcbeabdae8c6724395682eca6cf6192d9 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -132,7 +132,7 @@ def import_repository
project.repository.fetch_as_mirror(project.import_url, refmap: self.class.refmap, remote_name: REMOTE_NAME)
log_info(stage: 'import_repository', message: 'finished import')
- rescue Gitlab::Shell::Error, Gitlab::Git::RepositoryMirroring::RemoteError => e
+ rescue Gitlab::Shell::Error => e
log_error(stage: 'import_repository', message: 'failed import', error: e.message)
# Expire cache to prevent scenarios such as:
@@ -140,7 +140,7 @@ def import_repository
# 2. Retried import, repo is broken or not imported but +exists?+ still returns true
project.repository.expire_content_cache if project.repository_exists?
- raise e.message
+ raise
end
# Bitbucket Server keeps tracks of references for open pull requests in
diff --git a/qa/qa/ee/page/group/epic/show.rb b/qa/qa/ee/page/group/epic/show.rb
index 523d3ace401a1fd05a574a022fb1714ead7db181..489aa5349b139dafb062794f9bbd03bb7677b1a1 100644
--- a/qa/qa/ee/page/group/epic/show.rb
+++ b/qa/qa/ee/page/group/epic/show.rb
@@ -8,7 +8,7 @@ module Epic
class Show < QA::Page::Base
include QA::Page::Component::Issuable::Common
- view 'ee/app/assets/javascripts/related_issues/components/related_issues_block.vue' do
+ view 'ee/app/assets/javascripts/related_issues/constants.js' do
element :add_issues_button
end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
index b9580d81171c1bbbb42738c52f697c7133dc9297..6c5e91b6488cf53251829ca07c9af77d33b2bb7f 100644
--- a/qa/qa/resource/user.rb
+++ b/qa/qa/resource/user.rb
@@ -17,11 +17,11 @@ def initialize
end
def username
- @username ||= "qa-user-#{unique_id}"
+ @username || "qa-user-#{unique_id}"
end
def password
- @password ||= 'password'
+ @password || 'password'
end
def name
@@ -29,7 +29,15 @@ def name
end
def email
- @email ||= api_resource&.dig(:email) || "#{username}@example.com"
+ @email ||= "#{username}@example.com"
+ end
+
+ def public_email
+ @public_email ||= begin
+ api_public_email = api_resource&.dig(:public_email)
+
+ api_public_email && api_public_email != '' ? api_public_email : Runtime::User.default_email
+ end
end
def credentials_given?
diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb
index 5eb7a210fce4d756e1d37fa2ad9935f4e9ad5674..e8bcb8a9f504beeb6266b76d9b569730f6be1afa 100644
--- a/qa/qa/runtime/user.rb
+++ b/qa/qa/runtime/user.rb
@@ -7,6 +7,10 @@ def default_username
'root'
end
+ def default_email
+ 'admin@example.com'
+ end
+
def default_password
'5iveL!fe'
end
diff --git a/qa/qa/specs/features/browser_ui/2_plan/ee_epic/create_edit_delete_epic_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/ee_epic/create_edit_delete_epic_spec.rb
index c0f3ee12e2d277d7320dbc53a38c89de22b85d8e..fdfa6bd9782d1662d52723e47f30de63200ab626 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/ee_epic/create_edit_delete_epic_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/ee_epic/create_edit_delete_epic_spec.rb
@@ -15,32 +15,35 @@ module QA
epic = EE::Resource::Epic.fabricate! do |epic|
epic.group = issue.project.group
- epic.title = "My First Epic"
+ epic.title = 'My First Epic'
end
- expect(page).to have_content(/My First Epic/)
+ expect(page).to have_content('My First Epic')
# Edit Epics
EE::Page::Group::Epic::Show.act { go_to_edit_page }
EE::Page::Group::Epic::Edit.perform do |edit_page|
- edit_page.set_description("My Edited Epic Description")
- edit_page.set_title("My Edited Epic")
+ edit_page.set_description('My Edited Epic Description')
+ edit_page.set_title('My Edited Epic')
edit_page.save_changes
- expect(edit_page).to have_content(/My Edited Epic/)
+ expect(edit_page).to have_content('My Edited Epic')
end
# Add/Remove Issues to/from Epics
EE::Page::Group::Epic::Show.perform do |show_page|
show_page.add_issue_to_epic(issue.web_url)
+ expect(show_page).to have_content('added issue')
+ expect(show_page).to have_content('My Edited Epic')
+
show_page.remove_issue_from_epic
- expect(show_page).to have_content(/removed issue/)
+ expect(show_page).to have_content('removed issue')
end
# Comment on Epics
- EE::Page::Group::Epic::Show.act { add_comment_to_epic("My Epic Comments") }
+ EE::Page::Group::Epic::Show.act { add_comment_to_epic('My Epic Comments') }
- expect(page).to have_content(/My Epic Comments/)
+ expect(page).to have_content('My Epic Comments')
# Add Issue to Epic using quick actions
issue.visit!
@@ -49,30 +52,30 @@ module QA
show_page.select_all_activities_filter
show_page.comment("/epic #{epic.web_url}")
show_page.comment("/remove_epic")
- expect(show_page).to have_content(/removed from epic/)
+ expect(show_page).to have_content('removed from epic')
end
epic.visit!
- expect(page).to have_content("added issue", count: 2)
- expect(page).to have_content("removed issue", count: 2)
+ expect(page).to have_content('added issue', count: 2)
+ expect(page).to have_content('removed issue', count: 2)
# Close Epic
EE::Page::Group::Epic::Show.act { close_reopen_epic }
- expect(page).to have_content(/Closed/)
+ expect(page).to have_content('Closed')
# Reopen Epic
EE::Page::Group::Epic::Show.act { close_reopen_epic }
- expect(page).to have_content(/Open/)
+ expect(page).to have_content('Open')
# Delete Epics
EE::Page::Group::Epic::Show.act { go_to_edit_page }
EE::Page::Group::Epic::Edit.perform do |edit_page|
edit_page.delete_epic
- expect(edit_page).to have_content(/The epic was successfully deleted/)
+ expect(edit_page).to have_content('The epic was successfully deleted')
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
index 3a5d89e6b837a5b9db0904bb3db41bbfdc205e5a..b862a7bd1edf966f8f0102dde9c82db9a52b658f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
@@ -2,7 +2,10 @@
module QA
context 'Create' do
- describe 'Commit data' do
+ # failure reported: https://gitlab.com/gitlab-org/quality/nightly/issues/42
+ # also failing in staging until the fix is picked into the next release:
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24533
+ describe 'Commit data', :quarantine do
before(:context) do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -47,7 +50,7 @@ def raw_content
Page::Project::Commit::Show.perform(&:select_email_patches)
- expect(page).to have_content("From: #{user.name} <#{user.email}>")
+ expect(page).to have_content("From: #{user.name} <#{user.public_email}>")
expect(page).to have_content('Subject: [PATCH] Add second file')
expect(page).to have_content('diff --git a/second b/second')
end
diff --git a/qa/spec/resource/user_spec.rb b/qa/spec/resource/user_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d612dfc530e60ec3a8bd0473e1caaf9ff26e2cec
--- /dev/null
+++ b/qa/spec/resource/user_spec.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+describe QA::Resource::User do
+ let(:api_resource) do
+ {
+ name: "GitLab QA",
+ username: "gitlab-qa",
+ web_url: "https://staging.gitlab.com/gitlab-qa",
+ public_email: "1614863-gitlab-qa@users.noreply.staging.gitlab.com"
+ }
+ end
+
+ describe '#username' do
+ it 'generates a default username' do
+ expect(subject.username).to match(/qa-user-\w+/)
+ end
+
+ it 'is possible to set the username' do
+ subject.username = 'johndoe'
+
+ expect(subject.username).to eq('johndoe')
+ end
+ end
+
+ describe '#password' do
+ it 'generates a default password' do
+ expect(subject.password).to eq('password')
+ end
+
+ it 'is possible to set the password' do
+ subject.password = 'secret'
+
+ expect(subject.password).to eq('secret')
+ end
+ end
+
+ describe '#name' do
+ it 'defaults to the username' do
+ expect(subject.name).to eq(subject.username)
+ end
+
+ it 'retrieves the name from the api_resource if present' do
+ subject.__send__(:api_resource=, api_resource)
+
+ expect(subject.name).to eq(api_resource[:name])
+ end
+
+ it 'is possible to set the name' do
+ subject.name = 'John Doe'
+
+ expect(subject.name).to eq('John Doe')
+ end
+ end
+
+ describe '#email' do
+ it 'defaults to the @example.com' do
+ expect(subject.email).to eq("#{subject.username}@example.com")
+ end
+
+ it 'is possible to set the email' do
+ subject.email = 'johndoe@example.org'
+
+ expect(subject.email).to eq('johndoe@example.org')
+ end
+ end
+
+ describe '#public_email' do
+ it 'defaults to QA::Runtime::User.default_email' do
+ expect(subject.public_email).to eq(QA::Runtime::User.default_email)
+ end
+
+ it 'retrieves the public_email from the api_resource if present' do
+ subject.__send__(:api_resource=, api_resource)
+
+ expect(subject.public_email).to eq(api_resource[:public_email])
+ end
+
+ it 'defaults to QA::Runtime::User.default_email if the public_email from the api_resource is blank' do
+ subject.__send__(:api_resource=, api_resource.merge(public_email: ''))
+
+ expect(subject.public_email).to eq(QA::Runtime::User.default_email)
+ end
+ end
+
+ describe '#credentials_given?' do
+ it 'returns false when username and email have not been overridden' do
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns false even after username and email have been called' do
+ # Call #username and #password to ensure this doesn't set their respective
+ # instance variable.
+ subject.username
+ subject.password
+
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns false if only the username has been overridden' do
+ subject.username = 'johndoe'
+
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns false if only the password has been overridden' do
+ subject.password = 'secret'
+
+ expect(subject).not_to be_credentials_given
+ end
+
+ it 'returns true if both the username and password have been overridden' do
+ subject.username = 'johndoe'
+ subject.password = 'secret'
+
+ expect(subject).to be_credentials_given
+ end
+ end
+end
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 118a7c7f638ff6defb1084e2c3930f96b91c3b2d..3e3c0fe2ea850dd02438cc28c17f1d5b3c0a48b6 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -149,19 +149,19 @@ HELM_CMD=$(cat << EOF
--set redis.resources.requests.cpu=100m \
--set minio.resources.requests.cpu=100m \
--set gitlab.migrations.image.repository="$gitlab_migrations_image_repository" \
- --set gitlab.migrations.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.migrations.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.sidekiq.image.repository="$gitlab_sidekiq_image_repository" \
- --set gitlab.sidekiq.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.sidekiq.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.unicorn.image.repository="$gitlab_unicorn_image_repository" \
- --set gitlab.unicorn.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.unicorn.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.task-runner.image.repository="$gitlab_task_runner_image_repository" \
- --set gitlab.task-runner.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.task-runner.image.tag="$CI_COMMIT_REF_SLUG" \
--set gitlab.gitaly.image.repository="registry.gitlab.com/gitlab-org/build/cng-mirror/gitaly" \
--set gitlab.gitaly.image.tag="v$GITALY_VERSION" \
--set gitlab.gitlab-shell.image.repository="registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-shell" \
--set gitlab.gitlab-shell.image.tag="v$GITLAB_SHELL_VERSION" \
--set gitlab.unicorn.workhorse.image="$gitlab_workhorse_image_repository" \
- --set gitlab.unicorn.workhorse.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.unicorn.workhorse.tag="$CI_COMMIT_REF_SLUG" \
--set nginx-ingress.controller.config.ssl-ciphers="ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" \
--namespace="$KUBE_NAMESPACE" \
--version="$CI_PIPELINE_ID-$CI_JOB_ID" \
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 4032ba853e6bb1cd21e7a77aeedc77ebdb6db79f..9dbafffddfc305b92bba5004c5b3cee33c68f807 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -68,7 +68,7 @@ module Trigger
def base_variables
{
- 'GITLAB_REF_SLUG' => ENV['CI_COMMIT_REF_SLUG'],
+ 'GITLAB_REF_SLUG' => ENV['CI_COMMIT_TAG'] ? ENV['CI_COMMIT_REF_NAME'] : ENV['CI_COMMIT_REF_SLUG'],
'TRIGGERED_USER' => ENV['TRIGGERED_USER'] || ENV['GITLAB_USER_NAME'],
'TRIGGER_SOURCE' => ENV['CI_JOB_URL'],
'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'],
@@ -137,7 +137,11 @@ module Trigger
edition = Trigger.ee? ? 'EE' : 'CE'
{
+ # Back-compatibility until https://gitlab.com/gitlab-org/build/CNG/merge_requests/189 is merged
"GITLAB_#{edition}_VERSION" => ENV['CI_COMMIT_REF_NAME'],
+ "GITLAB_VERSION" => ENV['CI_COMMIT_REF_NAME'],
+ "GITLAB_TAG" => ENV['CI_COMMIT_TAG'],
+ "GITLAB_ASSETS_TAG" => ENV['CI_COMMIT_REF_SLUG'],
"#{edition}_PIPELINE" => 'true'
}
end
diff --git a/spec/controllers/projects/error_tracking_controller_spec.rb b/spec/controllers/projects/error_tracking_controller_spec.rb
index 729e71b87a671d46b957632df2951413d9fc59ab..6464398cea1c85be51c5726a77dfea95c1bffec5 100644
--- a/spec/controllers/projects/error_tracking_controller_spec.rb
+++ b/spec/controllers/projects/error_tracking_controller_spec.rb
@@ -20,18 +20,6 @@
expect(response).to render_template(:index)
end
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(error_tracking: false)
- end
-
- it 'returns 404' do
- get :index, params: project_params
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
context 'with insufficient permissions' do
before do
project.add_guest(user)
diff --git a/spec/controllers/projects/settings/operations_controller_spec.rb b/spec/controllers/projects/settings/operations_controller_spec.rb
index 810f5bb64ba54db22cd63787143bf13c3e6521ec..d989ec224819f1dfef3bc3b8d36bcd38bf76c217 100644
--- a/spec/controllers/projects/settings/operations_controller_spec.rb
+++ b/spec/controllers/projects/settings/operations_controller_spec.rb
@@ -41,18 +41,6 @@
end
end
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(error_tracking: false)
- end
-
- it 'renders 404' do
- get :show, params: project_params(project)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
context 'with insufficient permissions' do
before do
project.add_reporter(user)
@@ -121,18 +109,6 @@
end
end
- context 'with feature flag disabled' do
- before do
- stub_feature_flags(error_tracking: false)
- end
-
- it 'renders 404' do
- patch :update, params: project_params(project)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
context 'with insufficient permissions' do
before do
project.add_reporter(user)
diff --git a/spec/features/projects/settings/operations_settings_spec.rb b/spec/features/projects/settings/operations_settings_spec.rb
index 1f2328a6dd81f52ec4c36d8f342909eda1ff3605..06290c67c70729f47003163a5f93cac524061727 100644
--- a/spec/features/projects/settings/operations_settings_spec.rb
+++ b/spec/features/projects/settings/operations_settings_spec.rb
@@ -8,32 +8,16 @@
let(:role) { :maintainer }
before do
- stub_feature_flags(error_tracking: true)
sign_in(user)
project.add_role(user, role)
end
describe 'Sidebar > Operations' do
- context 'when sidebar feature flag enabled' do
- it 'renders the settings link in the sidebar' do
- visit project_path(project)
- wait_for_requests
+ it 'renders the settings link in the sidebar' do
+ visit project_path(project)
+ wait_for_requests
- expect(page).to have_selector('a[title="Operations"]', visible: false)
- end
- end
-
- context 'when sidebar feature flag disabled' do
- before do
- stub_feature_flags(error_tracking: false)
- end
-
- it 'does not render the settings link in the sidebar' do
- visit project_path(project)
- wait_for_requests
-
- expect(page).not_to have_selector('a[title="Operations"]', visible: false)
- end
+ expect(page).to have_selector('a[title="Operations"]', visible: false)
end
end
end
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..ebb2844d17facf4049b764db27523bcaf41f186f
--- /dev/null
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Project > Tags', :js do
+ include DropzoneHelper
+
+ let(:user) { create(:user) }
+ let(:role) { :developer }
+ let(:project) { create(:project, :repository) }
+
+ before do
+ sign_in(user)
+ project.add_role(user, role)
+ end
+
+ describe 'when opening project tags' do
+ before do
+ visit project_tags_path(project)
+ end
+
+ context 'page with tags list' do
+ it 'shows tag name' do
+ page.within first('.tags > .content-list > li') do
+ expect(page.find('.row-main-content')).to have_content 'v1.1.0 Version 1.1.0'
+ end
+ end
+
+ it 'shows tag edit button' do
+ page.within first('.tags > .content-list > li') do
+ edit_btn = page.find('.row-fixed-content.controls a.btn-edit')
+
+ expect(edit_btn['href']).to have_content '/tags/v1.1.0/release/edit'
+ end
+ end
+ end
+
+ context 'edit tag release notes' do
+ before do
+ find('.tags > .content-list > li:first-child .row-fixed-content.controls a.btn-edit').click
+ end
+
+ it 'shows tag name header' do
+ page.within('.content') do
+ expect(page.find('.sub-header-block')).to have_content 'Release notes for tag v1.1.0'
+ end
+ end
+
+ it 'shows release notes form' do
+ page.within('.content') do
+ expect(page).to have_selector('form.release-form')
+ end
+ end
+
+ it 'toolbar buttons on release notes form are functional' do
+ page.within('.content form.release-form') do
+ note_textarea = page.find('.js-gfm-input')
+
+ # Click on Bold button
+ page.find('.md-header-toolbar button.toolbar-btn:first-child').click
+
+ expect(note_textarea.value).to eq('****')
+ end
+ end
+
+ it 'release notes form shows "Attach a file" button', :js do
+ page.within('.content form.release-form') do
+ expect(page).to have_button('Attach a file')
+ expect(page).not_to have_selector('.uploading-progress-container', visible: true)
+ end
+ end
+
+ it 'shows "Attaching a file" message on uploading 1 file', :js do
+ slow_requests do
+ dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false)
+
+ expect(page).to have_selector('.attaching-file-message', visible: true, text: 'Attaching a file -')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index cc75c57358a3f819de548eb48472494070684bac..839d9387c1e1551874f5042335f3ea1bd765c672 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -381,21 +381,16 @@
end
context 'when project has external wiki' do
- before do
- allow(project).to receive(:has_external_wiki?).and_return(true)
- end
-
it 'includes external wiki tab' do
+ project.create_external_wiki_service(active: true, properties: { 'external_wiki_url' => 'https://gitlab.com' })
+
is_expected.to include(:external_wiki)
end
end
context 'when project does not have external wiki' do
- before do
- allow(project).to receive(:has_external_wiki?).and_return(false)
- end
-
it 'does not include external wiki tab' do
+ expect(project.external_wiki).to be_nil
is_expected.not_to include(:external_wiki)
end
end
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index 70423823b8971c7a726a318e17856925203b86da..1e90a2ef27f95b50d94eead59b2944272a508523 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -21,12 +21,9 @@
end
describe '#import_repository' do
- before do
+ it 'adds a remote' do
expect(subject).to receive(:import_pull_requests)
expect(subject).to receive(:delete_temp_branches)
- end
-
- it 'adds a remote' do
expect(project.repository).to receive(:fetch_as_mirror)
.with('http://bitbucket:test@my-bitbucket',
refmap: [:heads, :tags, '+refs/pull-requests/*/to:refs/merge-requests/*/head'],
@@ -34,6 +31,18 @@
subject.execute
end
+
+ it 'raises a Gitlab::Shell exception in the fetch' do
+ expect(project.repository).to receive(:fetch_as_mirror).and_raise(Gitlab::Shell::Error)
+
+ expect { subject.execute }.to raise_error(Gitlab::Shell::Error)
+ end
+
+ it 'raises an unhandled exception in the fetch' do
+ expect(project.repository).to receive(:fetch_as_mirror).and_raise(RuntimeError)
+
+ expect { subject.execute }.to raise_error(RuntimeError)
+ end
end
describe '#import_pull_requests' do
diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb
index ec2e7d672f050ad6a7f6427b6ea7019f6680fd75..cc76a2019eca27cee2692e975af779280c8a04da 100644
--- a/spec/models/appearance_spec.rb
+++ b/spec/models/appearance_spec.rb
@@ -36,6 +36,13 @@
expect(subject.send("#{logo_type}_path")).to be_nil
end
+ it 'returns the path when the upload has been orphaned' do
+ appearance.send(logo_type).upload.destroy
+ appearance.reload
+
+ expect(appearance.send("#{logo_type}_path")).to eq(expected_path)
+ end
+
it 'returns a local path using the system route' do
expect(appearance.send("#{logo_type}_path")).to eq(expected_path)
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index ac5874fd0f7a4454104df0fd5e801b895eea84d6..4978c43c9b5ccc00924f9c76236743a288e42bf9 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1237,6 +1237,27 @@ def expect_to_raise_storage_error
end
end
+ describe '#blobs_at' do
+ let(:empty_repository) { create(:project_empty_repo).repository }
+
+ it 'returns empty array for an empty repository' do
+ # rubocop:disable Style/WordArray
+ expect(empty_repository.blobs_at(['master', 'foobar'])).to eq([])
+ # rubocop:enable Style/WordArray
+ end
+
+ it 'returns blob array for a non-empty repository' do
+ repository.create_file(User.last, 'foobar', 'CONTENT', message: 'message', branch_name: 'master')
+
+ # rubocop:disable Style/WordArray
+ blobs = repository.blobs_at([['master', 'foobar']])
+ # rubocop:enable Style/WordArray
+
+ expect(blobs.first.name).to eq('foobar')
+ expect(blobs.size).to eq(1)
+ end
+ end
+
describe '#root_ref' do
it 'returns a branch name' do
expect(repository.root_ref).to be_an_instance_of(String)
diff --git a/spec/models/ssh_host_key_spec.rb b/spec/models/ssh_host_key_spec.rb
index 75db43b3d56e67e3fbce52de5d036354738db754..23a94334172cb46ac54b48cc6e19924c79c57999 100644
--- a/spec/models/ssh_host_key_spec.rb
+++ b/spec/models/ssh_host_key_spec.rb
@@ -50,6 +50,12 @@ def stub_ssh_keyscan(args, status: true, stdout: "", stderr: "")
subject(:ssh_host_key) { described_class.new(project: project, url: 'ssh://example.com:2222', compare_host_keys: compare_host_keys) }
+ describe '.primary_key' do
+ it 'returns a symbol' do
+ expect(described_class.primary_key).to eq(:id)
+ end
+ end
+
describe '#fingerprints', :use_clean_rails_memory_store_caching do
it 'returns an array of indexed fingerprints when the cache is filled' do
stub_reactive_cache(ssh_host_key, known_hosts: known_hosts)
diff --git a/spec/services/suggestions/apply_service_spec.rb b/spec/services/suggestions/apply_service_spec.rb
index e5ca1c155ed890149f5e0bd3da845358c55586a7..8e77d582eb4a87a95fd83f03e1f5ae6ae28dd234 100644
--- a/spec/services/suggestions/apply_service_spec.rb
+++ b/spec/services/suggestions/apply_service_spec.rb
@@ -134,12 +134,11 @@ def popen(cmd, path=nil)
end
end
- context 'when diff ref from position is different from repo diff refs' do
+ context 'when HEAD from position is different from source branch HEAD on repo' do
it 'returns error message' do
- outdated_refs = Gitlab::Diff::DiffRefs.new(base_sha: 'foo', start_sha: 'bar', head_sha: 'outdated')
-
allow(suggestion).to receive(:appliable?) { true }
- allow(suggestion.position).to receive(:diff_refs) { outdated_refs }
+ allow(suggestion.position).to receive(:head_sha) { 'old-sha' }
+ allow(suggestion.noteable).to receive(:source_branch_sha) { 'new-sha' }
result = subject.execute(suggestion)
diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb
index 752fd82c5e893ff53d1e3e7e8288776a7dfbcc4c..8e34521c7c86fa6d9e96c3d9f0309861854b6bd7 100644
--- a/spec/views/projects/settings/operations/show.html.haml_spec.rb
+++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb
@@ -13,8 +13,6 @@
describe 'Operations > Error Tracking' do
before do
- stub_feature_flags(error_tracking: true)
-
project.add_reporter(user)
allow(view).to receive(:error_tracking_setting)