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 @@ class Projects::ErrorTrackingController < Projects::ApplicationController .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 a1cac080bd2ff840215b30adfc9fc33943fa007c..4408cb5145a8faa2ad61d8d709acf663c5133a08 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -285,7 +285,7 @@ module ProjectsHelper # 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 @@ -328,7 +328,7 @@ module ProjectsHelper 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 e114c435b67b6f2ba007a78fadac3528c3240109..ff1ecfda684422f393f52da1ed181db66e6aa9cc 100644 --- a/app/models/appearance.rb +++ b/app/models/appearance.rb @@ -44,7 +44,11 @@ class Appearance < ActiveRecord::Base 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 b47238b52f16ffcb123d8e3116ce24167cdaf0a3..e6ab3b484a2ade5d6701f2c3528a8be4cfd5e674 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -525,6 +525,8 @@ class Repository # 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 @@ class SshHostKey # 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 @@ module Suggestions 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 @@ module Suggestions 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 758a12ea9f3dda1c858ba5d90ded823cd2f89e1d..a63c6ff21ab602255c5930689f8898a0e91227f5 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/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/project/clusters/index.md b/doc/user/project/clusters/index.md index 6f334af4fb71ea21e205e4edf8f3f87e73f49ed5..bb815695cb10ab98e7008313b5901320d54f5bef 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 d46ae31580ac0ccc8f9cbeec052d80ef6c5a83e7..81aad2d9312e5f1dc8778c1928eb17a0d094a83a 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -149,3 +149,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/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 @@ module Gitlab 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 @@ module Gitlab # 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/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 @@ module QA 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 @@ module QA 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 @@ module QA 'root' end + def default_email + 'admin@example.com' + end + def default_password '5iveL!fe' 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 @@ module QA 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 @@ describe Projects::ErrorTrackingController do 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 @@ describe Projects::Settings::OperationsController do 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 @@ describe Projects::Settings::OperationsController do 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 @@ describe 'Projects > Settings > For a forked project', :js do 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 10f61731206640ff8c5ae14f9c08c1c1f61d8651..990750f0b2f7790f3a3d68dbf75fef125aa4d1bf 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -372,21 +372,16 @@ describe ProjectsHelper do 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 @@ describe Gitlab::BitbucketServerImport::Importer do 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 @@ describe Gitlab::BitbucketServerImport::Importer do 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 @@ describe Appearance do 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 @@ describe Repository do 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 @@ describe SshHostKey do 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 @@ describe Suggestions::ApplyService do 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 'projects/settings/operations/show' do describe 'Operations > Error Tracking' do before do - stub_feature_flags(error_tracking: true) - project.add_reporter(user) allow(view).to receive(:error_tracking_setting)