From 29c01c6c91558358c37ba45b03f240632bfb918d Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 14 Nov 2019 03:06:25 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- Gemfile | 2 +- Gemfile.lock | 4 +- .../javascripts/ide/components/repo_editor.vue | 1 + .../components/content_viewer/content_viewer.vue | 6 ++ .../content_viewer/viewers/markdown_viewer.vue | 6 ++ app/controllers/concerns/preview_markdown.rb | 22 ++++---- app/models/clusters/applications/elastic_stack.rb | 29 ++++++++++ app/models/clusters/concerns/application_core.rb | 18 ++++++ app/models/environment.rb | 5 +- app/models/project.rb | 2 +- app/services/base_service.rb | 12 +++- app/services/commits/change_service.rb | 5 +- app/services/commits/create_service.rb | 13 ++++- .../enable-environment-dashboard-on-prod.yml | 5 ++ ...fj-32057-web-ide-preview-markdown-image-bug.yml | 5 ++ .../gdk-672-bump-puma-killer-limits-for-dev.yml | 5 ++ changelogs/unreleased/helm-v2-16-1.yml | 5 ++ .../rs-change-service-failure-reasons.yml | 5 ++ doc/api/commits.md | 28 +++++++++ doc/user/clusters/management_project.md | 17 +++++- lib/api/commits.rb | 4 +- .../Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml | 2 +- lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml | 2 +- .../cluster/puma_worker_killer_initializer.rb | 13 ++++- lib/gitlab/git/repository.rb | 11 +++- lib/gitlab/gitaly_client/operation_service.rb | 2 +- lib/gitlab/kubernetes/helm.rb | 2 +- spec/controllers/admin/clusters_controller_spec.rb | 25 ++++---- .../admin/identities_controller_spec.rb | 8 ++- .../controllers/admin/spam_logs_controller_spec.rb | 4 +- spec/controllers/import/gitlab_controller_spec.rb | 5 +- .../projects/discussions_controller_spec.rb | 16 ++++-- .../projects/mattermosts_controller_spec.rb | 13 +++-- .../merge_requests/creations_controller_spec.rb | 4 +- .../merge_requests/diffs_controller_spec.rb | 8 ++- spec/controllers/projects/notes_controller_spec.rb | 4 +- .../projects/project_members_controller_spec.rb | 8 ++- .../projects/prometheus/metrics_controller_spec.rb | 4 +- .../projects/settings/ci_cd_controller_spec.rb | 8 ++- .../projects/snippets_controller_spec.rb | 12 +++- spec/controllers/projects_controller_spec.rb | 24 ++++++++ spec/controllers/users_controller_spec.rb | 4 +- spec/features/admin/admin_projects_spec.rb | 5 +- spec/features/admin/admin_users_spec.rb | 4 +- spec/features/cycle_analytics_spec.rb | 8 ++- spec/features/global_search_spec.rb | 4 +- spec/features/groups/clusters/user_spec.rb | 8 ++- .../issuables/markdown_references/jira_spec.rb | 4 +- .../user_squashes_merge_request_spec.rb | 4 +- spec/features/projects/clusters/user_spec.rb | 8 ++- .../projects/commits/user_browses_commits_spec.rb | 12 +++- spec/features/projects/compare_spec.rb | 4 +- .../projects/environments/environment_spec.rb | 5 +- .../projects/environments/environments_spec.rb | 4 +- spec/features/projects/features_visibility_spec.rb | 8 ++- .../projects/import_export/export_file_spec.rb | 4 +- .../projects/import_export/import_file_spec.rb | 4 +- spec/features/projects/pages_lets_encrypt_spec.rb | 4 +- .../security/project/internal_access_spec.rb | 8 ++- .../security/project/private_access_spec.rb | 8 ++- .../security/project/public_access_spec.rb | 8 ++- spec/features/tags/developer_deletes_tag_spec.rb | 6 +- spec/features/users/signup_spec.rb | 4 +- spec/frontend/fixtures/u2f.rb | 4 +- spec/helpers/markup_helper_spec.rb | 29 ++++++++++ .../content_viewer/content_viewer_spec.js | 26 +++++++++ .../gitlab/gitaly_client/operation_service_spec.rb | 6 +- spec/lib/gitlab/import_export/all_models.yml | 2 +- spec/lib/gitlab/kubernetes/helm/pod_spec.rb | 2 +- .../clusters/applications/elastic_stack_spec.rb | 66 ++++++++++++++++++++++ spec/requests/api/commits_spec.rb | 19 +++++++ spec/support/helpers/kubernetes_helpers.rb | 2 +- 72 files changed, 549 insertions(+), 109 deletions(-) create mode 100644 changelogs/unreleased/enable-environment-dashboard-on-prod.yml create mode 100644 changelogs/unreleased/fj-32057-web-ide-preview-markdown-image-bug.yml create mode 100644 changelogs/unreleased/gdk-672-bump-puma-killer-limits-for-dev.yml create mode 100644 changelogs/unreleased/helm-v2-16-1.yml create mode 100644 changelogs/unreleased/rs-change-service-failure-reasons.yml diff --git a/Gemfile b/Gemfile index 1d03c388549..ffe456cae08 100644 --- a/Gemfile +++ b/Gemfile @@ -449,7 +449,7 @@ group :ed25519 do end # Gitaly GRPC protocol definitions -gem 'gitaly', '~> 1.65.0' +gem 'gitaly', '~> 1.70.0' gem 'grpc', '~> 1.24.0' diff --git a/Gemfile.lock b/Gemfile.lock index 5d9e9b50ca0..a53485e6220 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -358,7 +358,7 @@ GEM po_to_json (>= 1.0.0) rails (>= 3.2.0) git (1.5.0) - gitaly (1.65.0) + gitaly (1.70.0) grpc (~> 1.0) github-markup (1.7.0) gitlab-labkit (0.7.0) @@ -1167,7 +1167,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly (~> 1.65.0) + gitaly (~> 1.70.0) github-markup (~> 1.7.0) gitlab-labkit (~> 0.5) gitlab-license (~> 1.0) diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index 3bf8308ccea..08b3e8a34d6 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -301,6 +301,7 @@ export default { v-if="showContentViewer" :content="file.content || file.raw" :path="file.rawPath || file.path" + :file-path="file.path" :file-size="file.size" :project-path="file.projectId" :type="fileType" diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue index 1e6f4c376c1..66155ddcdd9 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue @@ -18,6 +18,11 @@ export default { required: false, default: 0, }, + filePath: { + type: String, + required: false, + default: '', + }, projectPath: { type: String, required: false, @@ -52,6 +57,7 @@ export default { error + # If users have mistakenly set parameters or removed the depended clusters, + # `proxy_url` could raise an exception because gitlab can not communicate with the cluster. + # We check for a nil client in downstream use and behaviour is equivalent to an empty state + log_exception(error, :failed_to_create_elasticsearch_client) + end + end + private def specification @@ -74,6 +99,10 @@ module Clusters Gitlab::Kubernetes::KubectlCmd.delete("pvc", "--selector", "release=elastic-stack") ].compact end + + def kube_client + cluster&.kubeclient&.core_client + end end end end diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb index 979cf0645f5..21b98534808 100644 --- a/app/models/clusters/concerns/application_core.rb +++ b/app/models/clusters/concerns/application_core.rb @@ -60,6 +60,24 @@ module Clusters # Override if your application needs any action after # being uninstalled by Helm end + + def logger + @logger ||= Gitlab::Kubernetes::Logger.build + end + + def log_exception(error, event) + logger.error({ + exception: error.class.name, + status_code: error.error_code, + cluster_id: cluster&.id, + application_id: id, + class_name: self.class.name, + event: event, + message: error.message + }) + + Gitlab::Sentry.track_acceptable_exception(error, extra: { cluster_id: cluster&.id, application_id: id }) + end end end end diff --git a/app/models/environment.rb b/app/models/environment.rb index 6bc244b1df4..569299ad4b4 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -12,7 +12,7 @@ class Environment < ApplicationRecord has_one :last_deployment, -> { success.order('deployments.id DESC') }, class_name: 'Deployment' has_one :last_deployable, through: :last_deployment, source: 'deployable', source_type: 'CommitStatus' has_one :last_pipeline, through: :last_deployable, source: 'pipeline' - has_one :last_visible_deployment, -> { visible.distinct_on_environment }, class_name: 'Deployment' + has_one :last_visible_deployment, -> { visible.distinct_on_environment }, inverse_of: :environment, class_name: 'Deployment' has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus' has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline' @@ -66,6 +66,9 @@ class Environment < ApplicationRecord scope :for_project, -> (project) { where(project_id: project) } scope :with_deployment, -> (sha) { where('EXISTS (?)', Deployment.select(1).where('deployments.environment_id = environments.id').where(sha: sha)) } scope :unfoldered, -> { where(environment_type: nil) } + scope :with_rank, -> do + select('environments.*, rank() OVER (PARTITION BY project_id ORDER BY id DESC)') + end state_machine :state, initial: :available do event :start do diff --git a/app/models/project.rb b/app/models/project.rb index 8b31a7ea48b..1df2a981658 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -287,7 +287,7 @@ class Project < ApplicationRecord has_many :variables, class_name: 'Ci::Variable' has_many :triggers, class_name: 'Ci::Trigger' has_many :environments - has_many :unfoldered_environments, -> { unfoldered.available }, class_name: 'Environment' + has_many :environments_for_dashboard, -> { from(with_rank.unfoldered.available, :environments).where('rank <= 3') }, class_name: 'Environment' has_many :deployments has_many :pipeline_schedules, class_name: 'Ci::PipelineSchedule' has_many :project_deploy_tokens diff --git a/app/services/base_service.rb b/app/services/base_service.rb index c39edd5c114..bc0b968f516 100644 --- a/app/services/base_service.rb +++ b/app/services/base_service.rb @@ -50,16 +50,24 @@ class BaseService private - def error(message, http_status = nil) + # Return a Hash with an `error` status + # + # message - Error message to include in the Hash + # http_status - Optional HTTP status code override (default: nil) + # pass_back - Additional attributes to be included in the resulting Hash + def error(message, http_status = nil, pass_back: {}) result = { message: message, status: :error - } + }.reverse_merge(pass_back) result[:http_status] = http_status if http_status result end + # Return a Hash with a `success` status + # + # pass_back - Additional attributes to be included in the resulting Hash def success(pass_back = {}) pass_back[:status] = :success pass_back diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb index fbf71f02837..661e654406e 100644 --- a/app/services/commits/change_service.rb +++ b/app/services/commits/change_service.rb @@ -23,14 +23,15 @@ module Commits message, start_project: @start_project, start_branch_name: @start_branch) - rescue Gitlab::Git::Repository::CreateTreeError + rescue Gitlab::Git::Repository::CreateTreeError => ex act = action.to_s.dasherize type = @commit.change_type_title(current_user) error_msg = "Sorry, we cannot #{act} this #{type} automatically. " \ "This #{type} may already have been #{act}ed, or a more recent " \ "commit may have updated some of its content." - raise ChangeError, error_msg + + raise ChangeError.new(error_msg, ex.error_code) end end end diff --git a/app/services/commits/create_service.rb b/app/services/commits/create_service.rb index b5401a8ea37..b42494563b2 100644 --- a/app/services/commits/create_service.rb +++ b/app/services/commits/create_service.rb @@ -3,7 +3,15 @@ module Commits class CreateService < ::BaseService ValidationError = Class.new(StandardError) - ChangeError = Class.new(StandardError) + class ChangeError < StandardError + attr_reader :error_code + + def initialize(message, error_code = nil) + super(message) + + @error_code = error_code + end + end def initialize(*args) super @@ -21,8 +29,9 @@ module Commits new_commit = create_commit! success(result: new_commit) + rescue ChangeError => ex + error(ex.message, pass_back: { error_code: ex.error_code }) rescue ValidationError, - ChangeError, Gitlab::Git::Index::IndexError, Gitlab::Git::CommitError, Gitlab::Git::PreReceiveError, diff --git a/changelogs/unreleased/enable-environment-dashboard-on-prod.yml b/changelogs/unreleased/enable-environment-dashboard-on-prod.yml new file mode 100644 index 00000000000..47da49ca8aa --- /dev/null +++ b/changelogs/unreleased/enable-environment-dashboard-on-prod.yml @@ -0,0 +1,5 @@ +--- +title: Enable environments dashboard by default +merge_request: 19838 +author: +type: added diff --git a/changelogs/unreleased/fj-32057-web-ide-preview-markdown-image-bug.yml b/changelogs/unreleased/fj-32057-web-ide-preview-markdown-image-bug.yml new file mode 100644 index 00000000000..237f6bb6840 --- /dev/null +++ b/changelogs/unreleased/fj-32057-web-ide-preview-markdown-image-bug.yml @@ -0,0 +1,5 @@ +--- +title: Fix broken images when previewing markdown files in Web IDE +merge_request: 18899 +author: +type: fixed diff --git a/changelogs/unreleased/gdk-672-bump-puma-killer-limits-for-dev.yml b/changelogs/unreleased/gdk-672-bump-puma-killer-limits-for-dev.yml new file mode 100644 index 00000000000..67b93cf95df --- /dev/null +++ b/changelogs/unreleased/gdk-672-bump-puma-killer-limits-for-dev.yml @@ -0,0 +1,5 @@ +--- +title: Increase PumaWorkerKiller memory limit in development environment +merge_request: 20039 +author: +type: performance diff --git a/changelogs/unreleased/helm-v2-16-1.yml b/changelogs/unreleased/helm-v2-16-1.yml new file mode 100644 index 00000000000..15abf254915 --- /dev/null +++ b/changelogs/unreleased/helm-v2-16-1.yml @@ -0,0 +1,5 @@ +--- +title: Helm v2.16.1 +merge_request: 19981 +author: +type: fixed diff --git a/changelogs/unreleased/rs-change-service-failure-reasons.yml b/changelogs/unreleased/rs-change-service-failure-reasons.yml new file mode 100644 index 00000000000..28a04d28680 --- /dev/null +++ b/changelogs/unreleased/rs-change-service-failure-reasons.yml @@ -0,0 +1,5 @@ +--- +title: 'Add an `error_code` attribute to the API response when a cherry-pick or revert fails.' +merge_request: 19518 +author: +type: added diff --git a/doc/api/commits.md b/doc/api/commits.md index 3f2932f2666..f4bb09843c8 100644 --- a/doc/api/commits.md +++ b/doc/api/commits.md @@ -317,6 +317,21 @@ Example response: } ``` +In the event of a failed cherry-pick, the response will provide context about +why: + +```json +{ + "message": "Sorry, we cannot cherry-pick this commit automatically. This commit may already have been cherry-picked, or a more recent commit may have updated some of its content.", + "error_code": "empty" +} +``` + +In this case, the cherry-pick failed because the changeset was empty and likely +indicates that the commit already exists in the target branch. The other +possible error code is `conflict`, which indicates that there was a merge +conflict. + ## Revert a commit > [Introduced][ce-22919] in GitLab 11.5. @@ -358,6 +373,19 @@ Example response: } ``` +In the event of a failed revert, the response will provide context about why: + +```json +{ + "message": "Sorry, we cannot revert this commit automatically. This commit may already have been reverted, or a more recent commit may have updated some of its content.", + "error_code": "conflict" +} +``` + +In this case, the revert failed because the attempted revert generated a merge +conflict. The other possible error code is `empty`, which indicates that the +changeset was empty, likely due to the change having already been reverted. + ## Get the diff of a commit Get the diff of a commit in a project. diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md index 6cee781ff3d..a052239448f 100644 --- a/doc/user/clusters/management_project.md +++ b/doc/user/clusters/management_project.md @@ -32,10 +32,23 @@ Management projects are restricted to the following: ## Usage +To use a cluster management project for a cluster: + +1. Select the project. +1. Configure your pipelines. +1. Set an environment scope. + ### Selecting a cluster management project -You can select a management project for the cluster under **Advanced -settings**. +To select a cluster management project to use: + +1. Navigate to the appropriate configuration page. For a: + - [Project-level cluster](../project/clusters/index.md), navigate to your project's + **Operations > Kubernetes** page. + - [Group-level cluster](../group/clusters/index.md), navigate to your group's **Kubernetes** + page. +1. Select the project using **Cluster management project field** in the **Advanced settings** + section. ![Selecting a cluster management project under Advanced settings](img/advanced-settings-cluster-management-project-v12_5.png) diff --git a/lib/api/commits.rb b/lib/api/commits.rb index 3b9ac602c56..63a7fdfa3ab 100644 --- a/lib/api/commits.rb +++ b/lib/api/commits.rb @@ -223,7 +223,7 @@ module API present user_project.repository.commit(result[:result]), with: Entities::Commit else - render_api_error!(result[:message], 400) + error!(result.slice(:message, :error_code), 400, header) end end @@ -257,7 +257,7 @@ module API present user_project.repository.commit(result[:result]), with: Entities::Commit else - render_api_error!(result[:message], 400) + error!(result.slice(:message, :error_code), 400, header) end end diff --git a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml index a888f146664..7a672f910dd 100644 --- a/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml @@ -1,5 +1,5 @@ .dast-auto-deploy: - image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.4.0" + image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.6.0" dast_environment_deploy: extends: .dast-auto-deploy diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml index a95714d5684..c2d55fb3b86 100644 --- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml @@ -1,5 +1,5 @@ .auto-deploy: - image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.4.0" + image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.6.0" review: extends: .auto-deploy diff --git a/lib/gitlab/cluster/puma_worker_killer_initializer.rb b/lib/gitlab/cluster/puma_worker_killer_initializer.rb index a8440b63baa..92c799875b5 100644 --- a/lib/gitlab/cluster/puma_worker_killer_initializer.rb +++ b/lib/gitlab/cluster/puma_worker_killer_initializer.rb @@ -3,7 +3,12 @@ module Gitlab module Cluster class PumaWorkerKillerInitializer - def self.start(puma_options, puma_per_worker_max_memory_mb: 850, puma_master_max_memory_mb: 550) + def self.start( + puma_options, + puma_per_worker_max_memory_mb: 850, + puma_master_max_memory_mb: 550, + additional_puma_dev_max_memory_mb: 200 + ) require 'puma_worker_killer' PumaWorkerKiller.config do |config| @@ -14,7 +19,11 @@ module Gitlab # The Puma Worker Killer checks the total RAM used by both the master # and worker processes. # https://github.com/schneems/puma_worker_killer/blob/v0.1.0/lib/puma_worker_killer/puma_memory.rb#L57 - config.ram = puma_master_max_memory_mb + (worker_count * puma_per_worker_max_memory_mb) + # + # Additional memory is added when running in `development` + config.ram = puma_master_max_memory_mb + + (worker_count * puma_per_worker_max_memory_mb) + + (Rails.env.development? ? (1 + worker_count) * additional_puma_dev_max_memory_mb : 0) config.frequency = 20 # seconds diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index b2c22898079..4971a18e270 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -25,9 +25,18 @@ module Gitlab InvalidRef = Class.new(StandardError) GitError = Class.new(StandardError) DeleteBranchError = Class.new(StandardError) - CreateTreeError = Class.new(StandardError) TagExistsError = Class.new(StandardError) ChecksumError = Class.new(StandardError) + class CreateTreeError < StandardError + attr_reader :error_code + + def initialize(error_code) + super(self.class.name) + + # The value coming from Gitaly is an uppercase String (e.g., "EMPTY") + @error_code = error_code.downcase.to_sym + end + end # Directory name of repo attr_reader :name diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb index 6e486c763da..61c5db4c4df 100644 --- a/lib/gitlab/gitaly_client/operation_service.rb +++ b/lib/gitlab/gitaly_client/operation_service.rb @@ -447,7 +447,7 @@ module Gitlab elsif response.commit_error.presence raise Gitlab::Git::CommitError, response.commit_error elsif response.create_tree_error.presence - raise Gitlab::Git::Repository::CreateTreeError, response.create_tree_error + raise Gitlab::Git::Repository::CreateTreeError, response.create_tree_error_code end Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update) diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb index 5762c77bb95..b5181670b93 100644 --- a/lib/gitlab/kubernetes/helm.rb +++ b/lib/gitlab/kubernetes/helm.rb @@ -3,7 +3,7 @@ module Gitlab module Kubernetes module Helm - HELM_VERSION = '2.15.1' + HELM_VERSION = '2.16.1' KUBECTL_VERSION = '1.13.12' NAMESPACE = 'gitlab-managed-apps' SERVICE_ACCOUNT = 'tiller' diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb index e6decd24f0a..ebae931764d 100644 --- a/spec/controllers/admin/clusters_controller_spec.rb +++ b/spec/controllers/admin/clusters_controller_spec.rb @@ -227,16 +227,17 @@ describe Admin::ClustersController do describe 'security' do before do - allow_any_instance_of(described_class) - .to receive(:token_in_session).and_return('token') - allow_any_instance_of(described_class) - .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s) - allow_any_instance_of(GoogleApi::CloudPlatform::Client) - .to receive(:projects_zones_clusters_create) do - OpenStruct.new( - self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', - status: 'RUNNING' - ) + allow_next_instance_of(described_class) do |instance| + allow(instance).to receive(:token_in_session).and_return('token') + allow(instance).to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s) + end + allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance| + allow(instance).to receive(:projects_zones_clusters_create) do + OpenStruct.new( + self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123', + status: 'RUNNING' + ) + end end allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil) @@ -467,7 +468,9 @@ describe Admin::ClustersController do end it 'invokes schedule_status_update on each application' do - expect_any_instance_of(Clusters::Applications::Ingress).to receive(:schedule_status_update) + expect_next_instance_of(Clusters::Applications::Ingress) do |instance| + expect(instance).to receive(:schedule_status_update) + end get_cluster_status end diff --git a/spec/controllers/admin/identities_controller_spec.rb b/spec/controllers/admin/identities_controller_spec.rb index 68695afdb61..256aafe09f8 100644 --- a/spec/controllers/admin/identities_controller_spec.rb +++ b/spec/controllers/admin/identities_controller_spec.rb @@ -13,7 +13,9 @@ describe Admin::IdentitiesController do let(:user) { create(:omniauth_user, provider: 'ldapmain', extern_uid: 'uid=myuser,ou=people,dc=example,dc=com') } it 'repairs ldap blocks' do - expect_any_instance_of(RepairLdapBlockedUserService).to receive(:execute) + expect_next_instance_of(RepairLdapBlockedUserService) do |instance| + expect(instance).to receive(:execute) + end put :update, params: { user_id: user.username, id: user.ldap_identity.id, identity: { provider: 'twitter' } } end @@ -23,7 +25,9 @@ describe Admin::IdentitiesController do let(:user) { create(:omniauth_user, provider: 'ldapmain', extern_uid: 'uid=myuser,ou=people,dc=example,dc=com') } it 'repairs ldap blocks' do - expect_any_instance_of(RepairLdapBlockedUserService).to receive(:execute) + expect_next_instance_of(RepairLdapBlockedUserService) do |instance| + expect(instance).to receive(:execute) + end delete :destroy, params: { user_id: user.username, id: user.ldap_identity.id } end diff --git a/spec/controllers/admin/spam_logs_controller_spec.rb b/spec/controllers/admin/spam_logs_controller_spec.rb index d8c96501f5c..baf4216dcde 100644 --- a/spec/controllers/admin/spam_logs_controller_spec.rb +++ b/spec/controllers/admin/spam_logs_controller_spec.rb @@ -39,7 +39,9 @@ describe Admin::SpamLogsController do describe '#mark_as_ham' do before do - allow_any_instance_of(AkismetService).to receive(:submit_ham).and_return(true) + allow_next_instance_of(AkismetService) do |instance| + allow(instance).to receive(:submit_ham).and_return(true) + end end it 'submits the log as ham' do post :mark_as_ham, params: { id: first_spam.id } diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb index e465eca6c71..6a3713a1212 100644 --- a/spec/controllers/import/gitlab_controller_spec.rb +++ b/spec/controllers/import/gitlab_controller_spec.rb @@ -20,8 +20,9 @@ describe Import::GitlabController do describe "GET callback" do it "updates access token" do - allow_any_instance_of(Gitlab::GitlabImport::Client) - .to receive(:get_token).and_return(token) + allow_next_instance_of(Gitlab::GitlabImport::Client) do |instance| + allow(instance).to receive(:get_token).and_return(token) + end stub_omniauth_provider('gitlab') get :callback diff --git a/spec/controllers/projects/discussions_controller_spec.rb b/spec/controllers/projects/discussions_controller_spec.rb index 6ed822bbb10..d59f76c1b32 100644 --- a/spec/controllers/projects/discussions_controller_spec.rb +++ b/spec/controllers/projects/discussions_controller_spec.rb @@ -104,7 +104,9 @@ describe Projects::DiscussionsController do end it "sends notifications if all discussions are resolved" do - expect_any_instance_of(MergeRequests::ResolvedDiscussionNotificationService).to receive(:execute).with(merge_request) + expect_next_instance_of(MergeRequests::ResolvedDiscussionNotificationService) do |instance| + expect(instance).to receive(:execute).with(merge_request) + end post :resolve, params: request_params end @@ -122,8 +124,10 @@ describe Projects::DiscussionsController do end it "renders discussion with serializer" do - expect_any_instance_of(DiscussionSerializer).to receive(:represent) - .with(instance_of(Discussion), { context: instance_of(described_class), render_truncated_diff_lines: true }) + expect_next_instance_of(DiscussionSerializer) do |instance| + expect(instance).to receive(:represent) + .with(instance_of(Discussion), { context: instance_of(described_class), render_truncated_diff_lines: true }) + end post :resolve, params: request_params end @@ -193,8 +197,10 @@ describe Projects::DiscussionsController do end it "renders discussion with serializer" do - expect_any_instance_of(DiscussionSerializer).to receive(:represent) - .with(instance_of(Discussion), { context: instance_of(described_class), render_truncated_diff_lines: true }) + expect_next_instance_of(DiscussionSerializer) do |instance| + expect(instance).to receive(:represent) + .with(instance_of(Discussion), { context: instance_of(described_class), render_truncated_diff_lines: true }) + end delete :unresolve, params: request_params end diff --git a/spec/controllers/projects/mattermosts_controller_spec.rb b/spec/controllers/projects/mattermosts_controller_spec.rb index 45125385d9e..64440ed585d 100644 --- a/spec/controllers/projects/mattermosts_controller_spec.rb +++ b/spec/controllers/projects/mattermosts_controller_spec.rb @@ -13,8 +13,9 @@ describe Projects::MattermostsController do describe 'GET #new' do before do - allow_any_instance_of(MattermostSlashCommandsService) - .to receive(:list_teams).and_return([]) + allow_next_instance_of(MattermostSlashCommandsService) do |instance| + allow(instance).to receive(:list_teams).and_return([]) + end end it 'accepts the request' do @@ -42,7 +43,9 @@ describe Projects::MattermostsController do context 'no request can be made to mattermost' do it 'shows the error' do - allow_any_instance_of(MattermostSlashCommandsService).to receive(:configure).and_return([false, "error message"]) + allow_next_instance_of(MattermostSlashCommandsService) do |instance| + allow(instance).to receive(:configure).and_return([false, "error message"]) + end expect(subject).to redirect_to(new_project_mattermost_url(project)) end @@ -50,7 +53,9 @@ describe Projects::MattermostsController do context 'the request is succesull' do before do - allow_any_instance_of(Mattermost::Command).to receive(:create).and_return('token') + allow_next_instance_of(Mattermost::Command) do |instance| + allow(instance).to receive(:create).and_return('token') + end end it 'redirects to the new page' do diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb index ce977f26ec6..1bbb80f9904 100644 --- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb @@ -85,7 +85,9 @@ describe Projects::MergeRequests::CreationsController do describe 'GET diffs' do context 'when merge request cannot be created' do it 'does not assign diffs var' do - allow_any_instance_of(MergeRequest).to receive(:can_be_created).and_return(false) + allow_next_instance_of(MergeRequest) do |instance| + allow(instance).to receive(:can_be_created).and_return(false) + end get :diffs, params: get_diff_params.merge(format: 'json') diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb index 4f6a7de5ae7..06d9af33189 100644 --- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb +++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb @@ -86,7 +86,9 @@ describe Projects::MergeRequests::DiffsController do end it 'serializes merge request diff collection' do - expect_any_instance_of(DiffsSerializer).to receive(:represent).with(an_instance_of(Gitlab::Diff::FileCollection::MergeRequestDiff), an_instance_of(Hash)) + expect_next_instance_of(DiffsSerializer) do |instance| + expect(instance).to receive(:represent).with(an_instance_of(Gitlab::Diff::FileCollection::MergeRequestDiff), an_instance_of(Hash)) + end go end @@ -98,7 +100,9 @@ describe Projects::MergeRequests::DiffsController do end it 'serializes merge request diff collection' do - expect_any_instance_of(DiffsSerializer).to receive(:represent).with(an_instance_of(Gitlab::Diff::FileCollection::MergeRequestDiff), an_instance_of(Hash)) + expect_next_instance_of(DiffsSerializer) do |instance| + expect(instance).to receive(:represent).with(an_instance_of(Gitlab::Diff::FileCollection::MergeRequestDiff), an_instance_of(Hash)) + end go end diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb index e9d285aa0b0..e576a3d2d40 100644 --- a/spec/controllers/projects/notes_controller_spec.rb +++ b/spec/controllers/projects/notes_controller_spec.rb @@ -785,7 +785,9 @@ describe Projects::NotesController do end it "sends notifications if all discussions are resolved" do - expect_any_instance_of(MergeRequests::ResolvedDiscussionNotificationService).to receive(:execute).with(merge_request) + expect_next_instance_of(MergeRequests::ResolvedDiscussionNotificationService) do |instance| + expect(instance).to receive(:execute).with(merge_request) + end post :resolve, params: request_params end diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb index 2f473d395ad..072df1f5060 100644 --- a/spec/controllers/projects/project_members_controller_spec.rb +++ b/spec/controllers/projects/project_members_controller_spec.rb @@ -45,7 +45,9 @@ describe Projects::ProjectMembersController do end it 'adds user to members' do - expect_any_instance_of(Members::CreateService).to receive(:execute).and_return(status: :success) + expect_next_instance_of(Members::CreateService) do |instance| + expect(instance).to receive(:execute).and_return(status: :success) + end post :create, params: { namespace_id: project.namespace, @@ -59,7 +61,9 @@ describe Projects::ProjectMembersController do end it 'adds no user to members' do - expect_any_instance_of(Members::CreateService).to receive(:execute).and_return(status: :failure, message: 'Message') + expect_next_instance_of(Members::CreateService) do |instance| + expect(instance).to receive(:execute).and_return(status: :failure, message: 'Message') + end post :create, params: { namespace_id: project.namespace, diff --git a/spec/controllers/projects/prometheus/metrics_controller_spec.rb b/spec/controllers/projects/prometheus/metrics_controller_spec.rb index 17f9483be98..afdb8bbc983 100644 --- a/spec/controllers/projects/prometheus/metrics_controller_spec.rb +++ b/spec/controllers/projects/prometheus/metrics_controller_spec.rb @@ -85,7 +85,9 @@ describe Projects::Prometheus::MetricsController do end it 'calls prometheus adapter service' do - expect_any_instance_of(::Prometheus::AdapterService).to receive(:prometheus_adapter) + expect_next_instance_of(::Prometheus::AdapterService) do |instance| + expect(instance).to receive(:prometheus_adapter) + end subject.__send__(:prometheus_adapter) end diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb index c67e7f7dadd..98f8826397f 100644 --- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb +++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb @@ -125,7 +125,9 @@ describe Projects::Settings::CiCdController do context 'when run_auto_devops_pipeline is true' do before do - expect_any_instance_of(Projects::UpdateService).to receive(:run_auto_devops_pipeline?).and_return(true) + expect_next_instance_of(Projects::UpdateService) do |instance| + expect(instance).to receive(:run_auto_devops_pipeline?).and_return(true) + end end context 'when the project repository is empty' do @@ -159,7 +161,9 @@ describe Projects::Settings::CiCdController do context 'when run_auto_devops_pipeline is not true' do before do - expect_any_instance_of(Projects::UpdateService).to receive(:run_auto_devops_pipeline?).and_return(false) + expect_next_instance_of(Projects::UpdateService) do |instance| + expect(instance).to receive(:run_auto_devops_pipeline?).and_return(false) + end end it 'does not queue a CreatePipelineWorker' do diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb index 042a5542786..d372a94db56 100644 --- a/spec/controllers/projects/snippets_controller_spec.rb +++ b/spec/controllers/projects/snippets_controller_spec.rb @@ -92,7 +92,9 @@ describe Projects::SnippetsController do context 'when the snippet is spam' do before do - allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true) + allow_next_instance_of(AkismetService) do |instance| + allow(instance).to receive(:spam?).and_return(true) + end end context 'when the snippet is private' do @@ -170,7 +172,9 @@ describe Projects::SnippetsController do context 'when the snippet is spam' do before do - allow_any_instance_of(AkismetService).to receive(:spam?).and_return(true) + allow_next_instance_of(AkismetService) do |instance| + allow(instance).to receive(:spam?).and_return(true) + end end context 'when the snippet is private' do @@ -278,7 +282,9 @@ describe Projects::SnippetsController do let(:snippet) { create(:project_snippet, :private, project: project, author: user) } before do - allow_any_instance_of(AkismetService).to receive_messages(submit_spam: true) + allow_next_instance_of(AkismetService) do |instance| + allow(instance).to receive_messages(submit_spam: true) + end stub_application_setting(akismet_enabled: true) end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 22538565698..ff0259cd40d 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -927,6 +927,30 @@ describe ProjectsController do expect(json_response['body']).to match(/\!#{merge_request.iid} \(closed\)/) end end + + context 'when path parameter is provided' do + let(:project_with_repo) { create(:project, :repository) } + let(:preview_markdown_params) do + { + namespace_id: project_with_repo.namespace, + id: project_with_repo, + text: "![](./logo-white.png)\n", + path: 'files/images/README.md' + } + end + + before do + project_with_repo.add_maintainer(user) + end + + it 'renders JSON body with image links expanded' do + expanded_path = "/#{project_with_repo.full_path}/raw/master/files/images/logo-white.png" + + post :preview_markdown, params: preview_markdown_params + + expect(json_response['body']).to include(expanded_path) + end + end end describe '#ensure_canonical_path' do diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index fa057dc5b07..bbbb9691f53 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -174,7 +174,9 @@ describe UsersController do let(:user) { create(:user) } before do - allow_any_instance_of(User).to receive(:contributed_projects_ids).and_return([project.id]) + allow_next_instance_of(User) do |instance| + allow(instance).to receive(:contributed_projects_ids).and_return([project.id]) + end sign_in(user) project.add_developer(user) diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb index 058e548208f..7c40ac5bde3 100644 --- a/spec/features/admin/admin_projects_spec.rb +++ b/spec/features/admin/admin_projects_spec.rb @@ -73,8 +73,9 @@ describe "Admin::Projects" do before do create(:group, name: 'Web') - allow_any_instance_of(Projects::TransferService) - .to receive(:move_uploads_to_new_namespace).and_return(true) + allow_next_instance_of(Projects::TransferService) do |instance| + allow(instance).to receive(:move_uploads_to_new_namespace).and_return(true) + end end it 'transfers project to group web', :js do diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 29f29e58917..0c8cd895c00 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -179,7 +179,9 @@ describe "Admin::Users" do end it "calls send mail" do - expect_any_instance_of(NotificationService).to receive(:new_user) + expect_next_instance_of(NotificationService) do |instance| + expect(instance).to receive(:new_user) + end click_button "Create user" end diff --git a/spec/features/cycle_analytics_spec.rb b/spec/features/cycle_analytics_spec.rb index 3f46772c4b0..0fc4841ee0e 100644 --- a/spec/features/cycle_analytics_spec.rb +++ b/spec/features/cycle_analytics_spec.rb @@ -40,7 +40,9 @@ describe 'Cycle Analytics', :js do context "when there's cycle analytics data" do before do - allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) + allow_next_instance_of(Gitlab::ReferenceExtractor) do |instance| + allow(instance).to receive(:issues).and_return([issue]) + end project.add_maintainer(user) @build = create_cycle(user, project, issue, mr, milestone, pipeline) @@ -99,7 +101,9 @@ describe 'Cycle Analytics', :js do project.add_developer(user) project.add_guest(guest) - allow_any_instance_of(Gitlab::ReferenceExtractor).to receive(:issues).and_return([issue]) + allow_next_instance_of(Gitlab::ReferenceExtractor) do |instance| + allow(instance).to receive(:issues).and_return([issue]) + end create_cycle(user, project, issue, mr, milestone, pipeline) deploy_master(user, project) diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb index 00fa85930b1..c499fac6bc0 100644 --- a/spec/features/global_search_spec.rb +++ b/spec/features/global_search_spec.rb @@ -21,7 +21,9 @@ describe 'Global search' do describe 'I search through the issues and I see pagination' do before do - allow_any_instance_of(Gitlab::SearchResults).to receive(:per_page).and_return(1) + allow_next_instance_of(Gitlab::SearchResults) do |instance| + allow(instance).to receive(:per_page).and_return(1) + end create_list(:issue, 2, project: project, title: 'initial') end diff --git a/spec/features/groups/clusters/user_spec.rb b/spec/features/groups/clusters/user_spec.rb index 8891866c1f8..e06f2efe183 100644 --- a/spec/features/groups/clusters/user_spec.rb +++ b/spec/features/groups/clusters/user_spec.rb @@ -13,8 +13,12 @@ describe 'User Cluster', :js do gitlab_sign_in(user) allow(Groups::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 } - allow_any_instance_of(Clusters::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute) - allow_any_instance_of(Clusters::Cluster).to receive(:retrieve_connection_status).and_return(:connected) + allow_next_instance_of(Clusters::Kubernetes::CreateOrUpdateNamespaceService) do |instance| + allow(instance).to receive(:execute) + end + allow_next_instance_of(Clusters::Cluster) do |instance| + allow(instance).to receive(:retrieve_connection_status).and_return(:connected) + end end context 'when user does not have a cluster and visits cluster index page' do diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb index 596a374ec6d..c5818691b3c 100644 --- a/spec/features/issuables/markdown_references/jira_spec.rb +++ b/spec/features/issuables/markdown_references/jira_spec.rb @@ -17,7 +17,9 @@ describe "Jira", :js do stub_request(:get, "https://jira.example.com/rest/api/2/issue/JIRA-5") stub_request(:post, "https://jira.example.com/rest/api/2/issue/JIRA-5/comment") - allow_any_instance_of(JIRA::Resource::Issue).to receive(:remotelink).and_return(remotelink) + allow_next_instance_of(JIRA::Resource::Issue) do |instance| + allow(instance).to receive(:remotelink).and_return(remotelink) + end sign_in(user) diff --git a/spec/features/merge_requests/user_squashes_merge_request_spec.rb b/spec/features/merge_requests/user_squashes_merge_request_spec.rb index a018c86fa9a..a9b96c5bbf5 100644 --- a/spec/features/merge_requests/user_squashes_merge_request_spec.rb +++ b/spec/features/merge_requests/user_squashes_merge_request_spec.rb @@ -47,7 +47,9 @@ describe 'User squashes a merge request', :js do before do # Prevent source branch from being removed so we can use be_merged_to_root_ref # method to check if squash was performed or not - allow_any_instance_of(MergeRequest).to receive(:force_remove_source_branch?).and_return(false) + allow_next_instance_of(MergeRequest) do |instance| + allow(instance).to receive(:force_remove_source_branch?).and_return(false) + end project.add_maintainer(user) sign_in user diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb index 84f2e3e09ae..bdaeda83926 100644 --- a/spec/features/projects/clusters/user_spec.rb +++ b/spec/features/projects/clusters/user_spec.rb @@ -13,8 +13,12 @@ describe 'User Cluster', :js do gitlab_sign_in(user) allow(Projects::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 } - allow_any_instance_of(Clusters::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute) - allow_any_instance_of(Clusters::Cluster).to receive(:retrieve_connection_status).and_return(:connected) + allow_next_instance_of(Clusters::Kubernetes::CreateOrUpdateNamespaceService) do |instance| + allow(instance).to receive(:execute) + end + allow_next_instance_of(Clusters::Cluster) do |instance| + allow(instance).to receive(:retrieve_connection_status).and_return(:connected) + end end context 'when user does not have a cluster and visits cluster index page' do diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb index 131d9097f48..1cff7f2c385 100644 --- a/spec/features/projects/commits/user_browses_commits_spec.rb +++ b/spec/features/projects/commits/user_browses_commits_spec.rb @@ -57,7 +57,9 @@ describe 'User browses commits' do create(:ci_build, pipeline: pipeline) - allow_any_instance_of(Ci::Pipeline).to receive(:ci_yaml_file).and_return('') + allow_next_instance_of(Ci::Pipeline) do |instance| + allow(instance).to receive(:ci_yaml_file).and_return('') + end end it 'renders commit ci info' do @@ -94,8 +96,12 @@ describe 'User browses commits' do let(:commit) { create(:commit, project: project) } it 'renders successfully' do - allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(nil) - allow_any_instance_of(Gitlab::Diff::File).to receive(:binary?).and_return(true) + allow_next_instance_of(Gitlab::Diff::File) do |instance| + allow(instance).to receive(:blob).and_return(nil) + end + allow_next_instance_of(Gitlab::Diff::File) do |instance| + allow(instance).to receive(:binary?).and_return(true) + end visit(project_commit_path(project, commit)) diff --git a/spec/features/projects/compare_spec.rb b/spec/features/projects/compare_spec.rb index bdde04eec76..df5cec80ae4 100644 --- a/spec/features/projects/compare_spec.rb +++ b/spec/features/projects/compare_spec.rb @@ -107,7 +107,9 @@ describe "Compare", :js do visit project_compare_index_path(project, from: "feature", to: "master") allow(Commit).to receive(:max_diff_options).and_return(max_files: 3) - allow_any_instance_of(DiffHelper).to receive(:render_overflow_warning?).and_return(true) + allow_next_instance_of(DiffHelper) do |instance| + allow(instance).to receive(:render_overflow_warning?).and_return(true) + end click_button('Compare') diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index dd690699ff6..3eab13cb820 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -175,8 +175,9 @@ describe 'Environment' do # # In EE we have to stub EE::Environment since it overwrites # the "terminals" method. - allow_any_instance_of(Gitlab.ee? ? EE::Environment : Environment) - .to receive(:terminals) { nil } + allow_next_instance_of(Gitlab.ee? ? EE::Environment : Environment) do |instance| + allow(instance).to receive(:terminals) { nil } + end visit terminal_project_environment_path(project, environment) end diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb index 1a2302b3d0c..74c2758c30f 100644 --- a/spec/features/projects/environments/environments_spec.rb +++ b/spec/features/projects/environments/environments_spec.rb @@ -71,7 +71,9 @@ describe 'Environments page', :js do let!(:application_prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) } before do - allow_any_instance_of(Kubeclient::Client).to receive(:proxy_url).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil)) + allow_next_instance_of(Kubeclient::Client) do |instance| + allow(instance).to receive(:proxy_url).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil)) + end end it 'shows one environment without error' do diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index 9ec61743a11..5553e496e7a 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -42,7 +42,9 @@ describe 'Edit Project Settings' do context 'When external issue tracker is enabled and issues enabled on project settings' do it 'does not hide issues tab' do - allow_any_instance_of(Project).to receive(:external_issue_tracker).and_return(JiraService.new) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:external_issue_tracker).and_return(JiraService.new) + end visit project_path(project) @@ -54,7 +56,9 @@ describe 'Edit Project Settings' do it 'hides issues tab' do project.issues_enabled = false project.save! - allow_any_instance_of(Project).to receive(:external_issue_tracker).and_return(JiraService.new) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:external_issue_tracker).and_return(JiraService.new) + end visit project_path(project) diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb index b3ed550f45e..c15a3250221 100644 --- a/spec/features/projects/import_export/export_file_spec.rb +++ b/spec/features/projects/import_export/export_file_spec.rb @@ -26,7 +26,9 @@ describe 'Import/Export - project export integration test', :js do let(:project) { setup_project } before do - allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) + allow_next_instance_of(Gitlab::ImportExport) do |instance| + allow(instance).to receive(:storage_path).and_return(export_path) + end end after do diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb index 904c5390415..33c7182c084 100644 --- a/spec/features/projects/import_export/import_file_spec.rb +++ b/spec/features/projects/import_export/import_file_spec.rb @@ -11,7 +11,9 @@ describe 'Import/Export - project import integration test', :js do before do stub_uploads_object_storage(FileUploader) - allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) + allow_next_instance_of(Gitlab::ImportExport) do |instance| + allow(instance).to receive(:storage_path).and_return(export_path) + end gitlab_sign_in(user) end diff --git a/spec/features/projects/pages_lets_encrypt_spec.rb b/spec/features/projects/pages_lets_encrypt_spec.rb index 8b5964b2eee..c33a2896952 100644 --- a/spec/features/projects/pages_lets_encrypt_spec.rb +++ b/spec/features/projects/pages_lets_encrypt_spec.rb @@ -18,7 +18,9 @@ describe "Pages with Let's Encrypt", :https_pages_enabled do project.add_role(user, role) sign_in(user) project.namespace.update(owner: user) - allow_any_instance_of(Project).to receive(:pages_deployed?) { true } + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:pages_deployed?) { true } + end end context 'when the auto SSL management is initially disabled' do diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index 768b883a90e..9c1c81918fa 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -264,7 +264,9 @@ describe "Internal Project Access" do before do # Speed increase - allow_any_instance_of(Project).to receive(:branches).and_return([]) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:branches).and_return([]) + end end it { is_expected.to be_allowed_for(:admin) } @@ -283,7 +285,9 @@ describe "Internal Project Access" do before do # Speed increase - allow_any_instance_of(Project).to receive(:tags).and_return([]) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:tags).and_return([]) + end end it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index c2d44c05a22..dbaf97bc3fd 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -236,7 +236,9 @@ describe "Private Project Access" do before do # Speed increase - allow_any_instance_of(Project).to receive(:branches).and_return([]) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:branches).and_return([]) + end end it { is_expected.to be_allowed_for(:admin) } @@ -255,7 +257,9 @@ describe "Private Project Access" do before do # Speed increase - allow_any_instance_of(Project).to receive(:tags).and_return([]) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:tags).and_return([]) + end end it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 19f01257713..35cbc195f4f 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -477,7 +477,9 @@ describe "Public Project Access" do before do # Speed increase - allow_any_instance_of(Project).to receive(:branches).and_return([]) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:branches).and_return([]) + end end it { is_expected.to be_allowed_for(:admin) } @@ -496,7 +498,9 @@ describe "Public Project Access" do before do # Speed increase - allow_any_instance_of(Project).to receive(:tags).and_return([]) + allow_next_instance_of(Project) do |instance| + allow(instance).to receive(:tags).and_return([]) + end end it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/tags/developer_deletes_tag_spec.rb b/spec/features/tags/developer_deletes_tag_spec.rb index 82b416c3a7f..0fc62a578f9 100644 --- a/spec/features/tags/developer_deletes_tag_spec.rb +++ b/spec/features/tags/developer_deletes_tag_spec.rb @@ -39,8 +39,10 @@ describe 'Developer deletes tag' do context 'when pre-receive hook fails', :js do before do - allow_any_instance_of(Gitlab::GitalyClient::OperationService).to receive(:rm_tag) - .and_raise(Gitlab::Git::PreReceiveError, 'GitLab: Do not delete tags') + allow_next_instance_of(Gitlab::GitalyClient::OperationService) do |instance| + allow(instance).to receive(:rm_tag) + .and_raise(Gitlab::Git::PreReceiveError, 'GitLab: Do not delete tags') + end end it 'shows the error message' do diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index 29ff0c67dbd..3b19bd423a4 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -379,7 +379,9 @@ shared_examples 'Signup' do before do InvisibleCaptcha.timestamp_enabled = true stub_application_setting(recaptcha_enabled: true) - allow_any_instance_of(RegistrationsController).to receive(:verify_recaptcha).and_return(false) + allow_next_instance_of(RegistrationsController) do |instance| + allow(instance).to receive(:verify_recaptcha).and_return(false) + end end after do diff --git a/spec/frontend/fixtures/u2f.rb b/spec/frontend/fixtures/u2f.rb index dded6ce6380..9710fbbc181 100644 --- a/spec/frontend/fixtures/u2f.rb +++ b/spec/frontend/fixtures/u2f.rb @@ -34,7 +34,9 @@ context 'U2F' do before do sign_in(user) - allow_any_instance_of(Profiles::TwoFactorAuthsController).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares') + allow_next_instance_of(Profiles::TwoFactorAuthsController) do |instance| + allow(instance).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares') + end end it 'u2f/register.html' do diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb index 683c04428ab..5ca5f5703cf 100644 --- a/spec/helpers/markup_helper_spec.rb +++ b/spec/helpers/markup_helper_spec.rb @@ -89,6 +89,35 @@ describe MarkupHelper do end end end + + context 'when text contains a relative link to an image in the repository' do + let(:image_file) { "logo-white.png" } + let(:text_with_relative_path) { "![](./#{image_file})\n" } + let(:generated_html) { helper.markdown(text_with_relative_path, requested_path: requested_path) } + + subject { Nokogiri::HTML.parse(generated_html) } + + context 'when requested_path is provided in the context' do + let(:requested_path) { 'files/images/README.md' } + + it 'returns the correct HTML for the image' do + expanded_path = "/#{project.full_path}/raw/master/files/images/#{image_file}" + + expect(subject.css('a')[0].attr('href')).to eq(expanded_path) + expect(subject.css('img')[0].attr('data-src')).to eq(expanded_path) + end + end + + context 'when requested_path parameter is not provided' do + let(:requested_path) { nil } + + it 'returns the link to the image path as a relative path' do + expanded_path = "/#{project.full_path}/master/./#{image_file}" + + expect(subject.css('a')[0].attr('href')).to eq(expanded_path) + end + end + end end describe '#markdown_field' do diff --git a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js index bdf802052b9..16997e9dc67 100644 --- a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js +++ b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js @@ -70,4 +70,30 @@ describe('ContentViewer', () => { done(); }); }); + + it('markdown preview receives the file path as a parameter', done => { + mock = new MockAdapter(axios); + spyOn(axios, 'post').and.callThrough(); + mock.onPost(`${gon.relative_url_root}/testproject/preview_markdown`).reply(200, { + body: 'testing', + }); + + createComponent({ + path: 'test.md', + content: '* Test', + projectPath: 'testproject', + type: 'markdown', + filePath: 'foo/test.md', + }); + + setTimeout(() => { + expect(axios.post).toHaveBeenCalledWith( + `${gon.relative_url_root}/testproject/preview_markdown`, + { path: 'foo/test.md', text: '* Test' }, + jasmine.any(Object), + ); + + done(); + }); + }); }); diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb index f741a91b660..d4337c51279 100644 --- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb @@ -211,10 +211,12 @@ describe Gitlab::GitalyClient::OperationService do end context 'when a create_tree_error is present' do - let(:response) { response_class.new(create_tree_error: "something failed") } + let(:response) { response_class.new(create_tree_error: "something failed", create_tree_error_code: 'EMPTY') } it 'raises a CreateTreeError' do - expect { subject }.to raise_error(Gitlab::Git::Repository::CreateTreeError, "something failed") + expect { subject }.to raise_error(Gitlab::Git::Repository::CreateTreeError) do |error| + expect(error.error_code).to eq(:empty) + end end end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index 7d5206835c3..9256a6484b2 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -340,7 +340,7 @@ project: - triggers - pipeline_schedules - environments -- unfoldered_environments +- environments_for_dashboard - deployments - project_feature - auto_devops diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb index 0bba9d6e858..e1b4bd0b664 100644 --- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb @@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do it 'generates the appropriate specifications for the container' do container = subject.generate.spec.containers.first expect(container.name).to eq('helm') - expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.15.1-kube-1.13.12') + expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.16.1-kube-1.13.12') expect(container.env.count).to eq(3) expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT]) expect(container.command).to match_array(["/bin/sh"]) diff --git a/spec/models/clusters/applications/elastic_stack_spec.rb b/spec/models/clusters/applications/elastic_stack_spec.rb index 2b4697ee176..d0e0dd5ad57 100644 --- a/spec/models/clusters/applications/elastic_stack_spec.rb +++ b/spec/models/clusters/applications/elastic_stack_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' describe Clusters::Applications::ElasticStack do + include KubernetesHelpers + include_examples 'cluster application core specs', :clusters_applications_elastic_stack include_examples 'cluster application status specs', :clusters_applications_elastic_stack include_examples 'cluster application version specs', :clusters_applications_elastic_stack @@ -110,4 +112,68 @@ describe Clusters::Applications::ElasticStack do expect(values).to include('ELASTICSEARCH_HOSTS') end end + + describe '#elasticsearch_client' do + context 'cluster is nil' do + it 'returns nil' do + expect(subject.cluster).to be_nil + expect(subject.elasticsearch_client).to be_nil + end + end + + context "cluster doesn't have kubeclient" do + let(:cluster) { create(:cluster) } + subject { create(:clusters_applications_elastic_stack, cluster: cluster) } + + it 'returns nil' do + expect(subject.elasticsearch_client).to be_nil + end + end + + context 'cluster has kubeclient' do + let(:cluster) { create(:cluster, :project, :provided_by_gcp) } + let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url } + let(:kube_client) { subject.cluster.kubeclient.core_client } + + subject { create(:clusters_applications_elastic_stack, cluster: cluster) } + + before do + subject.cluster.platform_kubernetes.namespace = 'a-namespace' + stub_kubeclient_discover(cluster.platform_kubernetes.api_url) + + create(:cluster_kubernetes_namespace, + cluster: cluster, + cluster_project: cluster.cluster_project, + project: cluster.cluster_project.project) + end + + it 'creates proxy elasticsearch_client' do + expect(subject.elasticsearch_client).to be_instance_of(Elasticsearch::Transport::Client) + end + + it 'copies proxy_url, options and headers from kube client to elasticsearch_client' do + expect(Elasticsearch::Client) + .to(receive(:new)) + .with(url: a_valid_url) + .and_call_original + + client = subject.elasticsearch_client + faraday_connection = client.transport.connections.first.connection + + expect(faraday_connection.headers["Authorization"]).to eq(kube_client.headers[:Authorization]) + expect(faraday_connection.ssl.cert_store).to be_instance_of(OpenSSL::X509::Store) + expect(faraday_connection.ssl.verify).to eq(1) + end + + context 'when cluster is not reachable' do + before do + allow(kube_client).to receive(:proxy_url).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil)) + end + + it 'returns nil' do + expect(subject.elasticsearch_client).to be_nil + end + end + end + end end diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 9cea4866c4c..d8da1c001b0 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -1376,6 +1376,12 @@ describe API::Commits do it_behaves_like '400 response' do let(:request) { post api(route, current_user), params: { branch: 'markdown' } } end + + it 'includes an error_code in the response' do + post api(route, current_user), params: { branch: 'markdown' } + + expect(json_response['error_code']).to eq 'empty' + end end context 'when ref contains a dot' do @@ -1535,6 +1541,19 @@ describe API::Commits do let(:request) { post api(route, current_user) } end end + + context 'when commit is already reverted in the target branch' do + it 'includes an error_code in the response' do + # First one actually reverts + post api(route, current_user), params: { branch: 'markdown' } + + # Second one is redundant and should be empty + post api(route, current_user), params: { branch: 'markdown' } + + expect(response).to have_gitlab_http_status(400) + expect(json_response['error_code']).to eq 'empty' + end + end end context 'when authenticated', 'as a developer' do diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb index 199156c53d7..677aef57661 100644 --- a/spec/support/helpers/kubernetes_helpers.rb +++ b/spec/support/helpers/kubernetes_helpers.rb @@ -16,7 +16,7 @@ module KubernetesHelpers end def kube_logs_response - kube_response(kube_logs_body) + { body: kube_logs_body } end def kube_deployments_response -- cgit v1.2.3