Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-05-25 21:10:42 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-05-25 21:10:42 +0300
commita880341a7b3a164ba381620852cc3ea0777f67ad (patch)
treede7f7a09aee296eef7924cad7eb7ec2e9ea29ce0
parenta8c1bc6f757ecacbc3481e52a3f4cefb6c6db5fd (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_manual_todo.yml6
-rw-r--r--app/assets/javascripts/branches/components/sort_dropdown.vue5
-rw-r--r--app/assets/stylesheets/framework/lists.scss4
-rw-r--r--app/controllers/concerns/wiki_actions.rb2
-rw-r--r--app/controllers/projects/branches_controller.rb2
-rw-r--r--app/finders/projects_finder.rb11
-rw-r--r--app/models/ci/build_metadata.rb3
-rw-r--r--app/models/ci/pipeline.rb6
-rw-r--r--app/models/concerns/service_push_data_validations.rb4
-rw-r--r--app/models/environment_status.rb2
-rw-r--r--app/models/integrations/bamboo.rb2
-rw-r--r--app/models/integrations/base_ci.rb44
-rw-r--r--app/models/integrations/buildkite.rb145
-rw-r--r--app/models/integrations/drone_ci.rb106
-rw-r--r--app/models/integrations/jenkins.rb113
-rw-r--r--app/models/integrations/mock_ci.rb90
-rw-r--r--app/models/integrations/teamcity.rb191
-rw-r--r--app/models/project.rb42
-rw-r--r--app/models/project_repository_storage_move.rb13
-rw-r--r--app/models/project_services/buildkite_service.rb143
-rw-r--r--app/models/project_services/ci_service.rb42
-rw-r--r--app/models/project_services/drone_ci_service.rb104
-rw-r--r--app/models/project_services/jenkins_service.rb111
-rw-r--r--app/models/project_services/mock_ci_service.rb90
-rw-r--r--app/models/project_services/teamcity_service.rb189
-rw-r--r--app/models/snippet_repository_storage_move.rb13
-rw-r--r--app/services/branches/create_service.rb8
-rw-r--r--app/views/projects/_home_panel.html.haml6
-rw-r--r--app/views/projects/branches/_branch.html.haml34
-rw-r--r--app/views/projects/buttons/_download.html.haml8
-rw-r--r--app/workers/all_queues.yml36
-rw-r--r--app/workers/project_schedule_bulk_repository_shard_moves_worker.rb15
-rw-r--r--app/workers/project_update_repository_storage_worker.rb15
-rw-r--r--app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb16
-rw-r--r--app/workers/snippet_update_repository_storage_worker.rb15
-rw-r--r--config/feature_flags/development/security_dast_site_profiles_additional_fields.yml8
-rw-r--r--config/feature_flags/development/security_dast_site_profiles_api_option.yml8
-rw-r--r--config/sidekiq_queues.yml8
-rw-r--r--db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb16
-rw-r--r--db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb16
-rw-r--r--db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb44
-rw-r--r--db/schema_migrations/202105191321091
-rw-r--r--db/schema_migrations/202105191321291
-rw-r--r--db/schema_migrations/202105200124301
-rw-r--r--db/structure.sql14
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md3
-rw-r--r--doc/api/discussions.md24
-rw-r--r--doc/api/graphql/reference/index.md24
-rw-r--r--doc/api/project_aliases.md4
-rw-r--r--doc/api/project_import_export.md29
-rw-r--r--doc/api/repository_files.md2
-rw-r--r--doc/development/documentation/index.md1
-rw-r--r--doc/development/i18n/merging_translations.md6
-rw-r--r--doc/development/snowplow.md2
-rw-r--r--doc/user/project/repository/repository_mirroring.md29
-rw-r--r--lib/api/helpers.rb2
-rw-r--r--lib/api/helpers/services_helpers.rb12
-rw-r--r--lib/gitlab/ci/build/auto_retry.rb14
-rw-r--r--lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml11
-rw-r--r--lib/gitlab/email/receiver.rb2
-rw-r--r--lib/gitlab/integrations/sti_type.rb6
-rw-r--r--lib/gitlab/usage/metrics/aggregates/aggregate.rb12
-rw-r--r--lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb6
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/base_metric.rb1
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/database_metric.rb2
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb4
-rw-r--r--lib/gitlab/usage/time_frame.rb25
-rw-r--r--lib/gitlab/usage_data.rb35
-rw-r--r--lib/gitlab/usage_data_counters/hll_redis_counter.rb9
-rw-r--r--lib/gitlab/utils/usage_data.rb3
-rw-r--r--lib/tasks/gitlab/docs/redirect.rake72
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/config/metrics/aggregates/aggregated_metrics_spec.rb8
-rw-r--r--spec/controllers/projects/services_controller_spec.rb4
-rw-r--r--spec/factories/integrations.rb2
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb2
-rw-r--r--spec/features/projects/branches/user_deletes_branch_spec.rb2
-rw-r--r--spec/features/projects/branches_spec.rb10
-rw-r--r--spec/features/projects/environments/environment_spec.rb2
-rw-r--r--spec/features/projects/services/disable_triggers_spec.rb2
-rw-r--r--spec/features/projects_spec.rb14
-rw-r--r--spec/features/protected_branches_spec.rb4
-rw-r--r--spec/finders/projects_finder_spec.rb15
-rw-r--r--spec/lib/gitlab/ci/build/auto_retry_spec.rb4
-rw-r--r--spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb2
-rw-r--r--spec/lib/gitlab/email/receiver_spec.rb16
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb20
-rw-r--r--spec/models/ci/pipeline_spec.rb75
-rw-r--r--spec/models/environment_status_spec.rb11
-rw-r--r--spec/models/integrations/buildkite_spec.rb (renamed from spec/models/project_services/buildkite_service_spec.rb)2
-rw-r--r--spec/models/integrations/drone_ci_spec.rb (renamed from spec/models/project_services/drone_ci_service_spec.rb)6
-rw-r--r--spec/models/integrations/jenkins_spec.rb (renamed from spec/models/project_services/jenkins_service_spec.rb)2
-rw-r--r--spec/models/integrations/teamcity_spec.rb (renamed from spec/models/project_services/teamcity_service_spec.rb)2
-rw-r--r--spec/models/project_repository_storage_move_spec.rb35
-rw-r--r--spec/models/project_spec.rb25
-rw-r--r--spec/models/snippet_repository_storage_move_spec.rb13
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb2
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb2
-rw-r--r--spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb12
-rw-r--r--spec/workers/project_update_repository_storage_worker_spec.rb15
-rw-r--r--spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb12
-rw-r--r--spec/workers/snippet_update_repository_storage_worker_spec.rb15
102 files changed, 1222 insertions, 1210 deletions
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index df99014e425..4fb55ecaf6b 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -1649,19 +1649,14 @@ Gitlab/NamespacedClass:
- 'app/models/project_repository_storage_move.rb'
- 'app/models/project_services/alerts_service.rb'
- 'app/models/project_services/alerts_service_data.rb'
- - 'app/models/project_services/buildkite_service.rb'
- 'app/models/project_services/chat_notification_service.rb'
- - 'app/models/project_services/ci_service.rb'
- 'app/models/project_services/discord_service.rb'
- - 'app/models/project_services/drone_ci_service.rb'
- 'app/models/project_services/hangouts_chat_service.rb'
- 'app/models/project_services/issue_tracker_data.rb'
- - 'app/models/project_services/jenkins_service.rb'
- 'app/models/project_services/jira_tracker_data.rb'
- 'app/models/project_services/mattermost_service.rb'
- 'app/models/project_services/mattermost_slash_commands_service.rb'
- 'app/models/project_services/microsoft_teams_service.rb'
- - 'app/models/project_services/mock_ci_service.rb'
- 'app/models/project_services/mock_monitoring_service.rb'
- 'app/models/project_services/monitoring_service.rb'
- 'app/models/project_services/open_project_tracker_data.rb'
@@ -1670,7 +1665,6 @@ Gitlab/NamespacedClass:
- 'app/models/project_services/slack_service.rb'
- 'app/models/project_services/slack_slash_commands_service.rb'
- 'app/models/project_services/slash_commands_service.rb'
- - 'app/models/project_services/teamcity_service.rb'
- 'app/models/project_services/unify_circuit_service.rb'
- 'app/models/project_services/webex_teams_service.rb'
- 'app/models/project_setting.rb'
diff --git a/app/assets/javascripts/branches/components/sort_dropdown.vue b/app/assets/javascripts/branches/components/sort_dropdown.vue
index ddb4c5c0015..5f782b5e652 100644
--- a/app/assets/javascripts/branches/components/sort_dropdown.vue
+++ b/app/assets/javascripts/branches/components/sort_dropdown.vue
@@ -62,17 +62,18 @@ export default {
};
</script>
<template>
- <div class="gl-display-flex gl-pr-4">
+ <div class="gl-display-flex">
<gl-search-box-by-click
v-model="searchTerm"
:placeholder="$options.i18n.searchPlaceholder"
- class="gl-pr-4"
+ class="gl-mr-3"
data-testid="branch-search"
@submit="visitUrlFromOption(selectedKey)"
/>
<gl-dropdown
v-if="shouldShowDropdown"
:text="selectedSortMethodName"
+ class="gl-mr-3"
data-testid="branches-dropdown"
>
<gl-dropdown-item
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index a3e8b2c245c..9fe9f9a845c 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -135,7 +135,7 @@ ul.content-list {
float: right;
> .control-text {
- margin-right: $gl-padding-top;
+ margin-right: $grid-size;
line-height: $list-text-height;
&:last-child {
@@ -148,8 +148,6 @@ ul.content-list {
> .dropdown.inline {
margin-right: $grid-size;
display: inline-block;
- margin-top: 3px;
- margin-bottom: 4px;
&.btn-ldap-override {
@include media-breakpoint-up(sm) {
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index fc4f9aa3409..b7f6691ef4b 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -177,7 +177,7 @@ module WikiActions
redirect_to wiki_path(wiki),
status: :found
else
- @error = response
+ @error = response.message
render 'shared/wikis/edit'
end
end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 5006aa75ce5..3704f01e5dc 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -152,7 +152,7 @@ class Projects::BranchesController < Projects::ApplicationController
ref_escaped = strip_tags(sanitize(params[:ref]))
Addressable::URI.unescape(ref_escaped)
else
- @project.default_branch || 'master'
+ @project.default_branch_or_main
end
end
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 272747a124e..582075efc4e 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -14,7 +14,8 @@
# starred: boolean
# sort: string
# visibility_level: int
-# tags: string[]
+# tag: string[] - deprecated, use 'topic' instead
+# topic: string[]
# personal: boolean
# search: string
# search_namespaces: boolean
@@ -37,6 +38,8 @@ class ProjectsFinder < UnionFinder
@params = params
@current_user = current_user
@project_ids_relation = project_ids_relation
+
+ @params[:topic] ||= @params.delete(:tag) if @params[:tag].present?
end
def execute
@@ -76,7 +79,7 @@ class ProjectsFinder < UnionFinder
collection = by_starred(collection)
collection = by_trending(collection)
collection = by_visibility_level(collection)
- collection = by_tags(collection)
+ collection = by_topics(collection)
collection = by_search(collection)
collection = by_archived(collection)
collection = by_custom_attributes(collection)
@@ -176,8 +179,8 @@ class ProjectsFinder < UnionFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- def by_tags(items)
- params[:tag].present? ? items.tagged_with(params[:tag]) : items
+ def by_topics(items)
+ params[:topic].present? ? items.tagged_with(params[:topic]) : items
end
def by_search(items)
diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb
index 4094bdb26dc..8b3b298f5a2 100644
--- a/app/models/ci/build_metadata.rb
+++ b/app/models/ci/build_metadata.rb
@@ -10,6 +10,7 @@ module Ci
include Presentable
include ChronicDurationAttribute
include Gitlab::Utils::StrongMemoize
+ include IgnorableColumns
self.table_name = 'ci_builds_metadata'
@@ -37,6 +38,8 @@ module Ci
job_timeout_source: 4
}
+ ignore_column :build_id_convert_to_bigint, remove_with: '14.2', remove_after: '2021-08-22'
+
def update_timeout_state
timeout = timeout_with_highest_precedence
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 5d6c8542a74..b157b2f4a6c 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -922,6 +922,12 @@ module Ci
Ci::Build.latest.where(pipeline: self_and_descendants)
end
+ def environments_in_self_and_descendants
+ environment_ids = self_and_descendants.joins(:deployments).select(:'deployments.environment_id')
+
+ Environment.where(id: environment_ids)
+ end
+
# Without using `unscoped`, caller scope is also included into the query.
# Using `unscoped` here will be redundant after Rails 6.1
def self_and_descendants
diff --git a/app/models/concerns/service_push_data_validations.rb b/app/models/concerns/service_push_data_validations.rb
index defc5794142..451804a2c56 100644
--- a/app/models/concerns/service_push_data_validations.rb
+++ b/app/models/concerns/service_push_data_validations.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-# This concern is used by registerd services such as TeamCityService and
-# DroneCiService and add methods to perform validations on the received
+# This concern is used by registered integrations such as Integrations::TeamCity and
+# Integrations::DroneCi and adds methods to perform validations on the received
# data.
module ServicePushDataValidations
diff --git a/app/models/environment_status.rb b/app/models/environment_status.rb
index 55ea4e2fe18..07c0983f239 100644
--- a/app/models/environment_status.rb
+++ b/app/models/environment_status.rb
@@ -100,7 +100,7 @@ class EnvironmentStatus
def self.build_environments_status(mr, user, pipeline)
return [] unless pipeline
- pipeline.environments.includes(:project).available.map do |environment|
+ pipeline.environments_in_self_and_descendants.includes(:project).available.map do |environment|
next unless Ability.allowed?(user, :read_environment, environment)
EnvironmentStatus.new(pipeline.project, environment, mr, pipeline.sha)
diff --git a/app/models/integrations/bamboo.rb b/app/models/integrations/bamboo.rb
index 82111c7322e..dbd7aedf4fe 100644
--- a/app/models/integrations/bamboo.rb
+++ b/app/models/integrations/bamboo.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Integrations
- class Bamboo < CiService
+ class Bamboo < BaseCi
include ActionView::Helpers::UrlHelper
include ReactiveService
diff --git a/app/models/integrations/base_ci.rb b/app/models/integrations/base_ci.rb
new file mode 100644
index 00000000000..b2e269b1b50
--- /dev/null
+++ b/app/models/integrations/base_ci.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+# Base class for CI services
+# List methods you need to implement to get your CI service
+# working with GitLab merge requests
+module Integrations
+ class BaseCi < Integration
+ default_value_for :category, 'ci'
+
+ def valid_token?(token)
+ self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
+ end
+
+ def self.supported_events
+ %w(push)
+ end
+
+ # Return complete url to build page
+ #
+ # Ex.
+ # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
+ #
+ def build_page(sha, ref)
+ # implement inside child
+ end
+
+ # Return string with build status or :error symbol
+ #
+ # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
+ #
+ #
+ # Ex.
+ # @service.commit_status('13be4ac', 'master')
+ # # => 'success'
+ #
+ # @service.commit_status('2abe4ac', 'dev')
+ # # => 'running'
+ #
+ #
+ def commit_status(sha, ref)
+ # implement inside child
+ end
+ end
+end
diff --git a/app/models/integrations/buildkite.rb b/app/models/integrations/buildkite.rb
new file mode 100644
index 00000000000..906a5d02f9c
--- /dev/null
+++ b/app/models/integrations/buildkite.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require "addressable/uri"
+
+module Integrations
+ class Buildkite < BaseCi
+ include ReactiveService
+
+ ENDPOINT = "https://buildkite.com"
+
+ prop_accessor :project_url, :token
+
+ validates :project_url, presence: true, public_url: true, if: :activated?
+ validates :token, presence: true, if: :activated?
+
+ after_save :compose_service_hook, if: :activated?
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ # This is a stub method to work with deprecated API response
+ # TODO: remove enable_ssl_verification after 14.0
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
+ def enable_ssl_verification
+ true
+ end
+
+ # Since SSL verification will always be enabled for Buildkite,
+ # we no longer needs to store the boolean.
+ # This is a stub method to work with deprecated API param.
+ # TODO: remove enable_ssl_verification after 14.0
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
+ def enable_ssl_verification=(_value)
+ self.properties.delete('enable_ssl_verification') # Remove unused key
+ end
+
+ def webhook_url
+ "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}"
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.url = webhook_url
+ hook.enable_ssl_verification = true
+ hook.save
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ service_hook.execute(data)
+ end
+
+ def commit_status(sha, ref)
+ with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ end
+
+ def commit_status_path(sha)
+ "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
+ end
+
+ def build_page(sha, ref)
+ "#{project_url}/builds?commit=#{sha}"
+ end
+
+ def title
+ 'Buildkite'
+ end
+
+ def description
+ 'Run CI/CD pipelines with Buildkite.'
+ end
+
+ def self.to_param
+ 'buildkite'
+ end
+
+ def fields
+ [
+ { type: 'text',
+ name: 'token',
+ title: 'Integration Token',
+ help: 'This token will be provided when you create a Buildkite pipeline with a GitLab repository',
+ required: true },
+
+ { type: 'text',
+ name: 'project_url',
+ title: 'Pipeline URL',
+ placeholder: "#{ENDPOINT}/acme-inc/test-pipeline",
+ required: true }
+ ]
+ end
+
+ def calculate_reactive_cache(sha, ref)
+ response = Gitlab::HTTP.try_get(commit_status_path(sha), request_options)
+
+ status =
+ if response&.code == 200 && response['status']
+ response['status']
+ else
+ :error
+ end
+
+ { commit_status: status }
+ end
+
+ private
+
+ def webhook_token
+ token_parts.first
+ end
+
+ def status_token
+ token_parts.second
+ end
+
+ def token_parts
+ if token.present?
+ token.split(':')
+ else
+ []
+ end
+ end
+
+ def buildkite_endpoint(subdomain = nil)
+ if subdomain.present?
+ uri = Addressable::URI.parse(ENDPOINT)
+ new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}"
+
+ if uri.port.present?
+ "#{new_endpoint}:#{uri.port}"
+ else
+ new_endpoint
+ end
+ else
+ ENDPOINT
+ end
+ end
+
+ def request_options
+ { verify: false, extra_log_info: { project_id: project_id } }
+ end
+ end
+end
diff --git a/app/models/integrations/drone_ci.rb b/app/models/integrations/drone_ci.rb
new file mode 100644
index 00000000000..096f7093b8c
--- /dev/null
+++ b/app/models/integrations/drone_ci.rb
@@ -0,0 +1,106 @@
+# frozen_string_literal: true
+
+module Integrations
+ class DroneCi < BaseCi
+ include ReactiveService
+ include ServicePushDataValidations
+
+ prop_accessor :drone_url, :token
+ boolean_accessor :enable_ssl_verification
+
+ validates :drone_url, presence: true, public_url: true, if: :activated?
+ validates :token, presence: true, if: :activated?
+
+ after_save :compose_service_hook, if: :activated?
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ # If using a service template, project may not be available
+ hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join if project
+ hook.enable_ssl_verification = !!enable_ssl_verification
+ hook.save
+ end
+
+ def execute(data)
+ case data[:object_kind]
+ when 'push'
+ service_hook.execute(data) if push_valid?(data)
+ when 'merge_request'
+ service_hook.execute(data) if merge_request_valid?(data)
+ when 'tag_push'
+ service_hook.execute(data) if tag_push_valid?(data)
+ end
+ end
+
+ def allow_target_ci?
+ true
+ end
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ def commit_status_path(sha, ref)
+ Gitlab::Utils.append_path(
+ drone_url,
+ "gitlab/#{project.full_path}/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}&access_token=#{token}")
+ end
+
+ def commit_status(sha, ref)
+ with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
+ end
+
+ def calculate_reactive_cache(sha, ref)
+ response = Gitlab::HTTP.try_get(commit_status_path(sha, ref),
+ verify: enable_ssl_verification,
+ extra_log_info: { project_id: project_id })
+
+ status =
+ if response && response.code == 200 && response['status']
+ case response['status']
+ when 'killed'
+ :canceled
+ when 'failure', 'error'
+ # Because drone return error if some test env failed
+ :failed
+ else
+ response["status"]
+ end
+ else
+ :error
+ end
+
+ { commit_status: status }
+ end
+
+ def build_page(sha, ref)
+ Gitlab::Utils.append_path(
+ drone_url,
+ "gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}")
+ end
+
+ def title
+ 'Drone'
+ end
+
+ def description
+ s_('ProjectService|Run CI/CD pipelines with Drone.')
+ end
+
+ def self.to_param
+ 'drone_ci'
+ end
+
+ def help
+ s_('ProjectService|Run CI/CD pipelines with Drone.')
+ end
+
+ def fields
+ [
+ { type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true },
+ { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true },
+ { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
+ ]
+ end
+ end
+end
diff --git a/app/models/integrations/jenkins.rb b/app/models/integrations/jenkins.rb
new file mode 100644
index 00000000000..815e86bcaa1
--- /dev/null
+++ b/app/models/integrations/jenkins.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Jenkins < BaseCi
+ include ActionView::Helpers::UrlHelper
+
+ prop_accessor :jenkins_url, :project_name, :username, :password
+
+ before_update :reset_password
+
+ validates :jenkins_url, presence: true, addressable_url: true, if: :activated?
+ validates :project_name, presence: true, if: :activated?
+ validates :username, presence: true, if: ->(service) { service.activated? && service.password_touched? && service.password.present? }
+
+ default_value_for :push_events, true
+ default_value_for :merge_requests_events, false
+ default_value_for :tag_push_events, false
+
+ after_save :compose_service_hook, if: :activated?
+
+ def reset_password
+ # don't reset the password if a new one is provided
+ if (jenkins_url_changed? || username.blank?) && !password_touched?
+ self.password = nil
+ end
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.url = hook_url
+ hook.save
+ end
+
+ def execute(data)
+ return unless supported_events.include?(data[:object_kind])
+
+ service_hook.execute(data, "#{data[:object_kind]}_hook")
+ end
+
+ def test(data)
+ begin
+ result = execute(data)
+ return { success: false, result: result[:message] } if result[:http_status] != 200
+ rescue StandardError => error
+ return { success: false, result: error }
+ end
+
+ { success: true, result: result[:message] }
+ end
+
+ def hook_url
+ url = URI.parse(jenkins_url)
+ url.path = File.join(url.path || '/', "project/#{project_name}")
+ url.user = ERB::Util.url_encode(username) unless username.blank?
+ url.password = ERB::Util.url_encode(password) unless password.blank?
+ url.to_s
+ end
+
+ def self.supported_events
+ %w(push merge_request tag_push)
+ end
+
+ def title
+ 'Jenkins'
+ end
+
+ def description
+ s_('Run CI/CD pipelines with Jenkins.')
+ end
+
+ def help
+ docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('integration/jenkins'), target: '_blank', rel: 'noopener noreferrer'
+ s_('Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
+ end
+
+ def self.to_param
+ 'jenkins'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'jenkins_url',
+ title: s_('ProjectService|Jenkins server URL'),
+ required: true,
+ placeholder: 'http://jenkins.example.com',
+ help: s_('The URL of the Jenkins server.')
+ },
+ {
+ type: 'text',
+ name: 'project_name',
+ required: true,
+ placeholder: 'my_project_name',
+ help: s_('The name of the Jenkins project. Copy the name from the end of the URL to the project.')
+ },
+ {
+ type: 'text',
+ name: 'username',
+ required: true,
+ help: s_('The username for the Jenkins server.')
+ },
+ {
+ type: 'password',
+ name: 'password',
+ help: s_('The password for the Jenkins server.'),
+ non_empty_password_title: s_('ProjectService|Enter new password.'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password.')
+ }
+ ]
+ end
+ end
+end
diff --git a/app/models/integrations/mock_ci.rb b/app/models/integrations/mock_ci.rb
new file mode 100644
index 00000000000..d31f6381767
--- /dev/null
+++ b/app/models/integrations/mock_ci.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
+module Integrations
+ class MockCi < BaseCi
+ ALLOWED_STATES = %w[failed canceled running pending success success-with-warnings skipped not_found].freeze
+
+ prop_accessor :mock_service_url
+ validates :mock_service_url, presence: true, public_url: true, if: :activated?
+
+ def title
+ 'MockCI'
+ end
+
+ def description
+ 'Mock an external CI'
+ end
+
+ def self.to_param
+ 'mock_ci'
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'mock_service_url',
+ title: s_('ProjectService|Mock service URL'),
+ placeholder: 'http://localhost:4004',
+ required: true
+ }
+ ]
+ end
+
+ # Return complete url to build page
+ #
+ # Ex.
+ # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
+ #
+ def build_page(sha, ref)
+ Gitlab::Utils.append_path(
+ mock_service_url,
+ "#{project.namespace.path}/#{project.path}/status/#{sha}")
+ end
+
+ # Return string with build status or :error symbol
+ #
+ # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
+ #
+ # Ex.
+ # @service.commit_status('13be4ac', 'master')
+ # # => 'success'
+ #
+ # @service.commit_status('2abe4ac', 'dev')
+ # # => 'running'
+ #
+ def commit_status(sha, ref)
+ response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
+ read_commit_status(response)
+ rescue Errno::ECONNREFUSED
+ :error
+ end
+
+ def commit_status_path(sha)
+ Gitlab::Utils.append_path(
+ mock_service_url,
+ "#{project.namespace.path}/#{project.path}/status/#{sha}.json")
+ end
+
+ def read_commit_status(response)
+ return :error unless response.code == 200 || response.code == 404
+
+ status = if response.code == 404
+ 'pending'
+ else
+ response['status']
+ end
+
+ if status.present? && ALLOWED_STATES.include?(status)
+ status
+ else
+ :error
+ end
+ end
+
+ def can_test?
+ false
+ end
+ end
+end
diff --git a/app/models/integrations/teamcity.rb b/app/models/integrations/teamcity.rb
new file mode 100644
index 00000000000..8284d5963ae
--- /dev/null
+++ b/app/models/integrations/teamcity.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+module Integrations
+ class Teamcity < BaseCi
+ include ReactiveService
+ include ServicePushDataValidations
+
+ prop_accessor :teamcity_url, :build_type, :username, :password
+
+ validates :teamcity_url, presence: true, public_url: true, if: :activated?
+ validates :build_type, presence: true, if: :activated?
+ validates :username,
+ presence: true,
+ if: ->(service) { service.activated? && service.password }
+ validates :password,
+ presence: true,
+ if: ->(service) { service.activated? && service.username }
+
+ attr_accessor :response
+
+ after_save :compose_service_hook, if: :activated?
+ before_update :reset_password
+
+ class << self
+ def to_param
+ 'teamcity'
+ end
+
+ def supported_events
+ %w(push merge_request)
+ end
+
+ def event_description(event)
+ case event
+ when 'push', 'push_events'
+ 'TeamCity CI will be triggered after every push to the repository except branch delete'
+ when 'merge_request', 'merge_request_events'
+ 'TeamCity CI will be triggered after a merge request has been created or updated'
+ end
+ end
+ end
+
+ def compose_service_hook
+ hook = service_hook || build_service_hook
+ hook.save
+ end
+
+ def reset_password
+ if teamcity_url_changed? && !password_touched?
+ self.password = nil
+ end
+ end
+
+ def title
+ 'JetBrains TeamCity'
+ end
+
+ def description
+ s_('ProjectService|Run CI/CD pipelines with JetBrains TeamCity.')
+ end
+
+ def help
+ s_('To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings.')
+ end
+
+ def fields
+ [
+ {
+ type: 'text',
+ name: 'teamcity_url',
+ title: s_('ProjectService|TeamCity server URL'),
+ placeholder: 'https://teamcity.example.com',
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'build_type',
+ help: s_('ProjectService|The build configuration ID of the TeamCity project.'),
+ required: true
+ },
+ {
+ type: 'text',
+ name: 'username',
+ help: s_('ProjectService|Must have permission to trigger a manual build in TeamCity.')
+ },
+ {
+ type: 'password',
+ name: 'password',
+ non_empty_password_title: s_('ProjectService|Enter new password'),
+ non_empty_password_help: s_('ProjectService|Leave blank to use your current password')
+ }
+ ]
+ end
+
+ def build_page(sha, ref)
+ with_reactive_cache(sha, ref) {|cached| cached[:build_page] }
+ end
+
+ def commit_status(sha, ref)
+ with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
+ end
+
+ def calculate_reactive_cache(sha, ref)
+ response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,revision:#{sha}")
+
+ if response
+ { build_page: read_build_page(response), commit_status: read_commit_status(response) }
+ else
+ { build_page: teamcity_url, commit_status: :error }
+ end
+ end
+
+ def execute(data)
+ case data[:object_kind]
+ when 'push'
+ execute_push(data)
+ when 'merge_request'
+ execute_merge_request(data)
+ end
+ end
+
+ private
+
+ def execute_push(data)
+ branch = Gitlab::Git.ref_name(data[:ref])
+ post_to_build_queue(data, branch) if push_valid?(data)
+ end
+
+ def execute_merge_request(data)
+ branch = data[:object_attributes][:source_branch]
+ post_to_build_queue(data, branch) if merge_request_valid?(data)
+ end
+
+ def read_build_page(response)
+ if response.code != 200
+ # If actual build link can't be determined,
+ # send user to build summary page.
+ build_url("viewLog.html?buildTypeId=#{build_type}")
+ else
+ # If actual build link is available, go to build result page.
+ built_id = response['build']['id']
+ build_url("viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}")
+ end
+ end
+
+ def read_commit_status(response)
+ return :error unless response.code == 200 || response.code == 404
+
+ status = if response.code == 404
+ 'Pending'
+ else
+ response['build']['status']
+ end
+
+ return :error unless status.present?
+
+ if status.include?('SUCCESS')
+ 'success'
+ elsif status.include?('FAILURE')
+ 'failed'
+ elsif status.include?('Pending')
+ 'pending'
+ else
+ :error
+ end
+ end
+
+ def build_url(path)
+ Gitlab::Utils.append_path(teamcity_url, path)
+ end
+
+ def get_path(path)
+ Gitlab::HTTP.try_get(build_url(path), verify: false, basic_auth: basic_auth, extra_log_info: { project_id: project_id })
+ end
+
+ def post_to_build_queue(data, branch)
+ Gitlab::HTTP.post(
+ build_url('httpAuth/app/rest/buildQueue'),
+ body: "<build branchName=#{branch.encode(xml: :attr)}>"\
+ "<buildType id=#{build_type.encode(xml: :attr)}/>"\
+ '</build>',
+ headers: { 'Content-type' => 'application/xml' },
+ basic_auth: basic_auth
+ )
+ end
+
+ def basic_auth
+ { username: username, password: password }
+ end
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 39415769e50..b2324b18e17 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -129,41 +129,15 @@ class Project < ApplicationRecord
after_create :check_repository_absence!
acts_as_ordered_taggable_on :topics
- # The 'tag_list' alias and the 'has_many' associations are required during the 'tags -> topics' migration
- # TODO: eliminate 'tag_list', 'topic_taggings' and 'tags' in the further process of the migration
- # https://gitlab.com/gitlab-org/gitlab/-/issues/331081
+ # The 'tag_list' alias and the 'tags' association are required during the 'tags -> topics' migration
+ # TODO: eliminate 'tag_list' and 'tags' in the further process of the migration
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/328226
alias_attribute :tag_list, :topic_list
- has_many :topic_taggings, -> { includes(:tag).order("#{ActsAsTaggableOn::Tagging.table_name}.id") },
- as: :taggable,
- class_name: 'ActsAsTaggableOn::Tagging',
- after_add: :dirtify_tag_list,
- after_remove: :dirtify_tag_list
- has_many :topics, -> { order("#{ActsAsTaggableOn::Tagging.table_name}.id") },
- class_name: 'ActsAsTaggableOn::Tag',
- through: :topic_taggings,
- source: :tag
has_many :tags, -> { order("#{ActsAsTaggableOn::Tagging.table_name}.id") },
class_name: 'ActsAsTaggableOn::Tag',
through: :topic_taggings,
source: :tag
- # Overwriting 'topic_list' and 'topic_list=' is necessary to ensure functionality during the background migration [1].
- # [1] https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61237
- # TODO: remove 'topic_list' and 'topic_list=' once the background migration is complete
- # https://gitlab.com/gitlab-org/gitlab/-/issues/331081
- def topic_list
- # Return both old topics (context 'tags') and new topics (context 'topics')
- tag_list_on('tags') + tag_list_on('topics')
- end
-
- def topic_list=(new_tags)
- # Old topics with context 'tags' are added as new topics with context 'topics'
- super(new_tags)
-
- # Remove old topics with context 'tags'
- set_tag_list_on('tags', '')
- end
-
attr_accessor :old_path_with_namespace
attr_accessor :template_name
attr_writer :pipeline_status
@@ -187,33 +161,33 @@ class Project < ApplicationRecord
has_one :assembla_service, class_name: 'Integrations::Assembla'
has_one :bamboo_service, class_name: 'Integrations::Bamboo'
has_one :bugzilla_service, class_name: 'Integrations::Bugzilla'
+ has_one :buildkite_service, class_name: 'Integrations::Buildkite'
has_one :campfire_service, class_name: 'Integrations::Campfire'
has_one :confluence_service, class_name: 'Integrations::Confluence'
has_one :custom_issue_tracker_service, class_name: 'Integrations::CustomIssueTracker'
has_one :datadog_service, class_name: 'Integrations::Datadog'
+ has_one :drone_ci_service, class_name: 'Integrations::DroneCi'
has_one :emails_on_push_service, class_name: 'Integrations::EmailsOnPush'
has_one :ewm_service, class_name: 'Integrations::Ewm'
has_one :external_wiki_service, class_name: 'Integrations::ExternalWiki'
has_one :flowdock_service, class_name: 'Integrations::Flowdock'
has_one :irker_service, class_name: 'Integrations::Irker'
+ has_one :jenkins_service, class_name: 'Integrations::Jenkins'
has_one :jira_service, class_name: 'Integrations::Jira'
+ has_one :mock_ci_service, class_name: 'Integrations::MockCi'
has_one :packagist_service, class_name: 'Integrations::Packagist'
has_one :pipelines_email_service, class_name: 'Integrations::PipelinesEmail'
has_one :pivotaltracker_service, class_name: 'Integrations::Pivotaltracker'
has_one :redmine_service, class_name: 'Integrations::Redmine'
+ has_one :teamcity_service, class_name: 'Integrations::Teamcity'
has_one :youtrack_service, class_name: 'Integrations::Youtrack'
has_one :discord_service
- has_one :drone_ci_service
has_one :mattermost_slash_commands_service
has_one :mattermost_service
has_one :slack_slash_commands_service
has_one :slack_service
- has_one :buildkite_service
- has_one :teamcity_service
has_one :pushover_service
- has_one :jenkins_service
has_one :prometheus_service, inverse_of: :project
- has_one :mock_ci_service
has_one :mock_monitoring_service
has_one :microsoft_teams_service
has_one :hangouts_chat_service
diff --git a/app/models/project_repository_storage_move.rb b/app/models/project_repository_storage_move.rb
deleted file mode 100644
index e54489ddb88..00000000000
--- a/app/models/project_repository_storage_move.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class ProjectRepositoryStorageMove < Projects::RepositoryStorageMove
-end
diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb
deleted file mode 100644
index f2ea5066e37..00000000000
--- a/app/models/project_services/buildkite_service.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: true
-
-require "addressable/uri"
-
-class BuildkiteService < CiService
- include ReactiveService
-
- ENDPOINT = "https://buildkite.com"
-
- prop_accessor :project_url, :token
-
- validates :project_url, presence: true, public_url: true, if: :activated?
- validates :token, presence: true, if: :activated?
-
- after_save :compose_service_hook, if: :activated?
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- # This is a stub method to work with deprecated API response
- # TODO: remove enable_ssl_verification after 14.0
- # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
- def enable_ssl_verification
- true
- end
-
- # Since SSL verification will always be enabled for Buildkite,
- # we no longer needs to store the boolean.
- # This is a stub method to work with deprecated API param.
- # TODO: remove enable_ssl_verification after 14.0
- # https://gitlab.com/gitlab-org/gitlab/-/issues/222808
- def enable_ssl_verification=(_value)
- self.properties.delete('enable_ssl_verification') # Remove unused key
- end
-
- def webhook_url
- "#{buildkite_endpoint('webhook')}/deliver/#{webhook_token}"
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.url = webhook_url
- hook.enable_ssl_verification = true
- hook.save
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- service_hook.execute(data)
- end
-
- def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
- end
-
- def commit_status_path(sha)
- "#{buildkite_endpoint('gitlab')}/status/#{status_token}.json?commit=#{sha}"
- end
-
- def build_page(sha, ref)
- "#{project_url}/builds?commit=#{sha}"
- end
-
- def title
- 'Buildkite'
- end
-
- def description
- 'Run CI/CD pipelines with Buildkite.'
- end
-
- def self.to_param
- 'buildkite'
- end
-
- def fields
- [
- { type: 'text',
- name: 'token',
- title: 'Integration Token',
- help: 'This token will be provided when you create a Buildkite pipeline with a GitLab repository',
- required: true },
-
- { type: 'text',
- name: 'project_url',
- title: 'Pipeline URL',
- placeholder: "#{ENDPOINT}/acme-inc/test-pipeline",
- required: true }
- ]
- end
-
- def calculate_reactive_cache(sha, ref)
- response = Gitlab::HTTP.try_get(commit_status_path(sha), request_options)
-
- status =
- if response&.code == 200 && response['status']
- response['status']
- else
- :error
- end
-
- { commit_status: status }
- end
-
- private
-
- def webhook_token
- token_parts.first
- end
-
- def status_token
- token_parts.second
- end
-
- def token_parts
- if token.present?
- token.split(':')
- else
- []
- end
- end
-
- def buildkite_endpoint(subdomain = nil)
- if subdomain.present?
- uri = Addressable::URI.parse(ENDPOINT)
- new_endpoint = "#{uri.scheme || 'http'}://#{subdomain}.#{uri.host}"
-
- if uri.port.present?
- "#{new_endpoint}:#{uri.port}"
- else
- new_endpoint
- end
- else
- ENDPOINT
- end
- end
-
- def request_options
- { verify: false, extra_log_info: { project_id: project_id } }
- end
-end
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
deleted file mode 100644
index 0733da761d5..00000000000
--- a/app/models/project_services/ci_service.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-# Base class for CI services
-# List methods you need to implement to get your CI service
-# working with GitLab merge requests
-class CiService < Integration
- default_value_for :category, 'ci'
-
- def valid_token?(token)
- self.respond_to?(:token) && self.token.present? && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
- end
-
- def self.supported_events
- %w(push)
- end
-
- # Return complete url to build page
- #
- # Ex.
- # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
- #
- def build_page(sha, ref)
- # implement inside child
- end
-
- # Return string with build status or :error symbol
- #
- # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
- #
- #
- # Ex.
- # @service.commit_status('13be4ac', 'master')
- # # => 'success'
- #
- # @service.commit_status('2abe4ac', 'dev')
- # # => 'running'
- #
- #
- def commit_status(sha, ref)
- # implement inside child
- end
-end
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
deleted file mode 100644
index ab1ba768a8f..00000000000
--- a/app/models/project_services/drone_ci_service.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-class DroneCiService < CiService
- include ReactiveService
- include ServicePushDataValidations
-
- prop_accessor :drone_url, :token
- boolean_accessor :enable_ssl_verification
-
- validates :drone_url, presence: true, public_url: true, if: :activated?
- validates :token, presence: true, if: :activated?
-
- after_save :compose_service_hook, if: :activated?
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- # If using a service template, project may not be available
- hook.url = [drone_url, "/api/hook", "?owner=#{project.namespace.full_path}", "&name=#{project.path}", "&access_token=#{token}"].join if project
- hook.enable_ssl_verification = !!enable_ssl_verification
- hook.save
- end
-
- def execute(data)
- case data[:object_kind]
- when 'push'
- service_hook.execute(data) if push_valid?(data)
- when 'merge_request'
- service_hook.execute(data) if merge_request_valid?(data)
- when 'tag_push'
- service_hook.execute(data) if tag_push_valid?(data)
- end
- end
-
- def allow_target_ci?
- true
- end
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- def commit_status_path(sha, ref)
- Gitlab::Utils.append_path(
- drone_url,
- "gitlab/#{project.full_path}/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}&access_token=#{token}")
- end
-
- def commit_status(sha, ref)
- with_reactive_cache(sha, ref) { |cached| cached[:commit_status] }
- end
-
- def calculate_reactive_cache(sha, ref)
- response = Gitlab::HTTP.try_get(commit_status_path(sha, ref),
- verify: enable_ssl_verification,
- extra_log_info: { project_id: project_id })
-
- status =
- if response && response.code == 200 && response['status']
- case response['status']
- when 'killed'
- :canceled
- when 'failure', 'error'
- # Because drone return error if some test env failed
- :failed
- else
- response["status"]
- end
- else
- :error
- end
-
- { commit_status: status }
- end
-
- def build_page(sha, ref)
- Gitlab::Utils.append_path(
- drone_url,
- "gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{Addressable::URI.encode_component(ref.to_s)}")
- end
-
- def title
- 'Drone'
- end
-
- def description
- s_('ProjectService|Run CI/CD pipelines with Drone.')
- end
-
- def self.to_param
- 'drone_ci'
- end
-
- def help
- s_('ProjectService|Run CI/CD pipelines with Drone.')
- end
-
- def fields
- [
- { type: 'text', name: 'token', help: s_('ProjectService|Token for the Drone project.'), required: true },
- { type: 'text', name: 'drone_url', title: s_('ProjectService|Drone server URL'), placeholder: 'http://drone.example.com', required: true },
- { type: 'checkbox', name: 'enable_ssl_verification', title: "Enable SSL verification" }
- ]
- end
-end
diff --git a/app/models/project_services/jenkins_service.rb b/app/models/project_services/jenkins_service.rb
deleted file mode 100644
index 990a35cd617..00000000000
--- a/app/models/project_services/jenkins_service.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-# frozen_string_literal: true
-
-class JenkinsService < CiService
- include ActionView::Helpers::UrlHelper
-
- prop_accessor :jenkins_url, :project_name, :username, :password
-
- before_update :reset_password
-
- validates :jenkins_url, presence: true, addressable_url: true, if: :activated?
- validates :project_name, presence: true, if: :activated?
- validates :username, presence: true, if: ->(service) { service.activated? && service.password_touched? && service.password.present? }
-
- default_value_for :push_events, true
- default_value_for :merge_requests_events, false
- default_value_for :tag_push_events, false
-
- after_save :compose_service_hook, if: :activated?
-
- def reset_password
- # don't reset the password if a new one is provided
- if (jenkins_url_changed? || username.blank?) && !password_touched?
- self.password = nil
- end
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.url = hook_url
- hook.save
- end
-
- def execute(data)
- return unless supported_events.include?(data[:object_kind])
-
- service_hook.execute(data, "#{data[:object_kind]}_hook")
- end
-
- def test(data)
- begin
- result = execute(data)
- return { success: false, result: result[:message] } if result[:http_status] != 200
- rescue StandardError => error
- return { success: false, result: error }
- end
-
- { success: true, result: result[:message] }
- end
-
- def hook_url
- url = URI.parse(jenkins_url)
- url.path = File.join(url.path || '/', "project/#{project_name}")
- url.user = ERB::Util.url_encode(username) unless username.blank?
- url.password = ERB::Util.url_encode(password) unless password.blank?
- url.to_s
- end
-
- def self.supported_events
- %w(push merge_request tag_push)
- end
-
- def title
- 'Jenkins'
- end
-
- def description
- s_('Run CI/CD pipelines with Jenkins.')
- end
-
- def help
- docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('integration/jenkins'), target: '_blank', rel: 'noopener noreferrer'
- s_('Run CI/CD pipelines with Jenkins when you push to a repository, or when a merge request is created, updated, or merged. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
- end
-
- def self.to_param
- 'jenkins'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'jenkins_url',
- title: s_('ProjectService|Jenkins server URL'),
- required: true,
- placeholder: 'http://jenkins.example.com',
- help: s_('The URL of the Jenkins server.')
- },
- {
- type: 'text',
- name: 'project_name',
- required: true,
- placeholder: 'my_project_name',
- help: s_('The name of the Jenkins project. Copy the name from the end of the URL to the project.')
- },
- {
- type: 'text',
- name: 'username',
- required: true,
- help: s_('The username for the Jenkins server.')
- },
- {
- type: 'password',
- name: 'password',
- help: s_('The password for the Jenkins server.'),
- non_empty_password_title: s_('ProjectService|Enter new password.'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current password.')
- }
- ]
- end
-end
diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb
deleted file mode 100644
index bd6344c6e1a..00000000000
--- a/app/models/project_services/mock_ci_service.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-# frozen_string_literal: true
-
-# For an example companion mocking service, see https://gitlab.com/gitlab-org/gitlab-mock-ci-service
-class MockCiService < CiService
- ALLOWED_STATES = %w[failed canceled running pending success success-with-warnings skipped not_found].freeze
-
- prop_accessor :mock_service_url
- validates :mock_service_url, presence: true, public_url: true, if: :activated?
-
- def title
- 'MockCI'
- end
-
- def description
- 'Mock an external CI'
- end
-
- def self.to_param
- 'mock_ci'
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'mock_service_url',
- title: s_('ProjectService|Mock service URL'),
- placeholder: 'http://localhost:4004',
- required: true
- }
- ]
- end
-
- # Return complete url to build page
- #
- # Ex.
- # http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
- #
- def build_page(sha, ref)
- Gitlab::Utils.append_path(
- mock_service_url,
- "#{project.namespace.path}/#{project.path}/status/#{sha}")
- end
-
- # Return string with build status or :error symbol
- #
- # Allowed states: 'success', 'failed', 'running', 'pending', 'skipped'
- #
- #
- # Ex.
- # @service.commit_status('13be4ac', 'master')
- # # => 'success'
- #
- # @service.commit_status('2abe4ac', 'dev')
- # # => 'running'
- #
- #
- def commit_status(sha, ref)
- response = Gitlab::HTTP.get(commit_status_path(sha), verify: false)
- read_commit_status(response)
- rescue Errno::ECONNREFUSED
- :error
- end
-
- def commit_status_path(sha)
- Gitlab::Utils.append_path(
- mock_service_url,
- "#{project.namespace.path}/#{project.path}/status/#{sha}.json")
- end
-
- def read_commit_status(response)
- return :error unless response.code == 200 || response.code == 404
-
- status = if response.code == 404
- 'pending'
- else
- response['status']
- end
-
- if status.present? && ALLOWED_STATES.include?(status)
- status
- else
- :error
- end
- end
-
- def can_test?
- false
- end
-end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
deleted file mode 100644
index 6fc24a4778c..00000000000
--- a/app/models/project_services/teamcity_service.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-# frozen_string_literal: true
-
-class TeamcityService < CiService
- include ReactiveService
- include ServicePushDataValidations
-
- prop_accessor :teamcity_url, :build_type, :username, :password
-
- validates :teamcity_url, presence: true, public_url: true, if: :activated?
- validates :build_type, presence: true, if: :activated?
- validates :username,
- presence: true,
- if: ->(service) { service.activated? && service.password }
- validates :password,
- presence: true,
- if: ->(service) { service.activated? && service.username }
-
- attr_accessor :response
-
- after_save :compose_service_hook, if: :activated?
- before_update :reset_password
-
- class << self
- def to_param
- 'teamcity'
- end
-
- def supported_events
- %w(push merge_request)
- end
-
- def event_description(event)
- case event
- when 'push', 'push_events'
- 'TeamCity CI will be triggered after every push to the repository except branch delete'
- when 'merge_request', 'merge_request_events'
- 'TeamCity CI will be triggered after a merge request has been created or updated'
- end
- end
- end
-
- def compose_service_hook
- hook = service_hook || build_service_hook
- hook.save
- end
-
- def reset_password
- if teamcity_url_changed? && !password_touched?
- self.password = nil
- end
- end
-
- def title
- 'JetBrains TeamCity'
- end
-
- def description
- s_('ProjectService|Run CI/CD pipelines with JetBrains TeamCity.')
- end
-
- def help
- s_('To run CI/CD pipelines with JetBrains TeamCity, input the GitLab project details in the TeamCity project Version Control Settings.')
- end
-
- def fields
- [
- {
- type: 'text',
- name: 'teamcity_url',
- title: s_('ProjectService|TeamCity server URL'),
- placeholder: 'https://teamcity.example.com',
- required: true
- },
- {
- type: 'text',
- name: 'build_type',
- help: s_('ProjectService|The build configuration ID of the TeamCity project.'),
- required: true
- },
- {
- type: 'text',
- name: 'username',
- help: s_('ProjectService|Must have permission to trigger a manual build in TeamCity.')
- },
- {
- type: 'password',
- name: 'password',
- non_empty_password_title: s_('ProjectService|Enter new password'),
- non_empty_password_help: s_('ProjectService|Leave blank to use your current password')
- }
- ]
- end
-
- def build_page(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:build_page] }
- end
-
- def commit_status(sha, ref)
- with_reactive_cache(sha, ref) {|cached| cached[:commit_status] }
- end
-
- def calculate_reactive_cache(sha, ref)
- response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,revision:#{sha}")
-
- if response
- { build_page: read_build_page(response), commit_status: read_commit_status(response) }
- else
- { build_page: teamcity_url, commit_status: :error }
- end
- end
-
- def execute(data)
- case data[:object_kind]
- when 'push'
- execute_push(data)
- when 'merge_request'
- execute_merge_request(data)
- end
- end
-
- private
-
- def execute_push(data)
- branch = Gitlab::Git.ref_name(data[:ref])
- post_to_build_queue(data, branch) if push_valid?(data)
- end
-
- def execute_merge_request(data)
- branch = data[:object_attributes][:source_branch]
- post_to_build_queue(data, branch) if merge_request_valid?(data)
- end
-
- def read_build_page(response)
- if response.code != 200
- # If actual build link can't be determined,
- # send user to build summary page.
- build_url("viewLog.html?buildTypeId=#{build_type}")
- else
- # If actual build link is available, go to build result page.
- built_id = response['build']['id']
- build_url("viewLog.html?buildId=#{built_id}&buildTypeId=#{build_type}")
- end
- end
-
- def read_commit_status(response)
- return :error unless response.code == 200 || response.code == 404
-
- status = if response.code == 404
- 'Pending'
- else
- response['build']['status']
- end
-
- return :error unless status.present?
-
- if status.include?('SUCCESS')
- 'success'
- elsif status.include?('FAILURE')
- 'failed'
- elsif status.include?('Pending')
- 'pending'
- else
- :error
- end
- end
-
- def build_url(path)
- Gitlab::Utils.append_path(teamcity_url, path)
- end
-
- def get_path(path)
- Gitlab::HTTP.try_get(build_url(path), verify: false, basic_auth: basic_auth, extra_log_info: { project_id: project_id })
- end
-
- def post_to_build_queue(data, branch)
- Gitlab::HTTP.post(
- build_url('httpAuth/app/rest/buildQueue'),
- body: "<build branchName=#{branch.encode(xml: :attr)}>"\
- "<buildType id=#{build_type.encode(xml: :attr)}/>"\
- '</build>',
- headers: { 'Content-type' => 'application/xml' },
- basic_auth: basic_auth
- )
- end
-
- def basic_auth
- { username: username, password: password }
- end
-end
diff --git a/app/models/snippet_repository_storage_move.rb b/app/models/snippet_repository_storage_move.rb
deleted file mode 100644
index 8234905a7e1..00000000000
--- a/app/models/snippet_repository_storage_move.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class SnippetRepositoryStorageMove < Snippets::RepositoryStorageMove
-end
diff --git a/app/services/branches/create_service.rb b/app/services/branches/create_service.rb
index 8684da701db..848e6aaa65a 100644
--- a/app/services/branches/create_service.rb
+++ b/app/services/branches/create_service.rb
@@ -2,8 +2,8 @@
module Branches
class CreateService < BaseService
- def execute(branch_name, ref, create_master_if_empty: true)
- create_master_branch if create_master_if_empty && project.empty_repo?
+ def execute(branch_name, ref, create_default_branch_if_empty: true)
+ create_default_branch if create_default_branch_if_empty && project.empty_repo?
result = ::Branches::ValidateNewService.new(project).execute(branch_name)
@@ -27,13 +27,13 @@ module Branches
private
- def create_master_branch
+ def create_default_branch
project.repository.create_file(
current_user,
'/README.md',
'',
message: 'Add README.md',
- branch_name: 'master'
+ branch_name: project.default_branch_or_main
)
end
end
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index a70679dab5f..26291c0358e 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -25,14 +25,14 @@
%span.access-request-links.gl-ml-3
= render 'shared/members/access_request_links', source: @project
- - if @project.tag_list.present?
- = cache_if(cache_enabled, [@project, :tag_list], expires_in: 1.day) do
+ - if @project.topic_list.present?
+ = cache_if(cache_enabled, [@project, :topic_list], expires_in: 1.day) do
%span.home-panel-topic-list.mt-2.w-100.d-inline-flex.gl-font-base.gl-font-weight-normal.gl-align-items-center
= sprite_icon('tag', css_class: 'icon gl-relative gl-mr-2')
- @project.topics_to_show.each do |topic|
- project_topics_classes = "badge badge-pill badge-secondary gl-mr-2"
- - explore_project_topic_path = explore_projects_path(tag: topic)
+ - explore_project_topic_path = explore_projects_path(topic: topic)
- if topic.length > max_project_topic_length
%a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
= topic.titleize
diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml
index a5414ce7ef2..548fdc10bd4 100644
--- a/app/views/projects/branches/_branch.html.haml
+++ b/app/views/projects/branches/_branch.html.haml
@@ -46,35 +46,37 @@
title: s_('Branches|Compare') do
= s_('Branches|Compare')
- = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name]
+ = render 'projects/buttons/download', project: @project, ref: branch.name, pipeline: @refs_pipelines[branch.name], class: 'gl-vertical-align-top'
- if can?(current_user, :push_code, @project)
- if branch.name == @project.repository.root_ref
- delete_default_branch_tooltip = s_('Branches|The default branch cannot be deleted')
- %span.has-tooltip{ title: delete_default_branch_tooltip }
- %button{ class: "gl-button btn btn-danger disabled", disabled: true, 'aria-label' => delete_default_branch_tooltip }
- = sprite_icon("remove")
+ %span.gl-display-inline-block.has-tooltip{ title: delete_default_branch_tooltip }
+ %button{ class: 'gl-button btn btn-default btn-icon disabled', disabled: true, 'aria-label' => delete_default_branch_tooltip }
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- elsif protected_branch?(@project, branch)
- if can?(current_user, :push_to_delete_protected_branch, @project)
- %button{ class: "gl-button btn btn-danger has-tooltip",
- title: s_('Branches|Delete protected branch'),
- data: { toggle: "modal",
- target: "#modal-delete-branch",
+ - delete_protected_branch_tooltip = s_('Branches|Delete protected branch')
+ %button{ class: 'gl-button btn btn-default btn-icon has-tooltip',
+ title: delete_protected_branch_tooltip,
+ 'aria-label' => delete_protected_branch_tooltip,
+ data: { toggle: 'modal',
+ target: '#modal-delete-branch',
delete_path: project_branch_path(@project, branch.name),
branch_name: branch.name,
- is_merged: ("true" if merged) } }
- = sprite_icon("remove")
+ is_merged: ('true' if merged) } }
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- else
- - delete_protected_branch_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
- %span.has-tooltip{ title: delete_protected_branch_tooltip }
- %button{ class: "gl-button btn btn-danger disabled", disabled: true, 'aria-label' => delete_protected_branch_tooltip }
- = sprite_icon("remove")
+ - delete_protected_branch_disabled_tooltip = s_('Branches|Only a project maintainer or owner can delete a protected branch')
+ %span.has-tooltip{ title: delete_protected_branch_disabled_tooltip }
+ %button{ class: 'gl-button btn btn-default btn-icon disabled', disabled: true, 'aria-label' => delete_protected_branch_disabled_tooltip, data: { testid: 'remove-protected-branch' } }
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
- else
= link_to project_branch_path(@project, branch.name),
- class: "gl-button btn btn-danger js-remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip",
+ class: 'gl-button btn btn-default btn-icon js-remove-row qa-remove-btn js-ajax-loading-spinner has-tooltip',
title: s_('Branches|Delete branch'),
method: :delete,
data: { confirm: s_("Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?") % { branch_name: branch.name } },
remote: true,
'aria-label' => s_('Branches|Delete branch') do
- = sprite_icon("remove")
+ = sprite_icon('remove', css_class: 'gl-button-icon gl-icon')
diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml
index 2f89a3f62ed..2d32e07d379 100644
--- a/app/views/projects/buttons/_download.html.haml
+++ b/app/views/projects/buttons/_download.html.haml
@@ -2,11 +2,11 @@
- if !project.empty_repo? && can?(current_user, :download_code, project)
- archive_prefix = "#{project.path}-#{ref.tr('/', '-')}"
- .project-action-button.dropdown.inline>
- %button.gl-button.btn.btn-default.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
- = sprite_icon('download', css_class: 'gl-icon')
+ .project-action-button.dropdown.gl-new-dropdown.inline>
+ %button.gl-button.btn.btn-default.dropdown-toggle.gl-dropdown-toggle.dropdown-icon-only.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download'), 'data-display' => 'static', data: { qa_selector: 'download_source_code_button' } }
+ = sprite_icon('download', css_class: 'gl-icon dropdown-icon')
%span.sr-only= _('Select Archive Format')
- = sprite_icon('chevron-down', css_class: 'gl-icon')
+ = sprite_icon('chevron-down', css_class: 'gl-icon dropdown-chevron')
.dropdown-menu.dropdown-menu-right{ role: 'menu' }
%section
%h5.m-0.dropdown-bold-header= _('Download source code')
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index ea0845b00e8..04ac7036752 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -2570,15 +2570,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: project_schedule_bulk_repository_shard_moves
- :worker_name: ProjectScheduleBulkRepositoryShardMovesWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: project_service
:worker_name: ProjectServiceWorker
:feature_category: :integrations
@@ -2588,15 +2579,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: project_update_repository_storage
- :worker_name: ProjectUpdateRepositoryStorageWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: projects_git_garbage_collect
:worker_name: Projects::GitGarbageCollectWorker
:feature_category: :gitaly
@@ -2811,24 +2793,6 @@
:weight: 1
:idempotent:
:tags: []
-- :name: snippet_schedule_bulk_repository_shard_moves
- :worker_name: SnippetScheduleBulkRepositoryShardMovesWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
-- :name: snippet_update_repository_storage
- :worker_name: SnippetUpdateRepositoryStorageWorker
- :feature_category: :gitaly
- :has_external_dependencies:
- :urgency: :throttled
- :resource_boundary: :unknown
- :weight: 1
- :idempotent: true
- :tags: []
- :name: snippets_schedule_bulk_repository_shard_moves
:worker_name: Snippets::ScheduleBulkRepositoryShardMovesWorker
:feature_category: :gitaly
diff --git a/app/workers/project_schedule_bulk_repository_shard_moves_worker.rb b/app/workers/project_schedule_bulk_repository_shard_moves_worker.rb
deleted file mode 100644
index 23d1594e4d9..00000000000
--- a/app/workers/project_schedule_bulk_repository_shard_moves_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class ProjectScheduleBulkRepositoryShardMovesWorker < Projects::ScheduleBulkRepositoryShardMovesWorker
- idempotent!
- urgency :throttled
-end
diff --git a/app/workers/project_update_repository_storage_worker.rb b/app/workers/project_update_repository_storage_worker.rb
deleted file mode 100644
index 0d68c0e16f8..00000000000
--- a/app/workers/project_update_repository_storage_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class ProjectUpdateRepositoryStorageWorker < Projects::UpdateRepositoryStorageWorker
- idempotent!
- urgency :throttled
-end
diff --git a/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb b/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
deleted file mode 100644
index 94a6b22538b..00000000000
--- a/app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class SnippetScheduleBulkRepositoryShardMovesWorker < Snippets::ScheduleBulkRepositoryShardMovesWorker
- idempotent!
- feature_category :gitaly
- urgency :throttled
-end
diff --git a/app/workers/snippet_update_repository_storage_worker.rb b/app/workers/snippet_update_repository_storage_worker.rb
deleted file mode 100644
index befae6db4f4..00000000000
--- a/app/workers/snippet_update_repository_storage_worker.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-# This is a compatibility class to avoid calling a non-existent
-# class from sidekiq during deployment.
-#
-# This class was moved to a namespace in https://gitlab.com/gitlab-org/gitlab/-/issues/299853.
-# we cannot remove this class entirely because there can be jobs
-# referencing it.
-#
-# We can get rid of this class in 14.0
-# https://gitlab.com/gitlab-org/gitlab/-/issues/322393
-class SnippetUpdateRepositoryStorageWorker < Snippets::UpdateRepositoryStorageWorker # rubocop:disable Scalability/IdempotentWorker
- idempotent!
- urgency :throttled
-end
diff --git a/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml b/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
deleted file mode 100644
index ef4d1cb3bfe..00000000000
--- a/config/feature_flags/development/security_dast_site_profiles_additional_fields.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: security_dast_site_profiles_additional_fields
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46848
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292897
-milestone: '13.7'
-type: development
-group: group::dynamic analysis
-default_enabled: true
diff --git a/config/feature_flags/development/security_dast_site_profiles_api_option.yml b/config/feature_flags/development/security_dast_site_profiles_api_option.yml
deleted file mode 100644
index 8a9c6fefb5d..00000000000
--- a/config/feature_flags/development/security_dast_site_profiles_api_option.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: security_dast_site_profiles_api_option
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58723
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325130
-milestone: '13.12'
-type: development
-group: group::dynamic analysis
-default_enabled: true
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 24d140abada..06f9cc2cd85 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -298,14 +298,10 @@
- 1
- - project_import_schedule
- 1
-- - project_schedule_bulk_repository_shard_moves
- - 1
- - project_service
- 1
- - project_template_export
- 1
-- - project_update_repository_storage
- - 1
- - projects_git_garbage_collect
- 1
- - projects_post_creation
@@ -370,10 +366,6 @@
- 1
- - set_user_status_based_on_user_cap_setting
- 1
-- - snippet_schedule_bulk_repository_shard_moves
- - 1
-- - snippet_update_repository_storage
- - 1
- - snippets_schedule_bulk_repository_shard_moves
- 1
- - snippets_update_repository_storage
diff --git a/db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb b/db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb
new file mode 100644
index 00000000000..7ff0276b4b5
--- /dev/null
+++ b/db/migrate/20210519132109_initialize_conversion_of_ci_builds_metadata_to_bigint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class InitializeConversionOfCiBuildsMetadataToBigint < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_builds_metadata
+ COLUMN = :build_id
+
+ def up
+ initialize_conversion_of_integer_to_bigint(TABLE, COLUMN)
+ end
+
+ def down
+ revert_initialize_conversion_of_integer_to_bigint(TABLE, COLUMN)
+ end
+end
diff --git a/db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb b/db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb
new file mode 100644
index 00000000000..3aeabbcc0ad
--- /dev/null
+++ b/db/post_migrate/20210519132129_backfill_ci_builds_metadata_for_bigint_conversion.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BackfillCiBuildsMetadataForBigintConversion < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ TABLE = :ci_builds_metadata
+ COLUMN = :build_id
+
+ def up
+ backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100
+ end
+
+ def down
+ revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMN
+ end
+end
diff --git a/db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb b/db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb
new file mode 100644
index 00000000000..d554b412420
--- /dev/null
+++ b/db/post_migrate/20210520012430_backfill_pk_conversion_for_self_managed.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+class BackfillPkConversionForSelfManaged < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ CONVERSIONS = [
+ { table: :events, columns: %i(id), sub_batch_size: 500 },
+ { table: :push_event_payloads, columns: %i(event_id), sub_batch_size: 2500, primary_key: :event_id },
+ { table: :ci_job_artifacts, columns: %i(id job_id), sub_batch_size: 2000 },
+ { table: :ci_sources_pipelines, columns: %i(source_job_id), sub_batch_size: 100 },
+ { table: :ci_build_needs, columns: %i(build_id), sub_batch_size: 1000 },
+ { table: :ci_builds, columns: %i(id stage_id), sub_batch_size: 250 },
+ { table: :ci_builds_runner_session, columns: %i(build_id), sub_batch_size: 5000 },
+ { table: :ci_build_trace_chunks, columns: %i(build_id), sub_batch_size: 1000 }
+ ]
+
+ def up
+ return unless should_run?
+
+ CONVERSIONS.each do |conversion|
+ backfill_conversion_of_integer_to_bigint(
+ conversion[:table], conversion[:columns],
+ sub_batch_size: conversion[:sub_batch_size], primary_key: conversion.fetch(:primary_key, :id)
+ )
+ end
+ end
+
+ def down
+ return unless should_run?
+
+ CONVERSIONS.each do |conversion|
+ revert_backfill_conversion_of_integer_to_bigint(
+ conversion[:table], conversion[:columns],
+ primary_key: conversion.fetch(:primary_key, :id)
+ )
+ end
+ end
+
+ private
+
+ def should_run?
+ !Gitlab.com?
+ end
+end
diff --git a/db/schema_migrations/20210519132109 b/db/schema_migrations/20210519132109
new file mode 100644
index 00000000000..9d8537aa6b2
--- /dev/null
+++ b/db/schema_migrations/20210519132109
@@ -0,0 +1 @@
+ba464ad09f3cec0e9cf94b3041ad946e3a5a8c915ce0b9f4f95ab49cb55d305d \ No newline at end of file
diff --git a/db/schema_migrations/20210519132129 b/db/schema_migrations/20210519132129
new file mode 100644
index 00000000000..da7a8212092
--- /dev/null
+++ b/db/schema_migrations/20210519132129
@@ -0,0 +1 @@
+8041e898177bdee3b4d1ad82ec7dd3b79cb7dd740f773cd91dc4306a87a397fd \ No newline at end of file
diff --git a/db/schema_migrations/20210520012430 b/db/schema_migrations/20210520012430
new file mode 100644
index 00000000000..d92bc8d8369
--- /dev/null
+++ b/db/schema_migrations/20210520012430
@@ -0,0 +1 @@
+86b9f1c0f4288bf83e8b2d70b06b8951b7bcef0aa9324d9546471f6f094b014b \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 8bfe5e16f41..7e2a540c6f1 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -152,6 +152,15 @@ BEGIN
END;
$$;
+CREATE FUNCTION trigger_8487d4de3e7b() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+ NEW."build_id_convert_to_bigint" := NEW."build_id";
+ RETURN NEW;
+END;
+$$;
+
CREATE FUNCTION trigger_91dc388a5fe6() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -10585,7 +10594,8 @@ CREATE TABLE ci_builds_metadata (
has_exposed_artifacts boolean,
environment_auto_stop_in character varying(255),
expanded_environment_name character varying(255),
- secrets jsonb DEFAULT '{}'::jsonb NOT NULL
+ secrets jsonb DEFAULT '{}'::jsonb NOT NULL,
+ build_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE SEQUENCE ci_builds_metadata_id_seq
@@ -25249,6 +25259,8 @@ CREATE TRIGGER trigger_69523443cc10 BEFORE INSERT OR UPDATE ON events FOR EACH R
CREATE TRIGGER trigger_8485e97c00e3 BEFORE INSERT OR UPDATE ON ci_sources_pipelines FOR EACH ROW EXECUTE FUNCTION trigger_8485e97c00e3();
+CREATE TRIGGER trigger_8487d4de3e7b BEFORE INSERT OR UPDATE ON ci_builds_metadata FOR EACH ROW EXECUTE FUNCTION trigger_8487d4de3e7b();
+
CREATE TRIGGER trigger_91dc388a5fe6 BEFORE INSERT OR UPDATE ON ci_build_trace_sections FOR EACH ROW EXECUTE FUNCTION trigger_91dc388a5fe6();
CREATE TRIGGER trigger_be1804f21693 BEFORE INSERT OR UPDATE ON ci_job_artifacts FOR EACH ROW EXECUTE FUNCTION trigger_be1804f21693();
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index dd43c7d6fbb..72ab536ceae 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -68,7 +68,8 @@ appears next to requests with warnings.
## Enable the Performance Bar via the Admin Area
-The GitLab Performance Bar is disabled by default. To enable it for a given group:
+The GitLab Performance Bar is disabled by default for non-administrators. To enable it
+for a given group:
1. Sign in as a user with Administrator [permissions](../../../user/permissions.md).
1. In the menu bar, click **Admin Area**.
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 3d40349ecca..d8d989adfe2 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -156,7 +156,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `issue_iid` | integer | yes | The IID of an issue |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions?body=comment"
@@ -167,7 +167,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
Adds a new note to the thread. This can also [create a thread from a single comment](../user/discussions/#start-a-thread-by-replying-to-a-standard-comment).
**WARNING**
-Notes can be added to other items than comments (system notes, etc.) making them threads.
+Notes can be added to other items than comments, such as system notes, making them threads.
```plaintext
POST /projects/:id/issues/:issue_iid/discussions/:discussion_id/notes
@@ -182,7 +182,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -365,7 +365,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `snippet_id` | integer | yes | The ID of an snippet |
| `body` | string | yes | The content of a discussion |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions?body=comment"
@@ -388,7 +388,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -572,7 +572,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions?body=comment"
@@ -596,7 +596,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/epics/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -847,7 +847,7 @@ Parameters for all comments:
| `merge_request_iid` | integer | yes | The IID of a merge request |
| `body` | string | yes | The content of the thread |
| `commit_id` | string | no | SHA referencing commit to start this thread on |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
| `position` | hash | no | Position when creating a diff note |
| `position[base_sha]` | string | yes | Base commit SHA in the source branch |
| `position[start_sha]` | string | yes | SHA referencing commit in target branch |
@@ -902,7 +902,7 @@ To create a new thread:
"previous versions are here"
]
```
-
+
1. Create a new diff thread. This example creates a thread on an added line:
```shell
@@ -981,7 +981,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment"
@@ -1216,7 +1216,7 @@ Parameters:
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `commit_id` | integer | yes | The ID of a commit |
| `body` | string | yes | The content of the thread |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such as `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
| `position` | hash | no | Position when creating a diff note |
| `position[base_sha]` | string | yes | Base commit SHA in the source branch |
| `position[start_sha]` | string | yes | SHA referencing commit in target branch |
@@ -1252,7 +1252,7 @@ Parameters:
| `discussion_id` | integer | yes | The ID of a thread |
| `note_id` | integer | yes | The ID of a thread note |
| `body` | string | yes | The content of the note/reply |
-| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires administrator or project/group owner rights) |
+| `created_at` | string | no | Date time string, ISO 8601 formatted, such `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/commits/11/discussions/6a9c1750b37d513a43987b574953fceb50b03ce7/notes?body=comment
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 05c2fdf26fd..0ac23edf687 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1533,13 +1533,13 @@ Input type: `DastSiteProfileCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationdastsiteprofilecreateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofilecreateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. |
| <a id="mutationdastsiteprofilecreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastsiteprofilecreateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Defaults to `[]`. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofilecreateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Defaults to `[]`. |
| <a id="mutationdastsiteprofilecreatefullpath"></a>`fullPath` | [`ID!`](#id) | The project the site profile belongs to. |
| <a id="mutationdastsiteprofilecreateprofilename"></a>`profileName` | [`String!`](#string) | The name of the site profile. |
-| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
-| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will be ignored if `security_dast_site_profiles_api_option` feature flag is disabled. |
+| <a id="mutationdastsiteprofilecreaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="mutationdastsiteprofilecreatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. |
| <a id="mutationdastsiteprofilecreatetargeturl"></a>`targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
#### Fields
@@ -1577,14 +1577,14 @@ Input type: `DastSiteProfileUpdateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="mutationdastsiteprofileupdateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofileupdateauth"></a>`auth` | [`DastSiteProfileAuthInput`](#dastsiteprofileauthinput) | Parameters for authentication. |
| <a id="mutationdastsiteprofileupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationdastsiteprofileupdateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="mutationdastsiteprofileupdateexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. |
| <a id="mutationdastsiteprofileupdatefullpath"></a>`fullPath` | [`ID!`](#id) | The project the site profile belongs to. |
| <a id="mutationdastsiteprofileupdateid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile to be updated. |
| <a id="mutationdastsiteprofileupdateprofilename"></a>`profileName` | [`String!`](#string) | The name of the site profile. |
-| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will be ignored if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
-| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will be ignored if `security_dast_site_profiles_api_option` feature flag is disabled. |
+| <a id="mutationdastsiteprofileupdaterequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="mutationdastsiteprofileupdatetargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. |
| <a id="mutationdastsiteprofileupdatetargeturl"></a>`targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
#### Fields
@@ -7857,15 +7857,15 @@ Represents a DAST Site Profile.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="dastsiteprofileauth"></a>`auth` | [`DastSiteProfileAuth`](#dastsiteprofileauth) | Target authentication details. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="dastsiteprofileauth"></a>`auth` | [`DastSiteProfileAuth`](#dastsiteprofileauth) | Target authentication details. |
| <a id="dastsiteprofileeditpath"></a>`editPath` | [`String`](#string) | Relative web path to the edit page of a site profile. |
-| <a id="dastsiteprofileexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
+| <a id="dastsiteprofileexcludedurls"></a>`excludedUrls` | [`[String!]`](#string) | The URLs to skip during an authenticated scan. |
| <a id="dastsiteprofileid"></a>`id` | [`DastSiteProfileID!`](#dastsiteprofileid) | ID of the site profile. |
| <a id="dastsiteprofilenormalizedtargeturl"></a>`normalizedTargetUrl` | [`String`](#string) | Normalized URL of the target to be scanned. |
| <a id="dastsiteprofileprofilename"></a>`profileName` | [`String`](#string) | The name of the site profile. |
| <a id="dastsiteprofilereferencedinsecuritypolicies"></a>`referencedInSecurityPolicies` | [`[String!]`](#string) | List of security policy names that are referencing given project. |
-| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. Will always return `null` if `security_dast_site_profiles_additional_fields` feature flag is disabled. |
-| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. Will always return `null` if `security_dast_site_profiles_api_option` feature flag is disabled. |
+| <a id="dastsiteprofilerequestheaders"></a>`requestHeaders` | [`String`](#string) | Comma-separated list of request header names and values to be added to every request made by DAST. |
+| <a id="dastsiteprofiletargettype"></a>`targetType` | [`DastTargetTypeEnum`](#dasttargettypeenum) | The type of target to be scanned. |
| <a id="dastsiteprofiletargeturl"></a>`targetUrl` | [`String`](#string) | The URL of the target to be scanned. |
| <a id="dastsiteprofileuserpermissions"></a>`userPermissions` | [`DastSiteProfilePermissions!`](#dastsiteprofilepermissions) | Permissions for the current user on the resource. |
| <a id="dastsiteprofilevalidationstatus"></a>`validationStatus` | [`DastSiteProfileValidationStatusEnum`](#dastsiteprofilevalidationstatusenum) | The current validation status of the site profile. |
diff --git a/doc/api/project_aliases.md b/doc/api/project_aliases.md
index 439f34ad93b..e09bb167a31 100644
--- a/doc/api/project_aliases.md
+++ b/doc/api/project_aliases.md
@@ -68,8 +68,8 @@ Example response:
## Create a project alias
-Add a new alias for a project. Responds with a 201 when successful,
-400 when there are validation errors (e.g. alias already exists):
+Add a new alias for a project. When successful, responds with `201 Created`.
+When there are validation errors, for example, when the alias already exists, responds with `400 Bad Request`:
```plaintext
POST /project_aliases
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index a4ad496b667..9f04afaa713 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -18,7 +18,7 @@ See also:
Start a new export.
-The endpoint also accepts an `upload` parameter. This parameter is a hash that contains
+The endpoint also accepts an `upload` parameter. This parameter is a hash. It contains
all the necessary information to upload the exported project to a web server or
to any S3-compatible platform. At the moment we only support binary
data file uploads to the final server.
@@ -70,23 +70,14 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
Status can be one of:
-- `none`
-- `queued`
-- `started`
-- `finished`
-- `regeneration_in_progress`
-
-`queued` state represents the request for export is received, and is currently in the queue to be processed.
-
-The `started` state represents that the export process has started and is currently in progress.
-It includes the process of exporting, actions performed on the resultant file such as sending
-an email notifying the user to download the file, uploading the exported file to a web server, etc.
-
-`finished` state is after the export process has completed and the user has been notified.
-
-`regeneration_in_progress` is when an export file is available to download, and a request to generate a new export is in process.
-
-`none` is when there are no exports _queued_, _started_, _finished_, or _being regenerated_
+- `none`: No exports _queued_, _started_, _finished_, or _being regenerated_.
+- `queued`: The request for export is received, and is in the queue to be processed.
+- `started`: The export process has started and is in progress. It includes:
+ - The process of exporting.
+ - Actions performed on the resulting file, such as sending an email notifying
+ the user to download the file, or uploading the exported file to a web server.
+- `finished`: After the export process has completed and the user has been notified.
+- `regeneration_in_progress`: An export file is available to download, and a request to generate a new export is in process.
`_links` are only present when export has finished.
@@ -288,7 +279,7 @@ NOTE:
An element's `id` field in `failed_relations` references the failure record, not the relation.
NOTE:
-The `failed_relations` array is currently capped to 100 items.
+The `failed_relations` array is capped to 100 items.
```json
{
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 70b804c368e..2ad8073b409 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -253,7 +253,7 @@ error message. Possible causes for a failed commit include:
user tried to make an empty commit;
- the branch was updated by a Git push while the file edit was in progress.
-Currently GitLab Shell has a boolean return code, preventing GitLab from specifying the error.
+GitLab Shell has a boolean return code, preventing GitLab from specifying the error.
## Delete existing file in repository
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 05aa003d89e..31bea68362a 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -229,6 +229,7 @@ To add a redirect:
```markdown
---
redirect_to: '../newpath/to/file/index.md'
+ remove_date: 'YYYY-MM-DD'
---
This document was moved to [another location](../path/to/file/index.md).
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index a3c6fc86693..d88b5039204 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -82,3 +82,9 @@ There's no automated way to pull the translation levels from CrowdIn, to display
this information in the language selection dropdown. Therefore, the translation
levels are hard-coded in the `TRANSLATION_LEVELS` constant in [`i18n.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/i18n.rb),
and must be regularly updated.
+
+To update the translation levels:
+
+1. Get the translation levels (percentage of approved words) from [Crowdin](https://crowdin.com/project/gitlab-ee/settings#translations).
+
+1. Update the hard-coded translation levels in [`i18n.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/i18n.rb#L40).
diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md
index 59ae1fc0d8c..aa1733fd42a 100644
--- a/doc/development/snowplow.md
+++ b/doc/development/snowplow.md
@@ -1,6 +1,6 @@
---
redirect_to: 'snowplow/index.md'
-remove_date: '2021-06-31'
+remove_date: '2021-06-30'
---
This document was moved to [another location](snowplow/index.md).
diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md
index 4df64463e52..6b79464005d 100644
--- a/doc/user/project/repository/repository_mirroring.md
+++ b/doc/user/project/repository/repository_mirroring.md
@@ -8,7 +8,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.htm
# Repository mirroring **(FREE)**
Repository mirroring allows for the mirroring of repositories to and from external sources. You
-can use it to mirror branches, tags, and commits between repositories. It's useful when you want to use
+can use it to mirror branches, tags, and commits between repositories. It helps you use
a repository outside of GitLab.
A repository mirror at GitLab updates automatically. You can also manually trigger an update
@@ -36,7 +36,7 @@ Maintainer or Owner permissions to the mirrored project.
The following are some possible use cases for repository mirroring:
- You migrated to GitLab but still need to keep your project in another source. In that case, you
- can simply set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
+ can set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
and branches are available in your GitLab instance. **(PREMIUM)**
- You have old projects in another source that you don't use actively anymore, but don't want to
remove for archiving purposes. In that case, you can create a push mirror so that your active
@@ -105,7 +105,7 @@ reflects that `develop` has diverged and was skipped, and be marked as a failed
update.
NOTE:
-After the mirror is created, this option can currently only be modified via the [API](../../../api/remote_mirrors.md).
+After the mirror is created, this option can only be modified via the [API](../../../api/remote_mirrors.md).
### Setting up a push mirror from GitLab to GitHub
@@ -122,11 +122,15 @@ The repository pushes shortly thereafter. To force a push, select the **Update n
### Setting up a push mirror from GitLab to AWS CodeCommit
-AWS CodeCommit push mirroring is currently the best way to connect GitLab repositories to AWS CodePipeline, as GitLab isn't yet supported as one of their Source Code Management (SCM) providers.
+AWS CodeCommit push mirroring is the best way to connect GitLab repositories to
+AWS CodePipeline, as GitLab isn't yet supported as one of their Source Code Management (SCM) providers.
-Each new AWS CodePipeline needs significant AWS infrastructure setup. It also requires an individual pipeline per branch.
+Each new AWS CodePipeline needs significant AWS infrastructure setup. It also
+requires an individual pipeline per branch.
-If AWS CodeDeploy is the final step of a CodePipeline, you can, instead, leverage GitLab CI/CD pipelines and simply use the AWS CLI in the final job in `.gitlab-ci.yml` to deploy to CodeDeploy.
+If AWS CodeDeploy is the final step of a CodePipeline, you can, instead, leverage
+GitLab CI/CD pipelines and use the AWS CLI in the final job in `.gitlab-ci.yml`
+to deploy to CodeDeploy.
NOTE:
GitLab-to-AWS-CodeCommit push mirroring cannot use SSH authentication until [GitLab issue 34014](https://gitlab.com/gitlab-org/gitlab/-/issues/34014) is resolved.
@@ -214,10 +218,9 @@ If it isn't working correctly, a red `error` tag appears and shows the error mes
You can set up a repository to automatically have its branches, tags, and commits updated from an
upstream repository.
-This is useful when a repository you're interested in is located on a different server, and you want
-to be able to browse its content and its activity using the familiar GitLab interface.
-
-To configure mirror pulling for an existing project:
+If a repository you're interested in is located on a different server, and you want
+to browse its content and its activity using the GitLab interface, you can configure
+mirror pulling:
1. If you [configured two-factor authentication (2FA)](https://docs.github.com/en/github/authenticating-to-github/securing-your-account-with-two-factor-authentication-2fa)
for GitHub, create a [personal access token for GitHub](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token)
@@ -244,7 +247,7 @@ Because GitLab is now set to pull changes from the upstream repository, you shou
directly to the repository on GitLab. Instead, any commits should be pushed to the remote repository.
Changes pushed to the remote repository are pulled into the GitLab repository, either:
-- Automatically within a certain period of time.
+- Automatically in a certain period of time.
- When a [forced update](#forcing-an-update) is initiated.
WARNING:
@@ -254,7 +257,7 @@ Deleted branches and tags in the upstream repository are not reflected in the Gi
### How it works
-Once the pull mirroring feature has been enabled for a repository, the repository is added to a queue.
+After the pull mirroring feature has been enabled for a repository, the repository is added to a queue.
Once per minute, a Sidekiq cron job schedules repository mirrors to update, based on:
@@ -556,7 +559,7 @@ Bidirectional mirroring should not be used as a permanent configuration. Refer t
[Git Fusion](https://www.perforce.com/manuals/git-fusion/#Git-Fusion/section_avy_hyc_gl.html) provides a Git interface
to [Perforce Helix](https://www.perforce.com/products) which can be used by GitLab to bidirectionally
-mirror projects with GitLab. This may be useful in some situations when migrating from Perforce Helix
+mirror projects with GitLab. This can help you in some situations when migrating from Perforce Helix
to GitLab where overlapping Perforce Helix workspaces cannot be migrated simultaneously to GitLab.
If using mirroring with Perforce Helix, you should only mirror protected branches. Perforce Helix
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 632717e1b73..b719b046977 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -599,6 +599,7 @@ module API
:custom_attributes,
:last_activity_after,
:last_activity_before,
+ :topic,
:repository_storage)
.symbolize_keys
.compact
@@ -611,7 +612,6 @@ module API
finder_params[:user] = params.delete(:user) if params[:user]
finder_params[:id_after] = sanitize_id_param(params[:id_after]) if params[:id_after]
finder_params[:id_before] = sanitize_id_param(params[:id_before]) if params[:id_before]
- finder_params[:tag] = params[:topic] if params[:topic].present?
finder_params
end
diff --git a/lib/api/helpers/services_helpers.rb b/lib/api/helpers/services_helpers.rb
index c796b50f5f3..0c139f30a0b 100644
--- a/lib/api/helpers/services_helpers.rb
+++ b/lib/api/helpers/services_helpers.rb
@@ -778,40 +778,40 @@ module API
::Integrations::Assembla,
::Integrations::Bamboo,
::Integrations::Bugzilla,
+ ::Integrations::Buildkite,
::Integrations::Campfire,
::Integrations::Confluence,
::Integrations::CustomIssueTracker,
::Integrations::Datadog,
+ ::Integrations::DroneCi,
::Integrations::EmailsOnPush,
::Integrations::Ewm,
::Integrations::ExternalWiki,
::Integrations::Flowdock,
::Integrations::Irker,
+ ::Integrations::Jenkins,
::Integrations::Jira,
::Integrations::Packagist,
::Integrations::PipelinesEmail,
::Integrations::Pivotaltracker,
::Integrations::Redmine,
+ ::Integrations::Teamcity,
::Integrations::Youtrack,
- ::BuildkiteService,
::DiscordService,
- ::DroneCiService,
::HangoutsChatService,
- ::JenkinsService,
::MattermostSlashCommandsService,
::SlackSlashCommandsService,
::PrometheusService,
::PushoverService,
::SlackService,
::MattermostService,
- ::MicrosoftTeamsService,
- ::TeamcityService
+ ::MicrosoftTeamsService
]
end
def self.development_service_classes
[
- ::MockCiService,
+ ::Integrations::MockCi,
::MockMonitoringService
]
end
diff --git a/lib/gitlab/ci/build/auto_retry.rb b/lib/gitlab/ci/build/auto_retry.rb
index e6ef12975c2..b98d1d7b330 100644
--- a/lib/gitlab/ci/build/auto_retry.rb
+++ b/lib/gitlab/ci/build/auto_retry.rb
@@ -7,6 +7,11 @@ class Gitlab::Ci::Build::AutoRetry
scheduler_failure: 2
}.freeze
+ RETRY_OVERRIDES = {
+ ci_quota_exceeded: 0,
+ no_matching_runner: 0
+ }.freeze
+
def initialize(build)
@build = build
end
@@ -19,13 +24,18 @@ class Gitlab::Ci::Build::AutoRetry
private
+ delegate :failure_reason, to: :@build
+
def within_max_retry_limit?
max_allowed_retries > 0 && max_allowed_retries > @build.retries_count
end
def max_allowed_retries
strong_memoize(:max_allowed_retries) do
- options_retry_max || DEFAULT_RETRIES.fetch(@build.failure_reason.to_sym, 0)
+ RETRY_OVERRIDES[failure_reason.to_sym] ||
+ options_retry_max ||
+ DEFAULT_RETRIES[failure_reason.to_sym] ||
+ 0
end
end
@@ -38,7 +48,7 @@ class Gitlab::Ci::Build::AutoRetry
end
def retry_on_reason_or_always?
- options_retry_when.include?(@build.failure_reason.to_s) ||
+ options_retry_when.include?(failure_reason.to_s) ||
options_retry_when.include?('always')
end
diff --git a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
index 693cf1469c2..60581d2a31b 100644
--- a/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/DAST.latest.gitlab-ci.yml
@@ -46,10 +46,13 @@ dast:
$REVIEW_DISABLED && $DAST_WEBSITE == null &&
$DAST_API_SPECIFICATION == null
when: never
- - if: $CI_COMMIT_BRANCH &&
+ - if: $CI_MERGE_REQUEST_IID &&
$CI_KUBERNETES_ACTIVE &&
$GITLAB_FEATURES =~ /\bdast\b/
+ - if: $CI_MERGE_REQUEST_IID && ($DAST_WEBSITE || $DAST_API_SPECIFICATION)
+ - if: $CI_OPEN_MERGE_REQUESTS
+ when: never
- if: $CI_COMMIT_BRANCH &&
- $DAST_WEBSITE
- - if: $CI_COMMIT_BRANCH &&
- $DAST_API_SPECIFICATION
+ $CI_KUBERNETES_ACTIVE &&
+ $GITLAB_FEATURES =~ /\bdast\b/
+ - if: $CI_COMMIT_BRANCH && ($DAST_WEBSITE || $DAST_API_SPECIFICATION)
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 71db8ab6067..8139a294269 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -20,7 +20,7 @@ module Gitlab
raise UnknownIncomingEmail unless handler
handler.execute.tap do
- Gitlab::Metrics.add_event(handler.metrics_event, handler.metrics_params)
+ Gitlab::Metrics::BackgroundTransaction.current&.add_event(handler.metrics_event, handler.metrics_params)
end
end
diff --git a/lib/gitlab/integrations/sti_type.rb b/lib/gitlab/integrations/sti_type.rb
index 5a38c382b81..f043a8fa060 100644
--- a/lib/gitlab/integrations/sti_type.rb
+++ b/lib/gitlab/integrations/sti_type.rb
@@ -4,9 +4,9 @@ module Gitlab
module Integrations
class StiType < ActiveRecord::Type::String
NAMESPACED_INTEGRATIONS = Set.new(%w(
- Asana Assembla Bamboo Bugzilla Campfire Confluence CustomIssueTracker Datadog
- EmailsOnPush Ewm ExternalWiki Flowdock IssueTracker Irker Jira Packagist PipelinesEmail
- Pivotaltracker Redmine Youtrack
+ Asana Assembla Bamboo Bugzilla Buildkite Campfire Confluence CustomIssueTracker Datadog
+ DroneCi EmailsOnPush Ewm ExternalWiki Flowdock IssueTracker Irker Jenkins Jira MockCi Packagist
+ PipelinesEmail Pivotaltracker Redmine Teamcity Youtrack
)).freeze
def cast(value)
diff --git a/lib/gitlab/usage/metrics/aggregates/aggregate.rb b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
index 4c40bfbc06f..71a14e02f9d 100644
--- a/lib/gitlab/usage/metrics/aggregates/aggregate.rb
+++ b/lib/gitlab/usage/metrics/aggregates/aggregate.rb
@@ -22,9 +22,7 @@ module Gitlab
}.freeze
class Aggregate
- delegate :weekly_time_range,
- :monthly_time_range,
- to: Gitlab::UsageDataCounters::HLLRedisCounter
+ include Gitlab::Usage::TimeFrame
def initialize(recorded_at)
@aggregated_metrics = load_metrics(AGGREGATED_METRICS_PATH)
@@ -32,15 +30,15 @@ module Gitlab
end
def all_time_data
- aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME)
+ aggregated_metrics_data(start_date: nil, end_date: nil, time_frame: Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
def monthly_data
- aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Utils::UsageData::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(**monthly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME))
end
def weekly_data
- aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Utils::UsageData::SEVEN_DAYS_TIME_FRAME_NAME))
+ aggregated_metrics_data(**weekly_time_range.merge(time_frame: Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME))
end
private
@@ -54,7 +52,7 @@ module Gitlab
case aggregation[:source]
when REDIS_SOURCE
- if time_frame == Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME
+ if time_frame == Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME
data[aggregation[:name]] = Gitlab::Utils::UsageData::FALLBACK
Gitlab::ErrorTracking
.track_and_raise_for_dev_exception(
diff --git a/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb b/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
index 3069afab147..eccf79b9703 100644
--- a/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
+++ b/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll.rb
@@ -56,15 +56,15 @@ module Gitlab
end
def time_period_to_human_name(time_period)
- return Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME if time_period.blank?
+ return Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME if time_period.blank?
start_date = time_period.first.to_date
end_date = time_period.last.to_date
if (end_date - start_date).to_i > 7
- Gitlab::Utils::UsageData::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
+ Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME
else
- Gitlab::Utils::UsageData::SEVEN_DAYS_TIME_FRAME_NAME
+ Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
index 88e520abce8..7b5bee3f8bd 100644
--- a/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/base_metric.rb
@@ -6,6 +6,7 @@ module Gitlab
module Instrumentations
class BaseMetric
include Gitlab::Utils::UsageData
+ include Gitlab::Usage::TimeFrame
attr_reader :time_frame
attr_reader :options
diff --git a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
index f83f90dea03..24994f14167 100644
--- a/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/database_metric.rb
@@ -52,7 +52,7 @@ module Gitlab
def time_constraints
case time_frame
when '28d'
- { created_at: 30.days.ago..2.days.ago }
+ monthly_time_range_db_params
when 'all'
{}
when 'none'
diff --git a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
index e6d892f217b..502a8147473 100644
--- a/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
+++ b/lib/gitlab/usage/metrics/instrumentations/redis_hll_metric.rb
@@ -35,9 +35,9 @@ module Gitlab
def time_constraints
case time_frame
when '28d'
- { start_date: 4.weeks.ago.to_date, end_date: Date.current }
+ monthly_time_range
when '7d'
- { start_date: 7.days.ago.to_date, end_date: Date.current }
+ weekly_time_range
else
raise "Unknown time frame: #{time_frame} for RedisHLLMetric"
end
diff --git a/lib/gitlab/usage/time_frame.rb b/lib/gitlab/usage/time_frame.rb
new file mode 100644
index 00000000000..966a087ee07
--- /dev/null
+++ b/lib/gitlab/usage/time_frame.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module TimeFrame
+ ALL_TIME_TIME_FRAME_NAME = "all"
+ SEVEN_DAYS_TIME_FRAME_NAME = "7d"
+ TWENTY_EIGHT_DAYS_TIME_FRAME_NAME = "28d"
+
+ def weekly_time_range
+ { start_date: 7.days.ago.to_date, end_date: Date.current }
+ end
+
+ def monthly_time_range
+ { start_date: 4.weeks.ago.to_date, end_date: Date.current }
+ end
+
+ # This time range is skewed for batch counter performance.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42972
+ def monthly_time_range_db_params(column: :created_at)
+ { column => 30.days.ago..2.days.ago }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index aeae176e943..6048a3b2283 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -33,6 +33,7 @@ module Gitlab
class << self
include Gitlab::Utils::UsageData
include Gitlab::Utils::StrongMemoize
+ include Gitlab::Usage::TimeFrame
def data(force_refresh: false)
Rails.cache.fetch('usage_data', force: force_refresh, expires_in: 2.weeks) do
@@ -55,7 +56,7 @@ module Gitlab
.merge(object_store_usage_data)
.merge(topology_usage_data)
.merge(usage_activity_by_stage)
- .merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, last_28_days_time_period))
+ .merge(usage_activity_by_stage(:usage_activity_by_stage_monthly, monthly_time_range_db_params))
.merge(analytics_unique_visits_data)
.merge(compliance_unique_visits_data)
.merge(search_unique_visits_data)
@@ -228,17 +229,17 @@ module Gitlab
{
counts_monthly: {
# rubocop: disable UsageData/LargeTable:
- deployments: deployment_count(Deployment.where(last_28_days_time_period)),
- successful_deployments: deployment_count(Deployment.success.where(last_28_days_time_period)),
- failed_deployments: deployment_count(Deployment.failed.where(last_28_days_time_period)),
+ deployments: deployment_count(Deployment.where(monthly_time_range_db_params)),
+ successful_deployments: deployment_count(Deployment.success.where(monthly_time_range_db_params)),
+ failed_deployments: deployment_count(Deployment.failed.where(monthly_time_range_db_params)),
# rubocop: enable UsageData/LargeTable:
- projects: count(Project.where(last_28_days_time_period), start: minimum_id(Project), finish: maximum_id(Project)),
- packages: count(::Packages::Package.where(last_28_days_time_period)),
- personal_snippets: count(PersonalSnippet.where(last_28_days_time_period)),
- project_snippets: count(ProjectSnippet.where(last_28_days_time_period)),
- projects_with_alerts_created: distinct_count(::AlertManagement::Alert.where(last_28_days_time_period), :project_id)
+ projects: count(Project.where(monthly_time_range_db_params), start: minimum_id(Project), finish: maximum_id(Project)),
+ packages: count(::Packages::Package.where(monthly_time_range_db_params)),
+ personal_snippets: count(PersonalSnippet.where(monthly_time_range_db_params)),
+ project_snippets: count(ProjectSnippet.where(monthly_time_range_db_params)),
+ projects_with_alerts_created: distinct_count(::AlertManagement::Alert.where(monthly_time_range_db_params), :project_id)
}.merge(
- snowplow_event_counts(last_28_days_time_period(column: :collector_tstamp))
+ snowplow_event_counts(monthly_time_range_db_params(column: :collector_tstamp))
).tap do |data|
data[:snippets] = add(data[:personal_snippets], data[:project_snippets])
end
@@ -522,10 +523,6 @@ module Gitlab
"#{platform}-#{ohai_data['platform_version']}"
end
- def last_28_days_time_period(column: :created_at)
- { column => 30.days.ago..2.days.ago }
- end
-
# Source: https://gitlab.com/gitlab-data/analytics/blob/master/transform/snowflake-dbt/data/ping_metrics_to_stage_mapping_data.csv
def usage_activity_by_stage(key = :usage_activity_by_stage, time_period = {})
{
@@ -743,7 +740,7 @@ module Gitlab
hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['analytics_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
- results['analytics_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+ results['analytics_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics, **monthly_time_range) }
{ analytics_unique_visits: results }
end
@@ -753,7 +750,7 @@ module Gitlab
hash[target] = redis_usage_data { unique_visit_service.unique_visits_for(targets: target) }
end
results['compliance_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance) }
- results['compliance_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+ results['compliance_unique_visits_for_any_target_monthly'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :compliance, **monthly_time_range) }
{ compliance_unique_visits: results }
end
@@ -761,11 +758,11 @@ module Gitlab
def search_unique_visits_data
events = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category('search')
results = events.each_with_object({}) do |event, hash|
- hash[event] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event, start_date: 7.days.ago.to_date, end_date: Date.current) }
+ hash[event] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: event, **weekly_time_range) }
end
- results['search_unique_visits_for_any_target_weekly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 7.days.ago.to_date, end_date: Date.current) }
- results['search_unique_visits_for_any_target_monthly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, start_date: 4.weeks.ago.to_date, end_date: Date.current) }
+ results['search_unique_visits_for_any_target_weekly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, **weekly_time_range) }
+ results['search_unique_visits_for_any_target_monthly'] = redis_usage_data { ::Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: events, **monthly_time_range) }
{ search_unique_visits: results }
end
diff --git a/lib/gitlab/usage_data_counters/hll_redis_counter.rb b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
index 833eebd5d04..2a231f8fce0 100644
--- a/lib/gitlab/usage_data_counters/hll_redis_counter.rb
+++ b/lib/gitlab/usage_data_counters/hll_redis_counter.rb
@@ -38,6 +38,7 @@ module Gitlab
# * Get unique counts per user: Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_dashboard', start_date: 28.days.ago, end_date: Date.current)
class << self
include Gitlab::Utils::UsageData
+ include Gitlab::Usage::TimeFrame
# Track unique events
#
@@ -98,14 +99,6 @@ module Gitlab
end
end
- def weekly_time_range
- { start_date: 7.days.ago.to_date, end_date: Date.current }
- end
-
- def monthly_time_range
- { start_date: 4.weeks.ago.to_date, end_date: Date.current }
- end
-
def known_event?(event_name)
event_for(event_name).present?
end
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index a90f617393b..4ea5b5a87de 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -42,9 +42,6 @@ module Gitlab
FALLBACK = -1
HISTOGRAM_FALLBACK = { '-1' => -1 }.freeze
DISTRIBUTED_HLL_FALLBACK = -2
- ALL_TIME_TIME_FRAME_NAME = "all"
- SEVEN_DAYS_TIME_FRAME_NAME = "7d"
- TWENTY_EIGHT_DAYS_TIME_FRAME_NAME = "28d"
MAX_BUCKET_SIZE = 100
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
diff --git a/lib/tasks/gitlab/docs/redirect.rake b/lib/tasks/gitlab/docs/redirect.rake
index 0c8e0755348..bb5dad94a8f 100644
--- a/lib/tasks/gitlab/docs/redirect.rake
+++ b/lib/tasks/gitlab/docs/redirect.rake
@@ -1,8 +1,11 @@
# frozen_string_literal: true
require 'date'
require 'pathname'
+require "yaml"
+#
# https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page
+#
namespace :gitlab do
namespace :docs do
desc 'GitLab | Docs | Create a doc redirect'
@@ -38,13 +41,14 @@ namespace :gitlab do
# - If this is an external URL, move the date 1 year later.
# - If this is a relative URL, move the date 3 months later.
#
- date = Time.now.utc.strftime('%Y-%m-%d')
- date = new_path.start_with?('http') ? Date.parse(date) >> 12 : Date.parse(date) >> 3
+ today = Time.now.utc.to_date
+ date = new_path.start_with?('http') ? today >> 12 : today >> 3
puts "=> Creating new redirect from #{old_path} to #{new_path}"
File.open(old_path, 'w') do |post|
post.puts '---'
post.puts "redirect_to: '#{new_path}'"
+ post.puts "remove_date: '#{date}'"
post.puts '---'
post.puts
post.puts "This file was moved to [another location](#{new_path})."
@@ -53,5 +57,69 @@ namespace :gitlab do
post.puts "<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->"
end
end
+
+ desc 'GitLab | Docs | Clean up old redirects'
+ task :clean_redirects do
+ #
+ # Calculate new path from the redirect URL.
+ #
+ # If the redirect is not a full URL:
+ # 1. Create a new Pathname of the file
+ # 2. Use dirname to get all but the last component of the path
+ # 3. Join with the redirect_to entry
+ # 4. Substitute:
+ # - '.md' => '.html'
+ # - 'doc/' => '/ee/'
+ #
+ # If the redirect URL is a full URL pointing to the Docs site
+ # (cross-linking among the 4 products), remove the FQDN prefix:
+ #
+ # From : https://docs.gitlab.com/ee/install/requirements.html
+ # To : /ee/install/requirements.html
+ #
+ def new_path(redirect, filename)
+ if !redirect.start_with?('http')
+ Pathname.new(filename).dirname.join(redirect).to_s.gsub(%r(\.md), '.html').gsub(%r(doc/), '/ee/')
+ elsif redirect.start_with?('https://docs.gitlab.com')
+ redirect.gsub('https://docs.gitlab.com', '')
+ else
+ redirect
+ end
+ end
+
+ today = Time.now.utc.to_date
+
+ #
+ # Find the files to be deleted.
+ # Exclude 'doc/development/documentation/index.md' because it
+ # contains an example of the YAML front matter.
+ #
+ files_to_be_deleted = `grep -Ir 'remove_date:' doc | grep -v doc/development/documentation/index.md | cut -d ":" -f 1`.split("\n")
+
+ #
+ # Iterate over the files to be deleted and print the needed
+ # YAML entries for the Docs site redirects.
+ #
+ files_to_be_deleted.each do |filename|
+ frontmatter = YAML.safe_load(File.read(filename))
+ remove_date = Date.parse(frontmatter['remove_date'])
+ old_path = filename.gsub(%r(\.md), '.html').gsub(%r(doc/), '/ee/')
+
+ #
+ # Check if the removal date is before today, and delete the file and
+ # print the content to be pasted in
+ # https://gitlab.com/gitlab-org/gitlab-docs/-/blob/master/content/_data/redirects.yaml.
+ # The remove_date of redirects.yaml should be nine months in the future.
+ # To not be confused with the remove_date of the Markdown page.
+ #
+ if remove_date < today
+ File.delete(filename) if File.exist?(filename)
+
+ puts " - from: #{old_path}"
+ puts " to: #{new_path(frontmatter['redirect_to'], filename)}"
+ puts " remove_date: #{remove_date >> 9}"
+ end
+ end
+ end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 476cf5abf55..2b0403eb83f 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -31147,6 +31147,9 @@ msgstr ""
msgid "StatusCheck|Target branch"
msgstr ""
+msgid "StatusCheck|Update status check"
+msgstr ""
+
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
diff --git a/spec/config/metrics/aggregates/aggregated_metrics_spec.rb b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
index 9aba86cdaf2..b5f8d363d40 100644
--- a/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
+++ b/spec/config/metrics/aggregates/aggregated_metrics_spec.rb
@@ -25,9 +25,9 @@ RSpec.describe 'aggregated metrics' do
RSpec::Matchers.define :have_known_time_frame do
allowed_time_frames = [
- Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME,
- Gitlab::Utils::UsageData::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME,
- Gitlab::Utils::UsageData::SEVEN_DAYS_TIME_FRAME_NAME
+ Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME,
+ Gitlab::Usage::TimeFrame::TWENTY_EIGHT_DAYS_TIME_FRAME_NAME,
+ Gitlab::Usage::TimeFrame::SEVEN_DAYS_TIME_FRAME_NAME
]
match do |aggregate|
@@ -63,7 +63,7 @@ RSpec.describe 'aggregated metrics' do
let_it_be(:events_records) { known_events.select { |event| aggregate[:events].include?(event[:name]) } }
it "does not include 'all' time frame for Redis sourced aggregate" do
- expect(aggregate[:time_frame]).not_to include(Gitlab::Utils::UsageData::ALL_TIME_TIME_FRAME_NAME)
+ expect(aggregate[:time_frame]).not_to include(Gitlab::Usage::TimeFrame::ALL_TIME_TIME_FRAME_NAME)
end
it "only refers to known events" do
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index d8fb3b226ed..642c76abe79 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -95,7 +95,7 @@ RSpec.describe Projects::ServicesController do
expect(response).to be_successful
expect(json_response).to be_empty
- expect(BuildkiteService.first).to be_present
+ expect(Integrations::Buildkite.first).to be_present
end
it 'creates the ServiceHook object' do
@@ -103,7 +103,7 @@ RSpec.describe Projects::ServicesController do
expect(response).to be_successful
expect(json_response).to be_empty
- expect(BuildkiteService.first.service_hook).to be_present
+ expect(Integrations::Buildkite.first.service_hook).to be_present
end
def do_put
diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb
index 8b8a950d081..77f73fa4d76 100644
--- a/spec/factories/integrations.rb
+++ b/spec/factories/integrations.rb
@@ -38,7 +38,7 @@ FactoryBot.define do
end
end
- factory :drone_ci_service do
+ factory :drone_ci_service, class: 'Integrations::DroneCi' do
project
active { true }
drone_url { 'https://bamboo.example.com' }
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index d9b5ec17a4a..2ff6288e2e4 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -104,7 +104,7 @@ RSpec.describe 'Merge request > User sees merge widget', :js do
before do
create(:service, project: project,
active: true,
- type: 'CiService',
+ type: 'DroneCiService',
category: 'ci')
visit project_merge_request_path(project, merge_request)
diff --git a/spec/features/projects/branches/user_deletes_branch_spec.rb b/spec/features/projects/branches/user_deletes_branch_spec.rb
index 53994ec018e..a5217007f3c 100644
--- a/spec/features/projects/branches/user_deletes_branch_spec.rb
+++ b/spec/features/projects/branches/user_deletes_branch_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe "User deletes branch", :js do
branch_search.native.send_keys(:enter)
page.within(".js-branch-improve\\/awesome") do
- accept_alert { find(".btn-danger").click }
+ accept_alert { click_link(title: 'Delete branch') }
end
wait_for_requests
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index f805416b03d..0c89ee28f30 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -99,11 +99,13 @@ RSpec.describe 'Branches' do
end
describe 'Delete unprotected branch on Overview' do
- it 'removes branch after confirmation', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/239019' do
+ it 'removes branch after confirmation', :js do
visit project_branches_filtered_path(project, state: 'all')
expect(all('.all-branches').last).to have_selector('li', count: 20)
- accept_confirm { first('.js-branch-item .btn-danger').click }
+ accept_confirm do
+ within('.js-branch-item', match: :first) { click_link(title: 'Delete branch') }
+ end
expect(all('.all-branches').last).to have_selector('li', count: 19)
end
@@ -172,7 +174,9 @@ RSpec.describe 'Branches' do
expect(page).to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 1)
- accept_confirm { find('.js-branch-fix .btn-danger').click }
+ accept_confirm do
+ within('.js-branch-fix') { click_link(title: 'Delete branch') }
+ end
expect(page).not_to have_content('fix')
expect(find('.all-branches')).to have_selector('li', count: 0)
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 1d7be7fa7a3..bc2ea540879 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -333,7 +333,7 @@ RSpec.describe 'Environment' do
visit project_branches_filtered_path(project, state: 'all', search: 'feature')
remove_branch_with_hooks(project, user, 'feature') do
- page.within('.js-branch-feature') { find('a.btn-danger').click }
+ within('.js-branch-feature') { click_link(title: 'Delete branch') }
end
visit_environment(environment)
diff --git a/spec/features/projects/services/disable_triggers_spec.rb b/spec/features/projects/services/disable_triggers_spec.rb
index d9e200cf563..c6413685f38 100644
--- a/spec/features/projects/services/disable_triggers_spec.rb
+++ b/spec/features/projects/services/disable_triggers_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Disable individual triggers', :js do
let(:service_name) { 'Jenkins' }
it 'shows trigger checkboxes' do
- event_count = JenkinsService.supported_events.count
+ event_count = Integrations::Jenkins.supported_events.count
expect(page).to have_content "Trigger"
expect(page).to have_css(checkbox_selector, visible: :all, count: event_count)
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index c18b0f2688b..2ac829d406c 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -128,23 +128,23 @@ RSpec.describe 'Project' do
end
it 'shows project topics' do
- project.update_attribute(:tag_list, 'topic1')
+ project.update_attribute(:topic_list, 'topic1')
visit path
expect(page).to have_css('.home-panel-topic-list')
- expect(page).to have_link('Topic1', href: explore_projects_path(tag: 'topic1'))
+ expect(page).to have_link('Topic1', href: explore_projects_path(topic: 'topic1'))
end
- it 'shows up to 3 project tags' do
- project.update_attribute(:tag_list, 'topic1, topic2, topic3, topic4')
+ it 'shows up to 3 project topics' do
+ project.update_attribute(:topic_list, 'topic1, topic2, topic3, topic4')
visit path
expect(page).to have_css('.home-panel-topic-list')
- expect(page).to have_link('Topic1', href: explore_projects_path(tag: 'topic1'))
- expect(page).to have_link('Topic2', href: explore_projects_path(tag: 'topic2'))
- expect(page).to have_link('Topic3', href: explore_projects_path(tag: 'topic3'))
+ expect(page).to have_link('Topic1', href: explore_projects_path(topic: 'topic1'))
+ expect(page).to have_link('Topic2', href: explore_projects_path(topic: 'topic2'))
+ expect(page).to have_link('Topic3', href: explore_projects_path(topic: 'topic3'))
expect(page).to have_content('+ 1 more')
end
end
diff --git a/spec/features/protected_branches_spec.rb b/spec/features/protected_branches_spec.rb
index 207b74c990a..2436132297e 100644
--- a/spec/features/protected_branches_spec.rb
+++ b/spec/features/protected_branches_spec.rb
@@ -21,13 +21,13 @@ RSpec.describe 'Protected Branches', :js do
expect(ProtectedBranch.count).to eq(1)
end
- it 'does not allow developer to removes protected branch' do
+ it 'does not allow developer to remove protected branch' do
visit project_branches_path(project)
find('input[data-testid="branch-search"]').set('fix')
find('input[data-testid="branch-search"]').native.send_keys(:enter)
- expect(page).to have_css('.btn-danger.disabled')
+ expect(page).to have_selector('button[data-testid="remove-protected-branch"][disabled]')
end
end
end
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 364e5de4ece..f47f070fea8 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -137,9 +137,9 @@ RSpec.describe ProjectsFinder do
end
end
- describe 'filter by tags' do
+ describe 'filter by tags (deprecated)' do
before do
- public_project.tag_list = 'foo'
+ public_project.topic_list = 'foo'
public_project.save!
end
@@ -148,6 +148,17 @@ RSpec.describe ProjectsFinder do
it { is_expected.to eq([public_project]) }
end
+ describe 'filter by topics' do
+ before do
+ public_project.topic_list = 'foo'
+ public_project.save!
+ end
+
+ let(:params) { { topic: 'foo' } }
+
+ it { is_expected.to eq([public_project]) }
+ end
+
describe 'filter by personal' do
let!(:personal_project) { create(:project, namespace: user.namespace) }
let(:params) { { personal: true } }
diff --git a/spec/lib/gitlab/ci/build/auto_retry_spec.rb b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
index cfa8c9cd938..b107553bbce 100644
--- a/spec/lib/gitlab/ci/build/auto_retry_spec.rb
+++ b/spec/lib/gitlab/ci/build/auto_retry_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
describe '#allowed?' do
using RSpec::Parameterized::TableSyntax
- let(:build) { create(:ci_build) }
+ let(:build) { build_stubbed(:ci_build) }
subject { auto_retry.allowed? }
@@ -22,6 +22,8 @@ RSpec.describe Gitlab::Ci::Build::AutoRetry do
"not matching reason" | 0 | { when: %w[script_error], max: 2 } | :api_failure | false
"scheduler failure override" | 1 | { when: %w[scheduler_failure], max: 1 } | :scheduler_failure | false
"default for scheduler failure" | 1 | {} | :scheduler_failure | true
+ "quota is exceeded" | 0 | { max: 2 } | :ci_quota_exceeded | false
+ "no matching runner" | 0 | { max: 2 } | :no_matching_runner | false
end
with_them do
diff --git a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
index 324ed498abc..cdcc862c376 100644
--- a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
+++ b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
@@ -27,7 +27,7 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do
end
context 'when models using single-type inheritance are used' do
- let(:models) { [Group, CiService, Namespace] }
+ let(:models) { [Group, Integrations::BaseCi, Namespace] }
before do
models.each do |model|
diff --git a/spec/lib/gitlab/email/receiver_spec.rb b/spec/lib/gitlab/email/receiver_spec.rb
index 9b05c12ef57..2c1fe529a5d 100644
--- a/spec/lib/gitlab/email/receiver_spec.rb
+++ b/spec/lib/gitlab/email/receiver_spec.rb
@@ -5,9 +5,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Email::Receiver do
include_context :email_shared_context
- shared_examples 'correctly finds the mail key' do
- specify do
+ shared_examples 'correctly finds the mail key and adds metric event' do
+ let(:metric_transaction) { double('Gitlab::Metrics::WebTransaction') }
+
+ specify :aggregate_failures do
expect(Gitlab::Email::Handler).to receive(:for).with(an_instance_of(Mail::Message), 'gitlabhq/gitlabhq+auth_token').and_return(handler)
+ expect(::Gitlab::Metrics::BackgroundTransaction).to receive(:current).and_return(metric_transaction)
+ expect(metric_transaction).to receive(:add_event).with(handler.metrics_event, handler.metrics_params)
receiver.execute
end
@@ -30,7 +34,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when in a Delivered-To header' do
let(:email_raw) { fixture_file('emails/forwarded_new_issue.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
it 'parses the metadata' do
expect(metadata[:delivered_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com", "support@example.com"])
@@ -40,7 +44,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when in an Envelope-To header' do
let(:email_raw) { fixture_file('emails/envelope_to_header.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
it 'parses the metadata' do
expect(metadata[:envelope_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com"])
@@ -50,7 +54,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when in an X-Envelope-To header' do
let(:email_raw) { fixture_file('emails/x_envelope_to_header.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
it 'parses the metadata' do
expect(metadata[:x_envelope_to]). to eq(["incoming+gitlabhq/gitlabhq+auth_token@appmail.example.com"])
@@ -60,7 +64,7 @@ RSpec.describe Gitlab::Email::Receiver do
context 'when enclosed with angle brackets in an Envelope-To header' do
let(:email_raw) { fixture_file('emails/envelope_to_header_with_angle_brackets.eml') }
- it_behaves_like 'correctly finds the mail key'
+ it_behaves_like 'correctly finds the mail key and adds metric event'
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index d2d9282e90b..5ddbc98a172 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -91,7 +91,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(described_class.usage_activity_by_stage_package({})).to eq(
projects_with_packages: 2
)
- expect(described_class.usage_activity_by_stage_package(described_class.last_28_days_time_period)).to eq(
+ expect(described_class.usage_activity_by_stage_package(described_class.monthly_time_range_db_params)).to eq(
projects_with_packages: 1
)
end
@@ -135,7 +135,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
project_clusters_disabled: 2,
project_clusters_enabled: 10
)
- expect(described_class.usage_activity_by_stage_configure(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_configure(described_class.monthly_time_range_db_params)).to include(
clusters_applications_cert_managers: 1,
clusters_applications_helm: 1,
clusters_applications_ingress: 1,
@@ -185,7 +185,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
snippets: 2,
suggestions: 2
)
- expect(described_class.usage_activity_by_stage_create(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_create(described_class.monthly_time_range_db_params)).to include(
deploy_keys: 1,
keys: 1,
merge_requests: 1,
@@ -225,7 +225,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
omniauth_providers: ['google_oauth2'],
user_auth_by_provider: { 'group_saml' => 2, 'ldap' => 4, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
events: 1,
groups: 1,
users_created: 3,
@@ -252,7 +252,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
unique_users_all_imports: 10
)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
unique_users_all_imports: 5
)
end
@@ -327,7 +327,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
groups_imported: Gitlab::UsageData::DEPRECATED_VALUE
}
)
- expect(described_class.usage_activity_by_stage_manage(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
{
bulk_imports: {
gitlab_v1: 1,
@@ -411,7 +411,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_with_enabled_alert_integrations_histogram: { '1' => 2 }
)
- data_28_days = described_class.usage_activity_by_stage_monitor(described_class.last_28_days_time_period)
+ data_28_days = described_class.usage_activity_by_stage_monitor(described_class.monthly_time_range_db_params)
expect(data_28_days).to include(
clusters: 1,
clusters_applications_prometheus: 1,
@@ -450,7 +450,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
projects_jira_dvcs_cloud_active: 2,
projects_jira_dvcs_server_active: 2
)
- expect(described_class.usage_activity_by_stage_plan(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(
issues: 2,
notes: 1,
projects: 1,
@@ -479,7 +479,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
releases: 2,
successful_deployments: 2
)
- expect(described_class.usage_activity_by_stage_release(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(
deployments: 1,
failed_deployments: 1,
releases: 1,
@@ -513,7 +513,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
ci_triggers: 2,
clusters_applications_runner: 2
)
- expect(described_class.usage_activity_by_stage_verify(described_class.last_28_days_time_period)).to include(
+ expect(described_class.usage_activity_by_stage_verify(described_class.monthly_time_range_db_params)).to include(
ci_builds: 1,
ci_external_pipelines: 1,
ci_internal_pipelines: 1,
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 3b5f2a198e2..024ac1b8094 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -3162,6 +3162,81 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
end
+ describe '#environments_in_self_and_descendants' do
+ subject { pipeline.environments_in_self_and_descendants }
+
+ context 'when pipeline is not child nor parent' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+
+ it 'returns just the pipeline environment' do
+ expect(subject).to contain_exactly(build.deployment.environment)
+ end
+ end
+
+ context 'when pipeline is in extended family' do
+ let_it_be(:parent) { create(:ci_pipeline) }
+ let_it_be(:parent_build) { create(:ci_build, :with_deployment, environment: 'staging', pipeline: parent) }
+
+ let_it_be(:pipeline) { create(:ci_pipeline, child_of: parent) }
+ let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+
+ let_it_be(:child) { create(:ci_pipeline, child_of: pipeline) }
+ let_it_be(:child_build) { create(:ci_build, :with_deployment, environment: 'canary', pipeline: child) }
+
+ let_it_be(:grandchild) { create(:ci_pipeline, child_of: child) }
+ let_it_be(:grandchild_build) { create(:ci_build, :with_deployment, environment: 'test', pipeline: grandchild) }
+
+ let_it_be(:sibling) { create(:ci_pipeline, child_of: parent) }
+ let_it_be(:sibling_build) { create(:ci_build, :with_deployment, environment: 'review', pipeline: sibling) }
+
+ it 'returns its own environment and from all descendants' do
+ expected_environments = [
+ build.deployment.environment,
+ child_build.deployment.environment,
+ grandchild_build.deployment.environment
+ ]
+ expect(subject).to match_array(expected_environments)
+ end
+
+ it 'does not return parent environment' do
+ expect(subject).not_to include(parent_build.deployment.environment)
+ end
+
+ it 'does not return sibling environment' do
+ expect(subject).not_to include(sibling_build.deployment.environment)
+ end
+ end
+
+ context 'when each pipeline has multiple environments' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let_it_be(:build1) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+ let_it_be(:build2) { create(:ci_build, :with_deployment, environment: 'staging', pipeline: pipeline) }
+
+ let_it_be(:child) { create(:ci_pipeline, child_of: pipeline) }
+ let_it_be(:child_build1) { create(:ci_build, :with_deployment, environment: 'canary', pipeline: child) }
+ let_it_be(:child_build2) { create(:ci_build, :with_deployment, environment: 'test', pipeline: child) }
+
+ it 'returns all related environments' do
+ expected_environments = [
+ build1.deployment.environment,
+ build2.deployment.environment,
+ child_build1.deployment.environment,
+ child_build2.deployment.environment
+ ]
+ expect(subject).to match_array(expected_environments)
+ end
+ end
+
+ context 'when pipeline has no environment' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+
+ it 'returns empty' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+
describe '#root_ancestor' do
subject { pipeline.root_ancestor }
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index 09a73a4cdcb..1b9b38a0932 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -245,6 +245,17 @@ RSpec.describe EnvironmentStatus do
end
end
+ context 'when there is a deployment in a child pipeline' do
+ let!(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
+ let!(:child_build) { create(:ci_build, :with_deployment, :start_review_app, pipeline: child_pipeline) }
+ let(:child_environment) { child_build.deployment.environment }
+
+ it 'returns both parent and child entries' do
+ expect(subject.count).to eq(2)
+ expect(subject.map(&:id)).to contain_exactly(environment.id, child_environment.id)
+ end
+ end
+
context 'when environment is stopped' do
before do
environment.stop!
diff --git a/spec/models/project_services/buildkite_service_spec.rb b/spec/models/integrations/buildkite_spec.rb
index f6bf1551bf0..7dc81da7003 100644
--- a/spec/models/project_services/buildkite_service_spec.rb
+++ b/spec/models/integrations/buildkite_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe BuildkiteService, :use_clean_rails_memory_store_caching do
+RSpec.describe Integrations::Buildkite, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
include StubRequests
diff --git a/spec/models/project_services/drone_ci_service_spec.rb b/spec/models/integrations/drone_ci_spec.rb
index 9aaf4f7a644..cae1cd189a9 100644
--- a/spec/models/project_services/drone_ci_service_spec.rb
+++ b/spec/models/integrations/drone_ci_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe DroneCiService, :use_clean_rails_memory_store_caching do
+RSpec.describe Integrations::DroneCi, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
describe 'associations' do
@@ -32,7 +32,7 @@ RSpec.describe DroneCiService, :use_clean_rails_memory_store_caching do
end
shared_context :drone_ci_service do
- let(:drone) { DroneCiService.new }
+ let(:drone) { described_class.new }
let(:project) { create(:project, :repository, name: 'project') }
let(:path) { project.full_path }
let(:drone_url) { 'http://drone.example.com' }
@@ -41,7 +41,7 @@ RSpec.describe DroneCiService, :use_clean_rails_memory_store_caching do
let(:token) { 'secret' }
let(:iid) { rand(1..9999) }
- # URL's
+ # URLs
let(:build_page) { "#{drone_url}/gitlab/#{path}/redirect/commits/#{sha}?branch=#{branch}" }
let(:commit_status_path) { "#{drone_url}/gitlab/#{path}/commits/#{sha}?branch=#{branch}&access_token=#{token}" }
diff --git a/spec/models/project_services/jenkins_service_spec.rb b/spec/models/integrations/jenkins_spec.rb
index 4663e41736a..2374dfe4480 100644
--- a/spec/models/project_services/jenkins_service_spec.rb
+++ b/spec/models/integrations/jenkins_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe JenkinsService do
+RSpec.describe Integrations::Jenkins do
let(:project) { create(:project) }
let(:jenkins_url) { 'http://jenkins.example.com/' }
let(:jenkins_hook_url) { jenkins_url + 'project/my_project' }
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/integrations/teamcity_spec.rb
index f71dad86a08..b88a4722ad4 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/integrations/teamcity_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe TeamcityService, :use_clean_rails_memory_store_caching do
+RSpec.describe Integrations::Teamcity, :use_clean_rails_memory_store_caching do
include ReactiveCachingHelpers
include StubRequests
diff --git a/spec/models/project_repository_storage_move_spec.rb b/spec/models/project_repository_storage_move_spec.rb
deleted file mode 100644
index eb193a44680..00000000000
--- a/spec/models/project_repository_storage_move_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ProjectRepositoryStorageMove, type: :model do
- let_it_be_with_refind(:project) { create(:project) }
-
- it_behaves_like 'handles repository moves' do
- let(:container) { project }
- let(:repository_storage_factory_key) { :project_repository_storage_move }
- let(:error_key) { :project }
- let(:repository_storage_worker) { Projects::UpdateRepositoryStorageWorker }
- end
-
- describe 'state transitions' do
- let(:storage) { 'test_second_storage' }
-
- before do
- stub_storage_settings(storage => { 'path' => 'tmp/tests/extra_storage' })
- end
-
- context 'when started' do
- subject(:storage_move) { create(:project_repository_storage_move, :started, container: project, destination_storage_name: storage) }
-
- context 'and transits to replicated' do
- it 'sets the repository storage and marks the container as writable' do
- storage_move.finish_replication!
-
- expect(project.repository_storage).to eq(storage)
- expect(project).not_to be_repository_read_only
- end
- end
- end
- end
-end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 6a0bc714731..ce22fc2b1f0 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -6889,31 +6889,6 @@ RSpec.describe Project, factory_default: :keep do
expect(project.tags.map(&:name)).to match_array(%w[topic1 topic2 topic3])
end
end
-
- context 'intermediate state during background migration' do
- before do
- project.taggings.first.update!(context: 'tags')
- project.instance_variable_set("@tag_list", nil)
- project.reload
- end
-
- it 'tag_list returns string array including old and new topics' do
- expect(project.tag_list).to match_array(%w[topic1 topic2 topic3])
- end
-
- it 'tags returns old and new tag records' do
- expect(project.tags.first.class.name).to eq('ActsAsTaggableOn::Tag')
- expect(project.tags.map(&:name)).to match_array(%w[topic1 topic2 topic3])
- expect(project.taggings.map(&:context)).to match_array(%w[tags topics topics])
- end
-
- it 'update tag_list adds new topics and removes old topics' do
- project.update!(tag_list: 'topic1, topic2, topic3, topic4')
-
- expect(project.tags.map(&:name)).to match_array(%w[topic1 topic2 topic3 topic4])
- expect(project.taggings.map(&:context)).to match_array(%w[topics topics topics topics])
- end
- end
end
def finish_job(export_job)
diff --git a/spec/models/snippet_repository_storage_move_spec.rb b/spec/models/snippet_repository_storage_move_spec.rb
deleted file mode 100644
index f5ad837fb36..00000000000
--- a/spec/models/snippet_repository_storage_move_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SnippetRepositoryStorageMove, type: :model do
- it_behaves_like 'handles repository moves' do
- let_it_be_with_refind(:container) { create(:snippet) }
-
- let(:repository_storage_factory_key) { :snippet_repository_storage_move }
- let(:error_key) { :snippet }
- let(:repository_storage_worker) { Snippets::UpdateRepositoryStorageWorker }
- end
-end
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index 76b77ee0de2..c64f9e8465f 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe MergeRequestPresenter do
context 'when no head pipeline' do
it 'return status using CiService' do
- ci_service = double(MockCiService)
+ ci_service = double(Integrations::MockCi)
ci_status = double
allow(resource.source_project)
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index cfee26a0d6a..bdfeb7a97f0 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -486,7 +486,7 @@ RSpec.shared_examples 'wiki controller actions' do
end.not_to change { wiki.list_pages.size }
expect(response).to render_template('shared/wikis/edit')
- expect(assigns(:error).message).to eq('Could not delete wiki page')
+ expect(assigns(:error)).to eq('Could not delete wiki page')
end
end
end
diff --git a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
deleted file mode 100644
index 256f665c0c4..00000000000
--- a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ProjectScheduleBulkRepositoryShardMovesWorker do
- it_behaves_like 'schedules bulk repository shard moves' do
- let_it_be_with_reload(:container) { create(:project, :repository) }
-
- let(:move_service_klass) { Projects::RepositoryStorageMove }
- let(:worker_klass) { Projects::UpdateRepositoryStorageWorker }
- end
-end
diff --git a/spec/workers/project_update_repository_storage_worker_spec.rb b/spec/workers/project_update_repository_storage_worker_spec.rb
deleted file mode 100644
index 6924e8a93a3..00000000000
--- a/spec/workers/project_update_repository_storage_worker_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ProjectUpdateRepositoryStorageWorker do
- subject { described_class.new }
-
- it_behaves_like 'an update storage move worker' do
- let_it_be_with_refind(:container) { create(:project, :repository) }
- let_it_be(:repository_storage_move) { create(:project_repository_storage_move) }
-
- let(:service_klass) { Projects::UpdateRepositoryStorageService }
- let(:repository_storage_move_klass) { Projects::RepositoryStorageMove }
- end
-end
diff --git a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb
deleted file mode 100644
index a5f1c6b7b3d..00000000000
--- a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SnippetScheduleBulkRepositoryShardMovesWorker do
- it_behaves_like 'schedules bulk repository shard moves' do
- let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } }
-
- let(:move_service_klass) { Snippets::RepositoryStorageMove }
- let(:worker_klass) { Snippets::UpdateRepositoryStorageWorker }
- end
-end
diff --git a/spec/workers/snippet_update_repository_storage_worker_spec.rb b/spec/workers/snippet_update_repository_storage_worker_spec.rb
deleted file mode 100644
index 205cb2e432f..00000000000
--- a/spec/workers/snippet_update_repository_storage_worker_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe SnippetUpdateRepositoryStorageWorker do
- subject { described_class.new }
-
- it_behaves_like 'an update storage move worker' do
- let_it_be_with_refind(:container) { create(:snippet, :repository) }
- let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) }
-
- let(:service_klass) { Snippets::UpdateRepositoryStorageService }
- let(:repository_storage_move_klass) { Snippets::RepositoryStorageMove }
- end
-end