diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
index 8e5b6a02b49..3569347dd43 100644
--- a/.rubocop_manual_todo.yml
+++ b/.rubocop_manual_todo.yml
@@ -232,8 +232,6 @@ Rails/SaveBang:
- 'spec/initializers/fog_google_https_private_urls_spec.rb'
- 'spec/lib/after_commit_queue_spec.rb'
- 'spec/lib/backup/manager_spec.rb'
- - 'spec/lib/banzai/reference_parser/external_issue_parser_spec.rb'
- - 'spec/lib/banzai/reference_redactor_spec.rb'
- 'spec/lib/gitlab/alerting/alert_spec.rb'
- 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
- 'spec/lib/gitlab/auth/ldap/user_spec.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index f01dedb40dd..f06496d4519 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -640,11 +640,6 @@ Rails/WhereEquals:
Rails/WhereExists:
Enabled: false
-# Offense count: 21
-# Cop supports --auto-correct.
-Rails/WhereNot:
- Enabled: false
-
# Offense count: 8
# Cop supports --auto-correct.
Security/YAMLLoad:
diff --git a/app/finders/ci/pipelines_finder.rb b/app/finders/ci/pipelines_finder.rb
index a77faebb160..e509cf940b8 100644
--- a/app/finders/ci/pipelines_finder.rb
+++ b/app/finders/ci/pipelines_finder.rb
@@ -131,7 +131,7 @@ module Ci
def by_yaml_errors(items)
case Gitlab::Utils.to_boolean(params[:yaml_errors])
when true
- items.where("yaml_errors IS NOT NULL")
+ items.where.not(yaml_errors: nil)
when false
items.where("yaml_errors IS NULL")
else
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index 1bbfdb431de..666286b3016 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -4,29 +4,29 @@ module ServicesHelper
def service_event_description(event)
case event
when "push", "push_events"
- s_("ProjectService|Event will be triggered by a push to the repository")
+ s_("ProjectService|Event triggered when someone pushes to the repository.")
when "tag_push", "tag_push_events"
- s_("ProjectService|Event will be triggered when a new tag is pushed to the repository")
+ s_("ProjectService|Event triggered when a new tag is pushed to the repository.")
when "note", "note_events"
- s_("ProjectService|Event will be triggered when someone adds a comment")
+ s_("ProjectService|Event triggered when someone adds a comment.")
when "confidential_note", "confidential_note_events"
- s_("ProjectService|Event will be triggered when someone adds a comment on a confidential issue")
+ s_("ProjectService|Event triggered when someone adds a comment on a confidential issue.")
when "issue", "issue_events"
- s_("ProjectService|Event will be triggered when an issue is created/updated/closed")
+ s_("ProjectService|Event triggered when an issue is created, updated, or closed.")
when "confidential_issue", "confidential_issue_events"
- s_("ProjectService|Event will be triggered when a confidential issue is created/updated/closed")
+ s_("ProjectService|Event triggered when a confidential issue is created, updated, or closed.")
when "merge_request", "merge_request_events"
- s_("ProjectService|Event will be triggered when a merge request is created/updated/merged")
+ s_("ProjectService|Event triggered when a merge request is created, updated, or merged.")
when "pipeline", "pipeline_events"
- s_("ProjectService|Event will be triggered when a pipeline status changes")
+ s_("ProjectService|Event triggered when a pipeline status changes.")
when "wiki_page", "wiki_page_events"
- s_("ProjectService|Event will be triggered when a wiki page is created/updated")
+ s_("ProjectService|Event triggered when a wiki page is created or updated.")
when "commit", "commit_events"
- s_("ProjectService|Event will be triggered when a commit is created/updated")
+ s_("ProjectService|Event triggered when a commit is created or updated.")
when "deployment"
- s_("ProjectService|Event will be triggered when a deployment starts or finishes")
+ s_("ProjectService|Event triggered when a deployment starts or finishes.")
when "alert"
- s_("ProjectService|Event will be triggered when a new, unique alert is recorded")
+ s_("ProjectService|Event triggered when a new, unique alert is recorded.")
end
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index dce9168a9a4..1f7f5f6babe 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -93,8 +93,7 @@ module Ci
validates :ref, presence: true
scope :not_interruptible, -> do
- joins(:metadata).where('ci_builds_metadata.id NOT IN (?)',
- Ci::BuildMetadata.scoped_build.with_interruptible.select(:id))
+ joins(:metadata).where.not('ci_builds_metadata.id' => Ci::BuildMetadata.scoped_build.with_interruptible.select(:id))
end
scope :unstarted, -> { where(runner_id: nil) }
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index fe6889a6808..9dd75150ac7 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -44,7 +44,7 @@ module Ci
next if position.present?
self.position = statuses.select(:stage_idx)
- .where('stage_idx IS NOT NULL')
+ .where.not(stage_idx: nil)
.group(:stage_idx)
.order('COUNT(*) DESC')
.first&.stage_idx.to_i
diff --git a/app/models/clusters/clusters_hierarchy.rb b/app/models/clusters/clusters_hierarchy.rb
index c9c18d8c96a..125783e6ee1 100644
--- a/app/models/clusters/clusters_hierarchy.rb
+++ b/app/models/clusters/clusters_hierarchy.rb
@@ -16,7 +16,7 @@ module Clusters
model
.unscoped
- .where('clusters.id IS NOT NULL')
+ .where.not('clusters.id' => nil)
.with
.recursive(cte.to_arel)
.from(cte_alias)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index e64380f5d91..fe262d48ac4 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -56,6 +56,7 @@ class CommitStatus < ApplicationRecord
scope :by_name, -> (name) { where(name: name) }
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
scope :eager_load_pipeline, -> { eager_load(:pipeline, project: { namespace: :route }) }
+ scope :with_pipeline, -> { joins(:pipeline) }
scope :for_project_paths, -> (paths) do
where(project: Project.where_full_path_in(Array(paths)))
@@ -180,6 +181,7 @@ class CommitStatus < ApplicationRecord
end
after_transition any => :failed do |commit_status|
+ next if Feature.enabled?(:async_add_build_failure_todo, commit_status.project, default_enabled: :yaml)
next unless commit_status.project
# rubocop: disable CodeReuse/ServiceClass
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 96b44c9ac0a..4cc65f4e295 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -86,7 +86,7 @@ class Environment < ApplicationRecord
end
scope :for_project, -> (project) { where(project_id: project) }
- scope :for_tier, -> (tier) { where(tier: tier).where('tier IS NOT NULL') }
+ scope :for_tier, -> (tier) { where(tier: tier).where.not(tier: nil) }
scope :with_deployment, -> (sha) { where('EXISTS (?)', Deployment.select(1).where('deployments.environment_id = environments.id').where(sha: sha)) }
scope :unfoldered, -> { where(environment_type: nil) }
scope :with_rank, -> do
diff --git a/app/models/project.rb b/app/models/project.rb
index eb0382414de..2431b40a8be 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -519,7 +519,7 @@ class Project < ApplicationRecord
scope :with_packages, -> { joins(:packages) }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
- scope :joined, ->(user) { where('namespace_id != ?', user.namespace_id) }
+ scope :joined, ->(user) { where.not(namespace_id: user.namespace_id) }
scope :starred_by, ->(user) { joins(:users_star_projects).where('users_star_projects.user_id': user.id) }
scope :visible_to_user, ->(user) { where(id: user.authorized_projects.select(:id).reorder(nil)) }
scope :visible_to_user_and_access_level, ->(user, access_level) { where(id: user.authorized_projects.where('project_authorizations.access_level >= ?', access_level).select(:id).reorder(nil)) }
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
index e8e12a9a206..803c1255195 100644
--- a/app/models/project_services/microsoft_teams_service.rb
+++ b/app/models/project_services/microsoft_teams_service.rb
@@ -2,7 +2,7 @@
class MicrosoftTeamsService < ChatNotificationService
def title
- 'Microsoft Teams Notification'
+ 'Microsoft Teams notifications'
end
def description
@@ -14,13 +14,7 @@ class MicrosoftTeamsService < ChatNotificationService
end
def help
- 'This service sends notifications about projects events to Microsoft Teams channels.
- To set up this service:
-
Use this service to send notifications about events in GitLab projects to your Microsoft Teams channels. How do I configure this integration?
' end def webhook_placeholder @@ -40,8 +34,8 @@ class MicrosoftTeamsService < ChatNotificationService def default_fields [ - { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + { type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}" }, + { type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'If selected, successful pipelines do not trigger a notification event.' }, { type: 'select', name: 'branches_to_be_notified', choices: branch_choices } ] end diff --git a/app/models/user.rb b/app/models/user.rb index decd1117c6c..de7bb1ccf49 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -353,12 +353,7 @@ class User < ApplicationRecord # this state transition object in order to do a rollback. # For this reason the tradeoff is to disable this cop. after_transition any => :blocked do |user| - if Feature.enabled?(:abort_user_pipelines_on_block, user) - Ci::AbortPipelinesService.new.execute(user.pipelines) - else - Ci::CancelUserPipelinesService.new.execute(user) - end - + Ci::AbortPipelinesService.new.execute(user.pipelines) Ci::DisableUserPipelineSchedulesService.new.execute(user) end # rubocop: enable CodeReuse/ServiceClass @@ -1041,7 +1036,7 @@ class User < ApplicationRecord [ Project.where(namespace: namespace), Project.joins(:project_authorizations) - .where("projects.namespace_id <> ?", namespace.id) + .where.not('projects.namespace_id' => namespace.id) .where(project_authorizations: { user_id: id, access_level: Gitlab::Access::OWNER }) ], remove_duplicates: false diff --git a/app/services/ci/cancel_user_pipelines_service.rb b/app/services/ci/cancel_user_pipelines_service.rb deleted file mode 100644 index 3d3a8032e8e..00000000000 --- a/app/services/ci/cancel_user_pipelines_service.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true - -module Ci - class CancelUserPipelinesService - # rubocop: disable CodeReuse/ActiveRecord - # This is a bug with CodeReuse/ActiveRecord cop - # https://gitlab.com/gitlab-org/gitlab/issues/32332 - def execute(user) - # TODO: fix N+1 queries https://gitlab.com/gitlab-org/gitlab/-/issues/300685 - user.pipelines.cancelable.find_each(&:cancel_running) - - ServiceResponse.success(message: 'Pipeline canceled') - rescue ActiveRecord::StaleObjectError - ServiceResponse.error(message: 'Error canceling pipeline') - end - # rubocop: enable CodeReuse/ActiveRecord - end -end diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb index 9355b82b598..3d58f3d9e9a 100644 --- a/app/services/ci/retry_build_service.rb +++ b/app/services/ci/retry_build_service.rb @@ -21,7 +21,7 @@ module Ci Gitlab::OptimisticLocking.retry_lock(new_build, name: 'retry_build', &:enqueue) - MergeRequests::AddTodoWhenBuildFailsService + ::MergeRequests::AddTodoWhenBuildFailsService .new(project, current_user) .close(new_build) end diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb index 90ee7b9b3ba..bb8590a769c 100644 --- a/app/services/ci/retry_pipeline_service.rb +++ b/app/services/ci/retry_pipeline_service.rb @@ -28,7 +28,7 @@ module Ci pipeline.reset_ancestor_bridges! - MergeRequests::AddTodoWhenBuildFailsService + ::MergeRequests::AddTodoWhenBuildFailsService .new(project, current_user) .close_all(pipeline) diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb index 317cd11a69d..4cbb6b77c50 100644 --- a/app/services/merge_requests/base_service.rb +++ b/app/services/merge_requests/base_service.rb @@ -164,7 +164,7 @@ module MergeRequests def pipeline_merge_requests(pipeline) pipeline.all_merge_requests.opened.each do |merge_request| - next unless pipeline == merge_request.head_pipeline + next unless pipeline.id == merge_request.head_pipeline_id yield merge_request end diff --git a/app/services/namespaces/in_product_marketing_emails_service.rb b/app/services/namespaces/in_product_marketing_emails_service.rb index aa29c8574ad..2b3c0c382a8 100644 --- a/app/services/namespaces/in_product_marketing_emails_service.rb +++ b/app/services/namespaces/in_product_marketing_emails_service.rb @@ -27,7 +27,7 @@ module Namespaces end def execute - raise NotImplementedError, "Track #{track} not defined" unless TRACKS.key?(track) + raise ArgumentError, "Track #{track} not defined" unless TRACKS.key?(track) groups_for_track.each_batch do |groups| groups.each do |group| diff --git a/app/services/todos/destroy/base_service.rb b/app/services/todos/destroy/base_service.rb index 7378f10e7c4..4e971246185 100644 --- a/app/services/todos/destroy/base_service.rb +++ b/app/services/todos/destroy/base_service.rb @@ -13,7 +13,7 @@ module Todos # rubocop: disable CodeReuse/ActiveRecord def without_authorized(items) - items.where('todos.user_id NOT IN (?)', authorized_users) + items.where.not('todos.user_id' => authorized_users) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/services/todos/destroy/private_features_service.rb b/app/services/todos/destroy/private_features_service.rb index bd49519d694..44c3ff231f8 100644 --- a/app/services/todos/destroy/private_features_service.rb +++ b/app/services/todos/destroy/private_features_service.rb @@ -36,7 +36,7 @@ module Todos items = Todo.where(project_id: project_id) items = items.where(user_id: user_id) if user_id - items.where('user_id NOT IN (?)', authorized_users) + items.where.not(user_id: authorized_users) .where(target_type: target_types) .delete_all end diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 921def1eef8..a542c8e179d 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -1235,6 +1235,14 @@ :weight: 3 :idempotent: :tags: [] +- :name: pipeline_default:ci_merge_requests_add_todo_when_build_fails + :feature_category: :continuous_integration + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 3 + :idempotent: true + :tags: [] - :name: pipeline_default:ci_pipeline_bridge_status :feature_category: :continuous_integration :has_external_dependencies: diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb index 3f99b30fdf7..c9cfb1da10b 100644 --- a/app/workers/build_finished_worker.rb +++ b/app/workers/build_finished_worker.rb @@ -37,6 +37,10 @@ class BuildFinishedWorker # rubocop:disable Scalability/IdempotentWorker ExpirePipelineCacheWorker.perform_async(build.pipeline_id) ChatNotificationWorker.perform_async(build.id) if build.pipeline.chat? + if build.failed? && Feature.enabled?(:async_add_build_failure_todo, build.project, default_enabled: :yaml) + ::Ci::MergeRequests::AddTodoWhenBuildFailsWorker.perform_async(build.id) + end + ## # We want to delay sending a build trace to object storage operation to # validate that this fixes a race condition between this and flushing live diff --git a/app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb b/app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb new file mode 100644 index 00000000000..d5e097dc2b5 --- /dev/null +++ b/app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true +module Ci + module MergeRequests + class AddTodoWhenBuildFailsWorker + include ApplicationWorker + include PipelineQueue + + urgency :low + idempotent! + + def perform(job_id) + job = ::CommitStatus.with_pipeline.find_by_id(job_id) + project = job&.project + + return unless job && project + + ::MergeRequests::AddTodoWhenBuildFailsService.new(job.project, nil).execute(job) + end + end + end +end diff --git a/changelogs/unreleased/324045-remove-feature-flag.yml b/changelogs/unreleased/324045-remove-feature-flag.yml new file mode 100644 index 00000000000..838d1923556 --- /dev/null +++ b/changelogs/unreleased/324045-remove-feature-flag.yml @@ -0,0 +1,5 @@ +--- +title: Bulk-abort user pipelines on block +merge_request: 57801 +author: +type: performance diff --git a/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml b/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml new file mode 100644 index 00000000000..fc438b5cc6b --- /dev/null +++ b/changelogs/unreleased/325509-set-namespaces-traversal_ids-for-production-gitlab-org-group.yml @@ -0,0 +1,5 @@ +--- +title: Backfill traversal_ids for gitlab-org .com +merge_request: 57075 +author: +type: performance diff --git a/changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml b/changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml new file mode 100644 index 00000000000..f3715817ea0 --- /dev/null +++ b/changelogs/unreleased/issue-220040-fix-rails-savebang-banzai-module.yml @@ -0,0 +1,5 @@ +--- +title: Fix Rails/SaveBang Rubocop offenses for banzai modules +merge_request: 58108 +author: Huzaifa Iftikhar @huzaifaiftikhar +type: fixed diff --git a/changelogs/unreleased/pl-rubocop-todo-where-not.yml b/changelogs/unreleased/pl-rubocop-todo-where-not.yml new file mode 100644 index 00000000000..da8c041ec10 --- /dev/null +++ b/changelogs/unreleased/pl-rubocop-todo-where-not.yml @@ -0,0 +1,5 @@ +--- +title: Resolves rubocop offenses Rails/WhereNot +merge_request: 58062 +author: Shubham Kumar (@imskr) +type: fixed diff --git a/config/feature_flags/development/abort_user_pipelines_on_block.yml b/config/feature_flags/development/async_add_build_failure_todo.yml similarity index 59% rename from config/feature_flags/development/abort_user_pipelines_on_block.yml rename to config/feature_flags/development/async_add_build_failure_todo.yml index b0e4fb30fc2..6bb1a84ed82 100644 --- a/config/feature_flags/development/abort_user_pipelines_on_block.yml +++ b/config/feature_flags/development/async_add_build_failure_todo.yml @@ -1,8 +1,8 @@ --- -name: abort_user_pipelines_on_block -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56126 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324045 -milestone: '13.10' +name: async_add_build_failure_todo +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57490/diffs +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326726 +milestone: '13.11' type: development -group: group::memory +group: group::continuous integration default_enabled: false diff --git a/config/metrics/schema.json b/config/metrics/schema.json index 4e5d4162a05..8878b3bc744 100644 --- a/config/metrics/schema.json +++ b/config/metrics/schema.json @@ -5,6 +5,10 @@ "key_path": { "type": "string" }, + "name": { + "type": ["string", "null"], + "pattern": "^([a-z]+_)*[a-z]+$" + }, "description": { "type": "string" }, diff --git a/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb b/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb index 76b00796d1a..ab217ba92ab 100644 --- a/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb +++ b/db/post_migrate/20200406102120_backfill_deployment_clusters_from_deployments.rb @@ -17,7 +17,7 @@ class BackfillDeploymentClustersFromDeployments < ActiveRecord::Migration[6.0] class Deployment < ActiveRecord::Base include EachBatch - default_scope { where('cluster_id IS NOT NULL') } # rubocop:disable Cop/DefaultScope + default_scope { where.not(cluster_id: nil) } # rubocop:disable Cop/DefaultScope self.table_name = 'deployments' end diff --git a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb index 891201eaa52..031d9ea49e2 100644 --- a/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb +++ b/db/post_migrate/20200811130433_create_missing_vulnerabilities_issue_links.rb @@ -18,11 +18,11 @@ class CreateMissingVulnerabilitiesIssueLinks < ActiveRecord::Migration[6.0] disable_ddl_transaction! def up - VulnerabilitiesFeedback.where('issue_id IS NOT NULL').each_batch do |relation| + VulnerabilitiesFeedback.where.not(issue_id: nil).each_batch do |relation| timestamp = Time.now issue_links = relation .joins("JOIN vulnerability_occurrences vo ON vo.project_id = vulnerability_feedback.project_id AND vo.report_type = vulnerability_feedback.category AND encode(vo.project_fingerprint, 'hex') = vulnerability_feedback.project_fingerprint") - .where('vo.vulnerability_id IS NOT NULL') + .where.not('vo.vulnerability_id' => nil) .pluck(:vulnerability_id, :issue_id) .map do |v_id, i_id| { diff --git a/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb b/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb new file mode 100644 index 00000000000..8cef1f1cc2b --- /dev/null +++ b/db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +class SetTraversalIdsForGitlabOrgGroupCom < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + return unless Gitlab.com? + + # namespace ID 9970 is gitlab-org on .com + with_lock_retries do + execute(<<~SQL) + UPDATE + namespaces + SET + traversal_ids = cte.traversal_ids + FROM + ( + WITH RECURSIVE cte(id, traversal_ids, cycle) AS ( + VALUES + (9970, ARRAY[9970], false) + UNION ALL + SELECT + n.id, + cte.traversal_ids || n.id, + n.id = ANY(cte.traversal_ids) + FROM + namespaces n, + cte + WHERE + n.parent_id = cte.id + AND NOT cycle + ) + SELECT + id, + traversal_ids + FROM + cte FOR + UPDATE + ) as cte + WHERE + namespaces.id = cte.id + AND namespaces.traversal_ids <> cte.traversal_ids + SQL + end + end + + def down + return unless Gitlab.com? + + # namespace ID 9970 is gitlab-org on .com + with_lock_retries do + execute(<<~SQL) + UPDATE + namespaces + SET + traversal_ids = '{}' + FROM + ( + WITH RECURSIVE cte(id, traversal_ids, cycle) AS ( + VALUES + (9970, ARRAY[9970], false) + UNION ALL + SELECT + n.id, + cte.traversal_ids || n.id, + n.id = ANY(cte.traversal_ids) + FROM + namespaces n, + cte + WHERE + n.parent_id = cte.id + AND NOT cycle + ) + SELECT + id, + traversal_ids + FROM + cte FOR + UPDATE + ) as cte + WHERE + namespaces.id = cte.id + SQL + end + end +end diff --git a/db/schema_migrations/20210311045139 b/db/schema_migrations/20210311045139 new file mode 100644 index 00000000000..71026c1b2af --- /dev/null +++ b/db/schema_migrations/20210311045139 @@ -0,0 +1 @@ +2387c8a5516aaf8bcf44c9bad45bfc9844d68d2c03330f67773ce046b21a7a6c \ No newline at end of file diff --git a/doc/user/project/integrations/img/microsoft_teams_configuration.png b/doc/user/project/integrations/img/microsoft_teams_configuration.png deleted file mode 100644 index 22ad28e3f73..00000000000 Binary files a/doc/user/project/integrations/img/microsoft_teams_configuration.png and /dev/null differ diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md index 41e0938fc3b..795ead573f2 100644 --- a/doc/user/project/integrations/microsoft_teams.md +++ b/doc/user/project/integrations/microsoft_teams.md @@ -6,49 +6,55 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Microsoft Teams service **(FREE)** -## On Microsoft Teams +You can integrate Microsoft Teams with GitLab, and display notifications about GitLab projects +in Microsoft Teams. To integrate the services, you must: -To enable Microsoft Teams integration you must create an incoming webhook integration on Microsoft -Teams by following the steps below: +1. [Configure Microsoft Teams](#configure-microsoft-teams) to enable a webhook + to listen for changes. +1. [Configure your GitLab project](#configure-your-gitlab-project) to push notifications + to the Microsoft Teams webhook. -1. Search for "incoming webhook" on the search bar in Microsoft Teams and select the - **Incoming Webhook** item. +## Configure Microsoft Teams + +To configure Microsoft Teams to listen for notifications from GitLab: + +1. In Microsoft Teams, search for "incoming webhook" in the search bar, and select the + **Incoming Webhook** item: ![Select Incoming Webhook](img/microsoft_teams_select_incoming_webhook.png) -1. Click the **Add to a team** button. +1. Select **Add to a team**. 1. Select the team and channel you want to add the integration to. 1. Add a name for the webhook. The name is displayed next to every message that comes in through the webhook. -1. Copy the webhook URL for the next steps. +1. Copy the webhook URL, as you need it to configure GitLab. -Learn more about -[setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook). +## Configure your GitLab project -## On GitLab +After you configure Microsoft Teams to receive notifications, you must configure +GitLab to send the notifications: -After you set up Microsoft Teams, it's time to set up GitLab. +1. Sign in to GitLab as a user with [Administrator](../../permissions.md) and go + to your project's page. +1. Go to **Settings > Integrations** and select **Microsoft Teams Notification**. +1. Select **Active** to enable the integration. +1. Select the check box next to each **Trigger** to enable: + - Push + - Issue + - Confidential issue + - Merge request + - Note + - Confidential note + - Tag push + - Pipeline - If you enable this trigger, you can also select **Notify only broken pipelines** to be notified only about failed pipelines. + - Wiki page +1. In **Webhook**, paste the URL you copied when you + [configured Microsoft Teams](#configure-microsoft-teams). +1. (Optional) If you enabled the pipeline trigger, you can select the + **Notify only broken pipelines** check box to push notifications only when pipelines break. +1. Select the branches you want to send notifications for. +1. Click **Save changes**. -Navigate to the [Integrations page](overview.md#accessing-integrations) -and select the **Microsoft Teams Notification** service to configure it. -There, you see a checkbox with the following events that can be triggered: +## Resources -- Push -- Issue -- Confidential issue -- Merge request -- Note -- Tag push -- Pipeline -- Wiki page - -At the end fill in your Microsoft Teams details: - -| Field | Description | -| ----- | ----------- | -| **Webhook** | The incoming webhook URL which you have to set up on Microsoft Teams. | -| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. | - -After you are all done, click **Save changes** for the changes to take effect. - -![Microsoft Teams configuration](img/microsoft_teams_configuration.png) +- [Setting up an incoming webhook on Microsoft Teams](https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/connectors-using#setting-up-a-custom-incoming-webhook). diff --git a/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb b/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb index eb4bc0aaf28..28cc4a5e3fa 100644 --- a/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb +++ b/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb @@ -11,7 +11,7 @@ module Gitlab MergeRequest .where(merge_request_assignees_not_exists_clause) .where(id: from_id..to_id) - .where('assignee_id IS NOT NULL') + .where.not(assignee_id: nil) .select(:id, :assignee_id) .to_sql diff --git a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb b/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb index 5b01141d8c1..665ad7abcbb 100644 --- a/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb +++ b/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer.rb @@ -27,7 +27,7 @@ module Gitlab joins(:user) .merge(UserModel.active) .where(id: (start_id..stop_id)) - .where('emails.confirmed_at IS NOT NULL') + .where.not('emails.confirmed_at' => nil) .where('emails.confirmed_at = users.confirmed_at') .where('emails.email <> users.email') .where('NOT EXISTS (SELECT 1 FROM user_synced_attributes_metadata WHERE user_id=users.id AND email_synced IS true)') diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb index 428bcbe8dc5..2f15cdd7506 100644 --- a/lib/gitlab/import_export/uploads_manager.rb +++ b/lib/gitlab/import_export/uploads_manager.rb @@ -76,7 +76,7 @@ module Gitlab def project_uploads_except_avatar(avatar_path) return @project.uploads unless avatar_path - @project.uploads.where("path != ?", avatar_path) + @project.uploads.where.not(path: avatar_path) end def download_and_copy(upload) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d4e0b68f6e5..01c1699bc4a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -24110,40 +24110,40 @@ msgstr "" msgid "ProjectService|Enter new password" msgstr "" -msgid "ProjectService|Event will be triggered by a push to the repository" +msgid "ProjectService|Event triggered when a commit is created or updated." msgstr "" -msgid "ProjectService|Event will be triggered when a commit is created/updated" +msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed." msgstr "" -msgid "ProjectService|Event will be triggered when a confidential issue is created/updated/closed" +msgid "ProjectService|Event triggered when a deployment starts or finishes." msgstr "" -msgid "ProjectService|Event will be triggered when a deployment starts or finishes" +msgid "ProjectService|Event triggered when a merge request is created, updated, or merged." msgstr "" -msgid "ProjectService|Event will be triggered when a merge request is created/updated/merged" +msgid "ProjectService|Event triggered when a new tag is pushed to the repository." msgstr "" -msgid "ProjectService|Event will be triggered when a new tag is pushed to the repository" +msgid "ProjectService|Event triggered when a new, unique alert is recorded." msgstr "" -msgid "ProjectService|Event will be triggered when a new, unique alert is recorded" +msgid "ProjectService|Event triggered when a pipeline status changes." msgstr "" -msgid "ProjectService|Event will be triggered when a pipeline status changes" +msgid "ProjectService|Event triggered when a wiki page is created or updated." msgstr "" -msgid "ProjectService|Event will be triggered when a wiki page is created/updated" +msgid "ProjectService|Event triggered when an issue is created, updated, or closed." msgstr "" -msgid "ProjectService|Event will be triggered when an issue is created/updated/closed" +msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue." msgstr "" -msgid "ProjectService|Event will be triggered when someone adds a comment" +msgid "ProjectService|Event triggered when someone adds a comment." msgstr "" -msgid "ProjectService|Event will be triggered when someone adds a comment on a confidential issue" +msgid "ProjectService|Event triggered when someone pushes to the repository." msgstr "" msgid "ProjectService|Issue URL" diff --git a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb index 5f92eb42e74..0c1b98e5ec3 100644 --- a/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb +++ b/spec/lib/banzai/reference_parser/external_issue_parser_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Banzai::ReferenceParser::ExternalIssueParser do levels.each do |level| it "creates reference when the feature is #{level}" do - project.project_feature.update(issues_access_level: level) + project.project_feature.update!(issues_access_level: level) visible_nodes = subject.nodes_visible_to_user(user, [link]) diff --git a/spec/lib/banzai/reference_redactor_spec.rb b/spec/lib/banzai/reference_redactor_spec.rb index 668e427cfa2..78cceedd0e5 100644 --- a/spec/lib/banzai/reference_redactor_spec.rb +++ b/spec/lib/banzai/reference_redactor_spec.rb @@ -64,7 +64,7 @@ RSpec.describe Banzai::ReferenceRedactor do let(:redactor) { described_class.new(Banzai::RenderContext.new(project, user)) } before do - project.update(pending_delete: true) + project.update!(pending_delete: true) end it 'redacts an issue attached' do diff --git a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb index 52e9f2d9846..b6f9c8106c9 100644 --- a/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb +++ b/spec/lib/gitlab/analytics/cycle_analytics/stage_events/code_stage_start_spec.rb @@ -15,7 +15,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::StageEvents::CodeStageStart do other_merge_request = create(:merge_request, source_project: project, source_branch: 'a', target_branch: 'master') - records = subject.apply_query_customization(MergeRequest.all).where('merge_requests_closing_issues.issue_id IS NOT NULL') + records = subject.apply_query_customization(MergeRequest.all).where.not('merge_requests_closing_issues.issue_id' => nil) expect(records).to eq([merge_request]) expect(records).not_to include(other_merge_request) end diff --git a/spec/lib/gitlab/usage/metric_definition_spec.rb b/spec/lib/gitlab/usage/metric_definition_spec.rb index 8b592838f5d..f98cc4cbcb7 100644 --- a/spec/lib/gitlab/usage/metric_definition_spec.rb +++ b/spec/lib/gitlab/usage/metric_definition_spec.rb @@ -16,7 +16,8 @@ RSpec.describe Gitlab::Usage::MetricDefinition do time_frame: 'none', data_source: 'database', distribution: %w(ee ce), - tier: %w(free starter premium ultimate bronze silver gold) + tier: %w(free starter premium ultimate bronze silver gold), + name: 'count_boards' } end @@ -53,6 +54,7 @@ RSpec.describe Gitlab::Usage::MetricDefinition do :distribution | nil :distribution | 'test' :tier | %w(test ee) + :name | 'count_