summaryrefslogtreecommitdiff
path: root/app/finders
diff options
context:
space:
mode:
Diffstat (limited to 'app/finders')
-rw-r--r--app/finders/admin/plans_finder.rb24
-rw-r--r--app/finders/boards/boards_finder.rb32
-rw-r--r--app/finders/ci/daily_build_group_report_results_finder.rb103
-rw-r--r--app/finders/ci/testing/daily_build_group_report_results_finder.rb88
-rw-r--r--app/finders/issuable_finder.rb52
-rw-r--r--app/finders/issuable_finder/params.rb27
-rw-r--r--app/finders/issuables/author_filter.rb41
-rw-r--r--app/finders/issuables/base_filter.rb36
-rw-r--r--app/finders/merge_request_target_project_finder.rb11
-rw-r--r--app/finders/merge_requests/oldest_per_commit_finder.rb32
-rw-r--r--app/finders/namespaces/projects_finder.rb64
-rw-r--r--app/finders/packages/maven/package_finder.rb5
-rw-r--r--app/finders/packages/npm/package_finder.rb37
-rw-r--r--app/finders/projects/groups_finder.rb68
-rw-r--r--app/finders/repositories/changelog_commits_finder.rb (renamed from app/finders/repositories/commits_with_trailer_finder.rb)25
-rw-r--r--app/finders/repositories/previous_tag_finder.rb12
-rw-r--r--app/finders/security/license_compliance_jobs_finder.rb2
-rw-r--r--app/finders/template_finder.rb16
-rw-r--r--app/finders/users_finder.rb9
19 files changed, 478 insertions, 206 deletions
diff --git a/app/finders/admin/plans_finder.rb b/app/finders/admin/plans_finder.rb
new file mode 100644
index 00000000000..5ca4b61b25e
--- /dev/null
+++ b/app/finders/admin/plans_finder.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Admin
+ class PlansFinder
+ attr_reader :params
+
+ def initialize(params = {})
+ @params = params
+ end
+
+ def execute
+ plans = Plan.all
+ by_name(plans)
+ end
+
+ private
+
+ def by_name(plans)
+ return plans unless params[:name]
+
+ Plan.find_by(name: params[:name]) # rubocop: disable CodeReuse/ActiveRecord
+ end
+ end
+end
diff --git a/app/finders/boards/boards_finder.rb b/app/finders/boards/boards_finder.rb
new file mode 100644
index 00000000000..5b8c313a178
--- /dev/null
+++ b/app/finders/boards/boards_finder.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Boards
+ class BoardsFinder < Boards::BaseService
+ def execute
+ find_boards
+ end
+
+ private
+
+ def boards
+ parent.boards.order_by_name_asc
+ end
+
+ def first_board
+ parent.boards.first_board
+ end
+
+ def find_boards
+ found =
+ if parent.multiple_issue_boards_available?
+ boards
+ else
+ # When multiple issue boards are not available
+ # a user is only allowed to view the default shown board
+ first_board
+ end
+
+ params[:board_id].present? ? [found.find(params[:board_id])] : found
+ end
+ end
+end
diff --git a/app/finders/ci/daily_build_group_report_results_finder.rb b/app/finders/ci/daily_build_group_report_results_finder.rb
index ef97ccb4c0f..9e736c70dda 100644
--- a/app/finders/ci/daily_build_group_report_results_finder.rb
+++ b/app/finders/ci/daily_build_group_report_results_finder.rb
@@ -1,56 +1,99 @@
# frozen_string_literal: true
+# DailyBuildGroupReportResultsFinder
+#
+# Used to filter DailyBuildGroupReportResults by set of params
+#
+# Arguments:
+# current_user
+# params:
+# project: integer
+# group: integer
+# coverage: boolean
+# ref_path: string
+# start_date: string
+# end_date: string
+# sort: boolean
+# limit: integer
+
module Ci
class DailyBuildGroupReportResultsFinder
include Gitlab::Allowable
- def initialize(current_user:, project:, ref_path: nil, start_date:, end_date:, limit: nil)
+ MAX_ITEMS = 1_000
+ REPORT_WINDOW = 90.days
+ DATE_FORMAT_ALLOWED = '%Y-%m-%d'
+
+ attr_reader :params, :current_user
+
+ def initialize(params: {}, current_user: nil)
+ @params = params
@current_user = current_user
- @project = project
- @ref_path = ref_path
- @start_date = start_date
- @end_date = end_date
- @limit = limit
end
def execute
- return none unless query_allowed?
+ return Ci::DailyBuildGroupReportResult.none unless query_allowed?
- query
+ collection = Ci::DailyBuildGroupReportResult.by_projects(params[:project])
+ collection = filter_report_results(collection)
+ collection
end
- protected
+ private
- attr_reader :current_user, :project, :ref_path, :start_date, :end_date, :limit
+ def query_allowed?
+ can?(current_user, :read_build_report_results, params[:project])
+ end
- def query
- Ci::DailyBuildGroupReportResult.recent_results(
- query_params,
- limit: limit
- )
+ def filter_report_results(collection)
+ collection = by_coverage(collection)
+ collection = by_ref_path(collection)
+ collection = by_dates(collection)
+
+ collection = sort(collection)
+ collection = limit_by(collection)
+ collection
end
- def query_allowed?
- can?(current_user, :read_build_report_results, project)
+ def by_coverage(items)
+ params[:coverage].present? ? items.with_coverage : items
+ end
+
+ def by_ref_path(items)
+ params[:ref_path].present? ? items.by_ref_path(params[:ref_path]) : items.with_default_branch
end
- def query_params
- params = {
- project_id: project,
- date: start_date..end_date
- }
+ def by_dates(items)
+ params[:start_date].present? && params[:end_date].present? ? items.by_dates(start_date, end_date) : items
+ end
- if ref_path.present?
- params[:ref_path] = ref_path
- else
- params[:default_branch] = true
- end
+ def sort(items)
+ params[:sort].present? ? items.ordered_by_date_and_group_name : items
+ end
- params
+ # rubocop: disable CodeReuse/ActiveRecord
+ def limit_by(items)
+ items.limit(limit)
end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def limit
+ return MAX_ITEMS unless params[:limit].present?
- def none
- Ci::DailyBuildGroupReportResult.none
+ [params[:limit].to_i, MAX_ITEMS].min
+ end
+
+ def start_date
+ start_date = Date.strptime(params[:start_date], DATE_FORMAT_ALLOWED) rescue REPORT_WINDOW.ago.to_date
+
+ # The start_date cannot be older than `end_date - 90 days`
+ [start_date, end_date - REPORT_WINDOW].max
+ end
+
+ def end_date
+ Date.strptime(params[:end_date], DATE_FORMAT_ALLOWED) rescue Date.current
end
end
end
+
+Ci::DailyBuildGroupReportResultsFinder.prepend_if_ee('::EE::Ci::DailyBuildGroupReportResultsFinder')
diff --git a/app/finders/ci/testing/daily_build_group_report_results_finder.rb b/app/finders/ci/testing/daily_build_group_report_results_finder.rb
deleted file mode 100644
index 70d9e55dc47..00000000000
--- a/app/finders/ci/testing/daily_build_group_report_results_finder.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-
-# DailyBuildGroupReportResultsFinder
-#
-# Used to filter DailyBuildGroupReportResults by set of params
-#
-# Arguments:
-# current_user
-# params:
-# project: integer
-# group: integer
-# coverage: boolean
-# ref_path: string
-# start_date: date
-# end_date: date
-# sort: boolean
-# limit: integer
-
-module Ci
- module Testing
- class DailyBuildGroupReportResultsFinder
- include Gitlab::Allowable
-
- MAX_ITEMS = 1_000
-
- attr_reader :params, :current_user
-
- def initialize(params: {}, current_user: nil)
- @params = params
- @current_user = current_user
- end
-
- def execute
- return Ci::DailyBuildGroupReportResult.none unless query_allowed?
-
- collection = Ci::DailyBuildGroupReportResult.by_projects(params[:project])
- collection = filter_report_results(collection)
- collection
- end
-
- private
-
- def query_allowed?
- can?(current_user, :read_build_report_results, params[:project])
- end
-
- def filter_report_results(collection)
- collection = by_coverage(collection)
- collection = by_ref_path(collection)
- collection = by_dates(collection)
-
- collection = sort(collection)
- collection = limit_by(collection)
- collection
- end
-
- def by_coverage(items)
- params[:coverage].present? ? items.with_coverage : items
- end
-
- def by_ref_path(items)
- params[:ref_path].present? ? items.by_ref_path(params[:ref_path]) : items.with_default_branch
- end
-
- def by_dates(items)
- params[:start_date].present? && params[:end_date].present? ? items.by_dates(params[:start_date], params[:end_date]) : items
- end
-
- def sort(items)
- params[:sort].present? ? items.ordered_by_date_and_group_name : items
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def limit_by(items)
- items.limit(limit)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def limit
- return MAX_ITEMS unless params[:limit].present?
-
- [params[:limit].to_i, MAX_ITEMS].min
- end
- end
- end
-end
-
-Ci::Testing::DailyBuildGroupReportResultsFinder.prepend_if_ee('::EE::Ci::Testing::DailyBuildGroupReportResultsFinder')
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index fc03d5cd90c..2409dc9d77d 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -47,6 +47,7 @@ class IssuableFinder
NEGATABLE_PARAMS_HELPER_KEYS = %i[project_id scope status include_subgroups].freeze
attr_accessor :current_user, :params
+ attr_reader :original_params
attr_writer :parent
delegate(*%i[assignee milestones], to: :params)
@@ -87,7 +88,7 @@ class IssuableFinder
end
def valid_params
- @valid_params ||= scalar_params + [array_params.merge(not: {})]
+ @valid_params ||= scalar_params + [array_params.merge(or: {}, not: {})]
end
end
@@ -101,6 +102,7 @@ class IssuableFinder
def initialize(current_user, params = {})
@current_user = current_user
+ @original_params = params
@params = params_class.new(params, current_user, klass)
end
@@ -142,7 +144,7 @@ class IssuableFinder
end
def should_filter_negated_args?
- return false unless Feature.enabled?(:not_issuable_queries, params.group || params.project, default_enabled: true)
+ return false unless not_filters_enabled?
# API endpoints send in `nil` values so we test if there are any non-nil
not_params.present? && not_params.values.any?
@@ -150,7 +152,6 @@ class IssuableFinder
# Negates all params found in `negatable_params`
def filter_negated_items(items)
- items = by_negated_author(items)
items = by_negated_assignee(items)
items = by_negated_label(items)
items = by_negated_milestone(items)
@@ -372,31 +373,14 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def by_author(items)
- if params.author
- items.where(author_id: params.author.id)
- elsif params.no_author?
- items.where(author_id: nil)
- elsif params.author_id? || params.author_username? # author not found
- items.none
- else
- items
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- def by_negated_author(items)
- if not_params.author
- items.where.not(author_id: not_params.author.id)
- elsif not_params.author_id? || not_params.author_username? # author not found
- items.none
- else
- items
- end
+ Issuables::AuthorFilter.new(
+ items,
+ params: original_params,
+ or_filters_enabled: or_filters_enabled?,
+ not_filters_enabled: not_filters_enabled?
+ ).filter
end
- # rubocop: enable CodeReuse/ActiveRecord
def by_assignee(items)
if params.filter_by_no_assignee?
@@ -514,4 +498,20 @@ class IssuableFinder
def by_non_archived(items)
params[:non_archived].present? ? items.non_archived : items
end
+
+ def or_filters_enabled?
+ strong_memoize(:or_filters_enabled) do
+ Feature.enabled?(:or_issuable_queries, feature_flag_scope, default_enabled: :yaml)
+ end
+ end
+
+ def not_filters_enabled?
+ strong_memoize(:not_filters_enabled) do
+ Feature.enabled?(:not_issuable_queries, feature_flag_scope, default_enabled: :yaml)
+ end
+ end
+
+ def feature_flag_scope
+ params.group || params.project
+ end
end
diff --git a/app/finders/issuable_finder/params.rb b/app/finders/issuable_finder/params.rb
index 803b30e86ac..a62210ceac5 100644
--- a/app/finders/issuable_finder/params.rb
+++ b/app/finders/issuable_finder/params.rb
@@ -27,19 +27,6 @@ class IssuableFinder
params.present?
end
- def author_id?
- params[:author_id].present? && params[:author_id] != NONE
- end
-
- def author_username?
- params[:author_username].present? && params[:author_username] != NONE
- end
-
- def no_author?
- # author_id takes precedence over author_username
- params[:author_id] == NONE || params[:author_username] == NONE
- end
-
def filter_by_no_assignee?
params[:assignee_id].to_s.downcase == FILTER_NONE
end
@@ -170,20 +157,6 @@ class IssuableFinder
end
# rubocop: disable CodeReuse/ActiveRecord
- def author
- strong_memoize(:author) do
- if author_id?
- User.find_by(id: params[:author_id])
- elsif author_username?
- User.find_by_username(params[:author_username])
- else
- nil
- end
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
def assignees
strong_memoize(:assignees) do
if assignee_id?
diff --git a/app/finders/issuables/author_filter.rb b/app/finders/issuables/author_filter.rb
new file mode 100644
index 00000000000..ce68dbafb95
--- /dev/null
+++ b/app/finders/issuables/author_filter.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Issuables
+ class AuthorFilter < BaseFilter
+ def filter
+ filtered = by_author(issuables)
+ filtered = by_author_union(filtered)
+ by_negated_author(filtered)
+ end
+
+ private
+
+ def by_author(issuables)
+ if params[:author_id].present?
+ issuables.authored(params[:author_id])
+ elsif params[:author_username].present?
+ issuables.authored(User.by_username(params[:author_username]))
+ else
+ issuables
+ end
+ end
+
+ def by_author_union(issuables)
+ return issuables unless or_filters_enabled? && or_params&.fetch(:author_username).present?
+
+ issuables.authored(User.by_username(or_params[:author_username]))
+ end
+
+ def by_negated_author(issuables)
+ return issuables unless not_filters_enabled? && not_params.present?
+
+ if not_params[:author_id].present?
+ issuables.not_authored(not_params[:author_id])
+ elsif not_params[:author_username].present?
+ issuables.not_authored(User.by_username(not_params[:author_username]))
+ else
+ issuables
+ end
+ end
+ end
+end
diff --git a/app/finders/issuables/base_filter.rb b/app/finders/issuables/base_filter.rb
new file mode 100644
index 00000000000..641ae2568cc
--- /dev/null
+++ b/app/finders/issuables/base_filter.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Issuables
+ class BaseFilter
+ attr_reader :issuables, :params
+
+ def initialize(issuables, params:, or_filters_enabled: false, not_filters_enabled: false)
+ @issuables = issuables
+ @params = params
+ @or_filters_enabled = or_filters_enabled
+ @not_filters_enabled = not_filters_enabled
+ end
+
+ def filter
+ raise NotImplementedError
+ end
+
+ private
+
+ def or_params
+ params[:or]
+ end
+
+ def not_params
+ params[:not]
+ end
+
+ def or_filters_enabled?
+ @or_filters_enabled
+ end
+
+ def not_filters_enabled?
+ @not_filters_enabled
+ end
+ end
+end
diff --git a/app/finders/merge_request_target_project_finder.rb b/app/finders/merge_request_target_project_finder.rb
index 85a73e0c6ff..dc9b28ab0a0 100644
--- a/app/finders/merge_request_target_project_finder.rb
+++ b/app/finders/merge_request_target_project_finder.rb
@@ -5,29 +5,30 @@ class MergeRequestTargetProjectFinder
attr_reader :current_user, :source_project
- def initialize(current_user: nil, source_project:)
+ def initialize(current_user: nil, source_project:, project_feature: :merge_requests)
@current_user = current_user
@source_project = source_project
+ @project_feature = project_feature
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute(include_routes: false)
if source_project.fork_network
include_routes ? projects.inc_routes : projects
else
- Project.where(id: source_project)
+ Project.id_in(source_project.id)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
private
+ attr_reader :project_feature
+
def projects
source_project
.fork_network
.projects
.public_or_visible_to_user(current_user)
.non_archived
- .with_feature_available_for_user(:merge_requests, current_user)
+ .with_feature_available_for_user(project_feature, current_user)
end
end
diff --git a/app/finders/merge_requests/oldest_per_commit_finder.rb b/app/finders/merge_requests/oldest_per_commit_finder.rb
index f50db43d7d2..5360f301036 100644
--- a/app/finders/merge_requests/oldest_per_commit_finder.rb
+++ b/app/finders/merge_requests/oldest_per_commit_finder.rb
@@ -15,19 +15,45 @@ module MergeRequests
# Returns a Hash that maps a commit ID to the oldest merge request that
# introduced that commit.
def execute(commits)
+ mapping = {}
+ shas = commits.map(&:id)
+
+ # To include merge requests by the commit SHA, we don't need to go through
+ # any diff rows.
+ #
+ # We can't squeeze all this into a single query, as the diff based data
+ # relies on a GROUP BY. On the other hand, retrieving MRs by their merge
+ # SHAs separately is much easier, and plenty fast.
+ @project
+ .merge_requests
+ .preload_target_project
+ .by_merge_commit_sha(shas)
+ .each do |mr|
+ # Merge SHAs can't be in the merge request itself. It _is_ possible a
+ # newer merge request includes the merge commit, but in that case we
+ # still want the oldest merge request.
+ mapping[mr.merge_commit_sha] = mr
+ end
+
+ remaining = shas - mapping.keys
+
+ return mapping if remaining.empty?
+
id_rows = MergeRequestDiffCommit
- .oldest_merge_request_id_per_commit(@project.id, commits.map(&:id))
+ .oldest_merge_request_id_per_commit(@project.id, remaining)
mrs = MergeRequest
.preload_target_project
.id_in(id_rows.map { |r| r[:merge_request_id] })
.index_by(&:id)
- id_rows.each_with_object({}) do |row, hash|
+ id_rows.each do |row|
if (mr = mrs[row[:merge_request_id]])
- hash[row[:sha]] = mr
+ mapping[row[:sha]] = mr
end
end
+
+ mapping
end
end
end
diff --git a/app/finders/namespaces/projects_finder.rb b/app/finders/namespaces/projects_finder.rb
new file mode 100644
index 00000000000..a6d98015e9d
--- /dev/null
+++ b/app/finders/namespaces/projects_finder.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+# Namespaces::ProjectsFinder
+#
+# Used to filter Projects by set of params
+#
+# Arguments:
+# current_user
+# namespace
+# params:
+# sort: string
+# search: string
+# include_subgroups: boolean
+# ids: int[]
+#
+module Namespaces
+ class ProjectsFinder
+ def initialize(namespace: nil, current_user: nil, params: {})
+ @namespace = namespace
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return Project.none if namespace.nil?
+
+ collection = if params[:include_subgroups].present?
+ namespace.all_projects.with_route
+ else
+ namespace.projects.with_route
+ end
+
+ filter_projects(collection)
+ end
+
+ private
+
+ attr_reader :namespace, :params, :current_user
+
+ def filter_projects(collection)
+ collection = by_ids(collection)
+ collection = by_similarity(collection)
+ collection
+ end
+
+ def by_ids(items)
+ return items unless params[:ids].present?
+
+ items.id_in(params[:ids])
+ end
+
+ def by_similarity(items)
+ return items unless params[:search].present?
+
+ if params[:sort] == :similarity
+ items = items.sorted_by_similarity_desc(params[:search], include_in_select: true)
+ end
+
+ items.merge(Project.search(params[:search]))
+ end
+ end
+end
+
+Namespaces::ProjectsFinder.prepend_if_ee('::EE::Namespaces::ProjectsFinder')
diff --git a/app/finders/packages/maven/package_finder.rb b/app/finders/packages/maven/package_finder.rb
index 7e753705cbd..ba3d4631f55 100644
--- a/app/finders/packages/maven/package_finder.rb
+++ b/app/finders/packages/maven/package_finder.rb
@@ -59,9 +59,8 @@ module Packages
# Returns the projects that the current user can view within a group.
def projects_visible_to_current_user
- ::Project
- .in_namespace(group.self_and_descendants.select(:id))
- .public_or_visible_to_user(current_user)
+ group.all_projects
+ .public_or_visible_to_user(current_user)
end
end
end
diff --git a/app/finders/packages/npm/package_finder.rb b/app/finders/packages/npm/package_finder.rb
index 2854226e178..3b79785d0e1 100644
--- a/app/finders/packages/npm/package_finder.rb
+++ b/app/finders/packages/npm/package_finder.rb
@@ -2,29 +2,40 @@
module Packages
module Npm
class PackageFinder
- attr_reader :project, :package_name
-
delegate :find_by_version, to: :execute
+ delegate :last, to: :execute
- def initialize(project, package_name)
- @project = project
+ def initialize(package_name, project: nil, namespace: nil)
@package_name = package_name
+ @project = project
+ @namespace = namespace
end
def execute
- return Packages::Package.none unless project
-
- packages
+ base.npm
+ .with_name(@package_name)
+ .last_of_each_version
+ .preload_files
end
private
- def packages
- project.packages
- .npm
- .with_name(package_name)
- .last_of_each_version
- .preload_files
+ def base
+ if @project
+ packages_for_project
+ elsif @namespace
+ packages_for_namespace
+ else
+ ::Packages::Package.none
+ end
+ end
+
+ def packages_for_project
+ @project.packages
+ end
+
+ def packages_for_namespace
+ ::Packages::Package.for_projects(@namespace.all_projects)
end
end
end
diff --git a/app/finders/projects/groups_finder.rb b/app/finders/projects/groups_finder.rb
new file mode 100644
index 00000000000..d0c42ad5611
--- /dev/null
+++ b/app/finders/projects/groups_finder.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+# Used to filter ancestor and shared project's Groups by a set of params
+#
+# Arguments:
+# project
+# current_user - which user is requesting groups
+# params:
+# with_shared: boolean (optional)
+# shared_min_access_level: integer (optional)
+# skip_groups: array of integers (optional)
+#
+module Projects
+ class GroupsFinder < UnionFinder
+ def initialize(project:, current_user: nil, params: {})
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return Group.none unless authorized?
+
+ items = all_groups.map do |item|
+ item = exclude_group_ids(item)
+ item
+ end
+
+ find_union(items, Group).with_route.order_id_desc
+ end
+
+ private
+
+ attr_reader :project, :current_user, :params
+
+ def authorized?
+ Ability.allowed?(current_user, :read_project, project)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def all_groups
+ groups = []
+ groups << project.group.self_and_ancestors if project.group
+
+ if params[:with_shared]
+ shared_groups = project.invited_groups
+
+ if params[:shared_min_access_level]
+ shared_groups = shared_groups.where(
+ 'project_group_links.group_access >= ?', params[:shared_min_access_level]
+ )
+ end
+
+ groups << shared_groups
+ end
+
+ groups << Group.none if groups.compact.empty?
+ groups
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def exclude_group_ids(groups)
+ return groups unless params[:skip_groups]
+
+ groups.id_not_in(params[:skip_groups])
+ end
+ end
+end
diff --git a/app/finders/repositories/commits_with_trailer_finder.rb b/app/finders/repositories/changelog_commits_finder.rb
index 4bd643c345b..b80b8e94e59 100644
--- a/app/finders/repositories/commits_with_trailer_finder.rb
+++ b/app/finders/repositories/changelog_commits_finder.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module Repositories
- # Finder for obtaining commits between two refs, with a Git trailer set.
- class CommitsWithTrailerFinder
+ # Finder for getting the commits to include in a changelog.
+ class ChangelogCommitsFinder
# The maximum number of commits to retrieve per page.
#
# This value is arbitrarily chosen. Lowering it means more Gitaly calls, but
@@ -20,6 +20,9 @@ module Repositories
# 5-10 Gitaly calls, while keeping memory usage at a reasonable amount.
COMMITS_PER_PAGE = 1024
+ # The regex to use for extracting the SHA of a reverted commit.
+ REVERT_REGEX = /^This reverts commit (?<sha>[0-9a-f]{40})/i.freeze
+
# The `project` argument specifies the project for which to obtain the
# commits.
#
@@ -44,7 +47,7 @@ module Repositories
#
# Example:
#
- # CommitsWithTrailerFinder.new(...).each_page('Signed-off-by') do |commits|
+ # ChangelogCommitsFinder.new(...).each_page('Changelog') do |commits|
# commits.each do |commit|
# ...
# end
@@ -53,12 +56,22 @@ module Repositories
return to_enum(__method__, trailer) unless block_given?
offset = 0
+ reverted = Set.new
response = fetch_commits
while response.any?
commits = []
response.each do |commit|
+ # If the commit is reverted in the same range (by a newer commit), we
+ # won't include it. This works here because commits are processed in
+ # reverse order (= newer first).
+ next if reverted.include?(commit.id)
+
+ if (sha = revert_commit_sha(commit))
+ reverted << sha
+ end
+
commits.push(commit) if commit.trailers.key?(trailer)
end
@@ -78,5 +91,11 @@ module Repositories
.repository
.commits(range, limit: @per_page, offset: offset, trailers: true)
end
+
+ def revert_commit_sha(commit)
+ matches = commit.description&.match(REVERT_REGEX)
+
+ matches[:sha] if matches
+ end
end
end
diff --git a/app/finders/repositories/previous_tag_finder.rb b/app/finders/repositories/previous_tag_finder.rb
index 150a6332c29..b5e786c30e9 100644
--- a/app/finders/repositories/previous_tag_finder.rb
+++ b/app/finders/repositories/previous_tag_finder.rb
@@ -16,12 +16,13 @@ module Repositories
# This finder expects that all tags to consider meet the following
# requirements:
#
- # * They start with the letter "v"
- # * They use semantic versioning for the tag format
+ # * They start with the letter "v" followed by a version, or immediately start
+ # with a version
+ # * They use semantic versioning for the version format
#
# Tags not meeting these requirements are ignored.
class PreviousTagFinder
- TAG_REGEX = /\Av(?<version>#{Gitlab::Regex.unbounded_semver_regex})\z/.freeze
+ TAG_REGEX = /\Av?(?<version>#{Gitlab::Regex.unbounded_semver_regex})\z/.freeze
def initialize(project)
@project = project
@@ -36,6 +37,11 @@ module Repositories
next unless matches
+ # When using this class for generating changelog data for a range of
+ # commits, we want to compare against the tag of the last _stable_
+ # release; not some random RC that came after that.
+ next if matches[:prerelease]
+
version = matches[:version]
tags[version] = tag
versions << version
diff --git a/app/finders/security/license_compliance_jobs_finder.rb b/app/finders/security/license_compliance_jobs_finder.rb
index 100f94b2cc7..0ec428ae408 100644
--- a/app/finders/security/license_compliance_jobs_finder.rb
+++ b/app/finders/security/license_compliance_jobs_finder.rb
@@ -12,7 +12,7 @@
module Security
class LicenseComplianceJobsFinder < JobsFinder
def self.allowed_job_types
- [:license_management, :license_scanning]
+ [:license_scanning]
end
end
end
diff --git a/app/finders/template_finder.rb b/app/finders/template_finder.rb
index 36f8d144908..739beee236c 100644
--- a/app/finders/template_finder.rb
+++ b/app/finders/template_finder.rb
@@ -22,16 +22,26 @@ class TemplateFinder
end
end
+ # This is temporary and will be removed once we introduce group level inherited templates and
+ # remove the inherited_issuable_templates FF
+ def all_template_names_hash_or_array(project, issuable_type)
+ if project.inherited_issuable_templates_enabled?
+ all_template_names(project, issuable_type.pluralize)
+ else
+ all_template_names_array(project, issuable_type.pluralize)
+ end
+ end
+
def all_template_names(project, type)
return {} if !VENDORED_TEMPLATES.key?(type.to_s) && type.to_s != 'licenses'
build(type, project).template_names
end
- # This is issues and merge requests description templates only.
- # This will be removed once we introduce group level inherited templates
+ # This is for issues and merge requests description templates only.
+ # This will be removed once we introduce group level inherited templates and remove the inherited_issuable_templates FF
def all_template_names_array(project, type)
- all_template_names(project, type).values.flatten.uniq
+ all_template_names(project, type).values.flatten.select { |tmpl| tmpl[:project_id] == project.id }.compact.uniq
end
end
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index 42042406f3f..5ac905e0dd4 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -14,6 +14,7 @@
# active: boolean
# blocked: boolean
# external: boolean
+# non_external: boolean
# without_projects: boolean
# sort: string
# id: integer
@@ -40,6 +41,7 @@ class UsersFinder
users = by_active(users)
users = by_external_identity(users)
users = by_external(users)
+ users = by_non_external(users)
users = by_2fa(users)
users = by_created_at(users)
users = by_without_projects(users)
@@ -97,13 +99,18 @@ class UsersFinder
# rubocop: disable CodeReuse/ActiveRecord
def by_external(users)
- return users = users.where.not(external: true) unless current_user&.admin?
return users unless params[:external]
users.external
end
# rubocop: enable CodeReuse/ActiveRecord
+ def by_non_external(users)
+ return users unless params[:non_external]
+
+ users.non_external
+ end
+
def by_2fa(users)
case params[:two_factor]
when 'enabled'