Commit fedf978f authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent db24ab2b
......@@ -98,7 +98,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
}
end
if Gitlab::CurrentSettings.instance_administration_project_id.present?
if Gitlab::CurrentSettings.self_monitoring_project_id.present?
return render status: :ok, json: self_monitoring_data
elsif SelfMonitoringProjectCreateWorker.in_progress?(job_id)
......@@ -134,7 +134,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
}
end
if Gitlab::CurrentSettings.instance_administration_project_id.nil?
if Gitlab::CurrentSettings.self_monitoring_project_id.nil?
return render status: :ok, json: {
message: _('Self-monitoring project has been successfully deleted')
}
......@@ -161,8 +161,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def self_monitoring_data
{
project_id: Gitlab::CurrentSettings.instance_administration_project_id,
project_full_path: Gitlab::CurrentSettings.instance_administration_project&.full_path
project_id: Gitlab::CurrentSettings.self_monitoring_project_id,
project_full_path: Gitlab::CurrentSettings.self_monitoring_project&.full_path
}
end
......@@ -171,7 +171,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
status: :not_implemented,
json: {
message: _('Self-monitoring is not enabled on this GitLab server, contact your administrator.'),
documentation_url: help_page_path('administration/monitoring/gitlab_instance_administration_project/index')
documentation_url: help_page_path('administration/monitoring/gitlab_self_monitoring_project/index')
}
)
end
......
......@@ -314,18 +314,21 @@ class IssuableFinder
params[:assignee_username].present?
end
# rubocop: disable CodeReuse/ActiveRecord
def assignee
return @assignee if defined?(@assignee)
assignees.first
end
@assignee =
# rubocop: disable CodeReuse/ActiveRecord
def assignees
strong_memoize(:assignees) do
if assignee_id?
User.find_by(id: params[:assignee_id])
User.where(id: params[:assignee_id])
elsif assignee_username?
User.find_by_username(params[:assignee_username])
User.where(username: params[:assignee_username])
else
nil
User.none
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
......@@ -415,7 +418,7 @@ class IssuableFinder
# These are "helper" params that are required inside the NOT to get the right results. They usually come in
# at the top-level params, but if they do come in inside the `:not` params, they should take precedence.
not_helpers = params.slice(*NEGATABLE_PARAMS_HELPER_KEYS).merge(params[:not].slice(*NEGATABLE_PARAMS_HELPER_KEYS))
not_param = { key => value }.with_indifferent_access.merge(not_helpers)
not_param = { key => value }.with_indifferent_access.merge(not_helpers).merge(not_query: true)
items_to_negate = self.class.new(current_user, not_param).execute
......@@ -543,6 +546,8 @@ class IssuableFinder
# rubocop: enable CodeReuse/ActiveRecord
def by_assignee(items)
return items.assigned_to(assignees) if not_query? && assignees.any?
if filter_by_no_assignee?
items.unassigned
elsif filter_by_any_assignee?
......@@ -624,7 +629,7 @@ class IssuableFinder
elsif filter_by_any_label?
items.any_label
else
items.with_label(label_names, params[:sort])
items.with_label(label_names, params[:sort], not_query: not_query?)
end
items
......@@ -673,4 +678,8 @@ class IssuableFinder
def min_access_level
ProjectFeature.required_minimum_access_level(klass)
end
def not_query?
!!params[:not_query]
end
end
......@@ -351,10 +351,10 @@ module ApplicationSettingsHelper
status_delete_self_monitoring_project_admin_application_settings_path,
'self_monitoring_project_exists' =>
Gitlab::CurrentSettings.instance_administration_project.present?.to_s,
Gitlab::CurrentSettings.self_monitoring_project.present?.to_s,
'self_monitoring_project_full_path' =>
Gitlab::CurrentSettings.instance_administration_project&.full_path
Gitlab::CurrentSettings.self_monitoring_project&.full_path
}
end
end
......
......@@ -10,7 +10,9 @@ class ApplicationSetting < ApplicationRecord
add_authentication_token_field :health_check_access_token
add_authentication_token_field :static_objects_external_storage_auth_token
belongs_to :instance_administration_project, class_name: "Project"
belongs_to :self_monitoring_project, class_name: "Project", foreign_key: 'instance_administration_project_id'
alias_attribute :self_monitoring_project_id, :instance_administration_project_id
belongs_to :instance_administrators_group, class_name: "Group"
# Include here so it can override methods from
......
......@@ -11,7 +11,7 @@ module Clusters
self.table_name = 'clusters_applications_knative'
has_one :serverless_domain_cluster, class_name: 'Serverless::DomainCluster', foreign_key: 'clusters_applications_knative_id', inverse_of: :knative
has_one :serverless_domain_cluster, class_name: '::Serverless::DomainCluster', foreign_key: 'clusters_applications_knative_id', inverse_of: :knative
include ::Clusters::Concerns::ApplicationCore
include ::Clusters::Concerns::ApplicationStatus
......
......@@ -108,7 +108,9 @@ module Issuable
where("NOT EXISTS (SELECT TRUE FROM #{to_ability_name}_assignees WHERE #{to_ability_name}_id = #{to_ability_name}s.id)")
end
scope :assigned_to, ->(u) do
where("EXISTS (SELECT TRUE FROM #{to_ability_name}_assignees WHERE user_id = ? AND #{to_ability_name}_id = #{to_ability_name}s.id)", u.id)
assignees_table = Arel::Table.new("#{to_ability_name}_assignees")
sql = assignees_table.project('true').where(assignees_table[:user_id].in(u)).where(Arel::Nodes::SqlLiteral.new("#{to_ability_name}_id = #{to_ability_name}s.id"))
where("EXISTS (#{sql.to_sql})")
end
# rubocop:enable GitlabSecurity/SqlInjection
......@@ -263,8 +265,9 @@ module Issuable
.reorder(Gitlab::Database.nulls_last_order('highest_priority', direction))
end
def with_label(title, sort = nil)
if title.is_a?(Array) && title.size > 1
def with_label(title, sort = nil, not_query: false)
multiple_labels = title.is_a?(Array) && title.size > 1
if multiple_labels && !not_query
joins(:labels).where(labels: { title: title }).group(*grouping_columns(sort)).having("COUNT(DISTINCT labels.title) = #{title.size}")
else
joins(:labels).where(labels: { title: title })
......
......@@ -102,7 +102,7 @@ class PrometheusService < MonitoringService
private
def self_monitoring_project?
project && project.id == current_settings.instance_administration_project_id
project && project.id == current_settings.self_monitoring_project_id
end
def internal_prometheus_url?
......
......@@ -15,5 +15,7 @@ module Serverless
format: { with: HEX_REGEXP, message: 'only allows hex characters' }
default_value_for(:uuid, allows_nil: false) { Gitlab::Serverless::Domain.generate_uuid }
delegate :domain, to: :pages_domain
end
end
This diff is collapsed.
---
title: Rename 'GitLab Instance Administration' project to 'GitLab self monitoring' project
merge_request: 23182
author:
type: changed
# rubocop:disable Rails/Output
if defined?(Rails::Console) || Rails.env.development?
# when using `spring` this will only print out the first time
if defined?(Rails::Console)
# note that this will not print out when using `spring`
justify = 15
puts '-' * 80
puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision}) #{Gitlab.ee? ? 'EE' : 'FOSS'}"
puts " GitLab:".ljust(justify) + "#{Gitlab::VERSION} (#{Gitlab.revision})"
puts " GitLab Shell:".ljust(justify) + "#{Gitlab::VersionInfo.parse(Gitlab::Shell.new.version)}"
puts " #{Gitlab::Database.human_adapter_name}:".ljust(justify) + Gitlab::Database.version
......
# GitLab instance administration project
---
redirect_to: '../gitlab_self_monitoring_project/index.md'
---
NOTE: **Note:**
This feature is available behind a feature flag called `self_monitoring_project`
since [12.7](https://gitlab.com/gitlab-org/gitlab/issues/32351). The feature flag
will be removed once we [add dashboards to display metrics](https://gitlab.com/groups/gitlab-org/-/epics/2367).
GitLab has been adding the ability for administrators to see insights into the health of
their GitLab instance. In order to surface this experience in a native way, similar to how
you would interact with an application deployed via GitLab, a base project called
"GitLab Instance Administration" with
[internal visibility](../../../public_access/public_access.md#internal-projects) will be
added under a group called "GitLab Instance Administrators" specifically created for
visualizing and configuring the monitoring of your GitLab instance.
All administrators at the time of creation of the project and group will be added
as maintainers of the group and project, and as an admin, you'll be able to add new
members to the group in order to give them maintainer access to the project.
This project will be used for self-monitoring your GitLab instance.
## Connection to Prometheus
The project will be automatically configured to connect to the
[internal Prometheus](../prometheus/index.md) instance if the Prometheus
instance is present (should be the case if GitLab was installed via Omnibus
and you haven't disabled it).
If that's not the case or if you have an external Prometheus instance or an HA setup,
you should
[configure it manually](../../../user/project/integrations/prometheus.md#manual-configuration-of-prometheus).
## Taking action on Prometheus alerts **(ULTIMATE)**
You can [add a webhook](../../../user/project/integrations/prometheus.md#external-prometheus-instances)
to the Prometheus config in order for GitLab to receive notifications of any alerts.
Once the webhook is setup, you can
[take action on incoming alerts](../../../user/project/integrations/prometheus.md#taking-action-on-incidents-ultimate).
This document was moved to [another location](../gitlab_self_monitoring_project/index.md).
# GitLab self monitoring project
NOTE: **Note:**
This feature is available behind a feature flag called `self_monitoring_project`
since [12.7](https://gitlab.com/gitlab-org/gitlab/issues/32351). The feature flag
will be removed once we [add dashboards to display metrics](https://gitlab.com/groups/gitlab-org/-/epics/2367).
GitLab has been adding the ability for administrators to see insights into the health of
their GitLab instance. In order to surface this experience in a native way, similar to how
you would interact with an application deployed via GitLab, a base project called
"GitLab self monitoring" with
[internal visibility](../../../public_access/public_access.md#internal-projects) will be
added under a group called "GitLab Instance Administrators" specifically created for
visualizing and configuring the monitoring of your GitLab instance.
All administrators at the time of creation of the project and group will be added
as maintainers of the group and project, and as an admin, you'll be able to add new
members to the group in order to give them maintainer access to the project.
This project will be used for self-monitoring your GitLab instance.
## Connection to Prometheus
The project will be automatically configured to connect to the
[internal Prometheus](../prometheus/index.md) instance if the Prometheus
instance is present (should be the case if GitLab was installed via Omnibus
and you haven't disabled it).
If that's not the case or if you have an external Prometheus instance or an HA setup,
you should
[configure it manually](../../../user/project/integrations/prometheus.md#manual-configuration-of-prometheus).
## Taking action on Prometheus alerts **(ULTIMATE)**
You can [add a webhook](../../../user/project/integrations/prometheus.md#external-prometheus-instances)
to the Prometheus config in order for GitLab to receive notifications of any alerts.
Once the webhook is setup, you can
[take action on incoming alerts](../../../user/project/integrations/prometheus.md#taking-action-on-incidents-ultimate).
......@@ -2,7 +2,7 @@
Explore our features to monitor your GitLab instance:
- [GitLab self-monitoring](gitlab_instance_administration_project/index.md): The
- [GitLab self-monitoring](gitlab_self_monitoring_project/index.md): The
GitLab instance administration project helps to monitor the GitLab instance and
take action on alerts.
- [Performance monitoring](performance/index.md): GitLab Performance Monitoring makes it possible to measure a wide variety of statistics of your instance.
......
......@@ -32,6 +32,7 @@ The following metrics are available:
| `gitlab_cache_operations_total` | Counter | 12.2 | Cache operations by controller/action | controller, action, operation |
| `gitlab_database_transaction_seconds` | Histogram | 12.1 | Time spent in database transactions, in seconds | |
| `gitlab_method_call_duration_seconds` | Histogram | 10.2 | Method calls real duration | controller, action, module, method |
| `gitlab_page_out_of_bounds` | Counter | 12.8 | Counter for the PageLimiter pagination limit being hit | controller, action, bot |
| `gitlab_rails_queue_duration_seconds` | Histogram | 9.4 | Measures latency between GitLab Workhorse forwarding a request to Rails | |
| `gitlab_sql_duration_seconds` | Histogram | 10.2 | SQL execution time, excluding SCHEMA operations and BEGIN / COMMIT | |
| `gitlab_transaction_allocated_memory_bytes` | Histogram | 10.2 | Allocated memory for all transactions (gitlab_transaction_* metrics) | |
......
......@@ -2681,6 +2681,27 @@ trigger_job:
strategy: depend
```
#### Linking pipelines with `trigger:strategy`
By default, the `trigger` job completes with the `success` status
as soon as the downstream pipeline is created.
To force the `trigger` job to wait for the downstream (multi-project or child) pipeline to complete, use
`strategy: depend`. This will make the trigger job wait with a "running" status until the triggered
pipeline completes. At that point, the `trigger` job will complete and display the same status as
the downstream job.
```yaml
trigger_job:
trigger:
include: path/to/child-pipeline.yml
strategy: depend
```
This can help keep your pipeline execution linear. In the example above, jobs from
subsequent stages will wait for the triggered pipeline to successfully complete before
starting, at the cost of reduced parallelization.
### `interruptible`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/23464) in GitLab 12.3.
......
......@@ -54,17 +54,6 @@ By default, this seeds an average of 10 issues per week for the last 52 weeks
per project. All issues will also be randomly labeled with team, type, severity,
and priority.
#### Seeding groups with sub-groups
You can seed groups with sub-groups that contain milestones/projects/issues
with the `gitlab:seed:group_seed` task:
```shell
bin/rake "gitlab:seed:group_seed[subgroup_depth, username]"
```
Group are additionally seeded with epics if GitLab instance has epics feature available.
### Automation
If you're very sure that you want to **wipe the current database** and refill
......
......@@ -13,11 +13,11 @@ module Gitlab
end
def self_monitoring_project
application_settings.instance_administration_project
application_settings.self_monitoring_project
end
def self_monitoring_project_id
application_settings.instance_administration_project_id
application_settings.self_monitoring_project_id
end
end
end
......
......@@ -9,7 +9,7 @@ module Gitlab
include SelfMonitoring::Helpers
VISIBILITY_LEVEL = Gitlab::VisibilityLevel::INTERNAL
PROJECT_NAME = 'GitLab Instance Administration'
PROJECT_NAME = 'GitLab self monitoring'
steps :validate_application_settings,
:create_group,
......@@ -69,7 +69,7 @@ module Gitlab
return success(result) if project_created?
response = application_settings.update(
instance_administration_project_id: result[:project].id
self_monitoring_project_id: result[:project].id
)
if response
......@@ -115,7 +115,7 @@ module Gitlab
def docs_path
Rails.application.routes.url_helpers.help_page_path(
'administration/monitoring/gitlab_instance_administration_project/index'
'administration/monitoring/gitlab_self_monitoring_project/index'
)
end
......
# frozen_string_literal: true
module Gitlab
module Serverless
class FunctionURI < URI::HTTPS
SERVERLESS_DOMAIN_REGEXP = %r{^(?<scheme>https?://)?(?<function>[^.]+)-(?<cluster_left>\h{2})a1(?<cluster_middle>\h{10})f2(?<cluster_right>\h{2})(?<environment_id>\h+)-(?<environment_slug>[^.]+)\.(?<domain>.+)}.freeze
attr_reader :function, :cluster, :environment
def initialize(function: nil, cluster: nil, environment: nil)
initialize_required_argument(:function, function)
initialize_required_argument(:cluster, cluster)
initialize_required_argument(:environment, environment)
@host = "#{function}-#{cluster.uuid[0..1]}a1#{cluster.uuid[2..-3]}f2#{cluster.uuid[-2..-1]}#{"%x" % environment.id}-#{environment.slug}.#{cluster.domain}"
super('https', nil, host, nil, nil, nil, nil, nil, nil)
end
def self.parse(uri)
match = SERVERLESS_DOMAIN_REGEXP.match(uri)
return unless match
cluster = ::Serverless::DomainCluster.find(match[:cluster_left] + match[:cluster_middle] + match[:cluster_right])
return unless cluster
environment = ::Environment.find(match[:environment_id].to_i(16))
return unless environment&.slug == match[:environment_slug]
new(
function: match[:function],
cluster: cluster,
environment: environment
)
end
private
def initialize_required_argument(name, value)
raise ArgumentError.new("missing argument: #{name}") unless value
instance_variable_set("@#{name}".to_sym, value)
end
end
end
end
......@@ -13,21 +13,10 @@ module Gitlab
(EE_QUEUE_CONFIG_PATH if Gitlab.ee?)
].compact.freeze
# For queues that don't have explicit workers - default and mailers
DummyWorker = Struct.new(:queue, :weight) do
def queue_namespace
nil
end
def get_weight
weight
end
end
DEFAULT_WORKERS = [
Gitlab::SidekiqConfig::Worker.new(DummyWorker.new('default', 1), ee: false),
Gitlab::SidekiqConfig::Worker.new(DummyWorker.new('mailers', 2), ee: false)
].freeze
DummyWorker.new('default', weight: 1),
DummyWorker.new('mailers', weight: 2)
].map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze
class << self
include Gitlab::SidekiqConfig::CliMethods
......@@ -66,12 +55,13 @@ module Gitlab
workers.partition(&:ee?).reverse.map(&:sort)
end
# YAML.load_file is OK here as we control the file contents
def all_queues_yml_outdated?
foss_workers, ee_workers = workers_for_all_queues_yml
return true if foss_workers != YAML.safe_load(File.read(FOSS_QUEUE_CONFIG_PATH))
return true if foss_workers != YAML.load_file(FOSS_QUEUE_CONFIG_PATH)
Gitlab.ee? && ee_workers != YAML.safe_load(File.read(EE_QUEUE_CONFIG_PATH))
Gitlab.ee? && ee_workers != YAML.load_file(EE_QUEUE_CONFIG_PATH)
end
def queues_for_sidekiq_queues_yml
......@@ -89,9 +79,9 @@ module Gitlab
remaining_queues.map(&:queue_and_weight)).sort
end
# YAML.load_file is OK here as we control the file contents
def sidekiq_queues_yml_outdated?
# YAML.load is OK here as we control the file contents
config_queues = YAML.load(File.read(SIDEKIQ_QUEUES_PATH))[:queues] # rubocop:disable Security/YAMLLoad
config_queues = YAML.load_file(SIDEKIQ_QUEUES_PATH)[:queues]
queues_for_sidekiq_queues_yml != config_queues
end
......
......@@ -23,8 +23,10 @@ module Gitlab
@worker_queues[rails_path] ||= QUEUE_CONFIG_PATHS.flat_map do |path|
full_path = File.join(rails_path, path)
queues = File.exist?(full_path) ? YAML.load_file(full_path) : []
File.exist?(full_path) ? YAML.load_file(full_path) : []
# https://gitlab.com/gitlab-org/gitlab/issues/199230
queues.map { |queue| queue.is_a?(Hash) ? queue[:name] : queue }
end
end
......@@ -37,6 +39,12 @@ module Gitlab
[queue, *queues_set.grep(/\A#{queue}:/)]
end
end
def clear_memoization!
if instance_variable_defined?('@worker_queues')
remove_instance_variable('@worker_queues')
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
end
end
......
# frozen_string_literal: true
module Gitlab
module SidekiqConfig
# For queues that don't have explicit workers - default and mailers
class DummyWorker
attr_accessor :queue
ATTRIBUTE_METHODS = {
feature_category: :get_feature_category,
has_external_dependencies: :worker_has_external_dependencies?,
latency_sensitive: :latency_sensitive_worker?,
resource_boundary: :get_worker_resource_boundary,
weight: :get_weight
}.freeze
def initialize(queue, attributes = {})
@queue = queue
@attributes = attributes
end
def queue_namespace
nil
end
ATTRIBUTE_METHODS.each do |attribute, meth|
define_method meth do
@attributes[attribute]
end
end
end
end
end
......@@ -41,11 +41,18 @@ module Gitlab
# YAML representation
def encode_with(coder)
coder.represent_scalar(nil, to_yaml)
coder.represent_map(nil, to_yaml)
end
def to_yaml
queue
{
name: queue,
feature_category: get_feature_category,
has_external_dependencies: worker_has_external_dependencies?,
latency_sensitive: latency_sensitive_worker?,
resource_boundary: get_worker_resource_boundary,
weight: get_weight
}
end
def namespace_and_weight
......
# frozen_string_literal: true
# Seed test groups with:
# 1. 2 Subgroups per level
# 1. 2 Users & group members per group
# 1. 2 Epics, 2 Milestones & 2 Projects per group
# 1. Project issues
#
# It also assigns each project's issue with one of group's or ascendants
# groups milestone & epic.
#
# @param subgroups_depth - number of subgroup levels
# @param username - user creating subgroups (i.e. GitLab admin)
#
# @example
# bundle exec rake "gitlab:seed:group_seed[5, root]"
#
namespace :gitlab do
namespace :seed do
desc 'Seed groups with sub-groups/projects/epics/milestones for Group Import testing'
task :group_seed, [:subgroups_depth, :username] => :gitlab_environment do |_t, args|
require 'sidekiq/testing'
GroupSeeder.new(
subgroups_depth: args.subgroups_depth,
username: args.username
).seed
end
end
end
class GroupSeeder
PROJECT_URL = 'https://gitlab.com/gitlab-org/gitlab-test.git'
attr_reader :all_group_ids
def initialize(subgroups_depth:, username:)
@subgroups_depth = subgroups_depth.to_i
@user = User.find_by_username(username)
@group_names = Set.new
@resource_count = 2
@all_groups = {}
@all_group_ids = []
end
def seed
create_groups
puts 'Done!'
end
def create_groups
create_root_group
create_sub_groups
create_users_and_members
create_epics if Gitlab.ee?
create_labels
create_milestones
Sidekiq::Testing.inline! do
create_projects
end
end
def create_users_and_members
all_group_ids.each do |group_id|
@resource_count.times do |_|
user = create_user
create_member(user.id, group_id)
end
end
end
def create_root_group
root_group = ::Groups::CreateService.new(@user, group_params).execute
track_group_id(1, root_group.id)
end
def create_sub_groups
(2..@subgroups_depth).each do |level|
parent_level = level - 1
current_level = level
parent_groups = @all_groups[parent_level]
parent_groups.each do |parent_id|
@resource_count.times do |_|
sub_group = ::Groups::CreateService.new(@user, group_params(parent_id: parent_id)).execute
track_group_id(current_level, sub_group.id)
end
end
end
end
def track_group_id(depth_level, group_id)
@all_groups[depth_level] ||= []
@all_groups[depth_level] << group_id
@all_group_ids << group_id
end
def group_params(parent_id: nil)
name = unique_name
{
name: name,
path: name,
parent_id: parent_id
}
end
def unique_name
name = ffaker_name
name = ffaker_name until @group_names.add?(name)
name
end
def ffaker_name
FFaker::Lorem.characters(5)
end
def create_user
User.create!(
username: FFaker::Internet.user_name,
name: FFaker::Name.name,
email: FFaker::Internet.email,
confirmed_at: DateTime.now,
password: Devise.friendly_token
)
end
def create_member(user_id, group_id)
roles = Gitlab::Access.values
GroupMember.create(user_id: user_id, access_level: roles.sample, source_id: group_id)
end
def create_epics
all_group_ids.each do |group_id|
@resource_count.times do |_|
group = Group.find(group_id)
epic_params = {
title: FFaker::Lorem.sentence(6),
description: FFaker::Lorem.paragraphs(3).join("\n\n"),
author: group.users.sample,
group: group
}
Epic.create!(epic_params)
end
end
end
def create_labels
all_group_ids.each do |group_id|
@resource_count.times do |_|
group = Group.find(group_id)
label_title = FFaker::Product.brand
Labels::CreateService.new(title: label_title, color: "##{Digest::MD5.hexdigest(label_title)[0..5]}").execute(group: group)
end
end
end
def create_milestones
all_group_ids.each do |group_id|
@resource_count.times do |i|
group = Group.find(group_id)
milestone_params = {
title: "v#{i}.0",
description: FFaker::Lorem.sentence,
state: [:active, :closed].sample
}
Milestones::CreateService.new(group, group.members.sample, milestone_params).execute
end
end
end
def create_projects
all_group_ids.each do |group_id|
group = Group.find(group_id)
@resource_count.times do |i|
_, project_path = PROJECT_URL.split('/')[-2..-1]
project_path.gsub!('.git', '')
params = {
import_url: PROJECT_URL,
namespace_id: group.id,
name: project_path.titleize + FFaker::Lorem.characters(10),
description: FFaker::Lorem.sentence,
visibility_level: 0,
skip_disk_validation: true
}
project = nil
Sidekiq::Worker.skipping_transaction_check do
project = ::Projects::CreateService.new(@user, params).execute
project.send(:_run_after_commit_queue)
project.import_state.send(:_run_after_commit_queue)
project.repository.expire_all_method_caches
end
create_project_issues(project)
assign_issues_to_epics_and_milestones(project)
end
end
end
def create_project_issues(project)
Gitlab::Seeder.quiet do
seeder = Quality::Seeders::Issues.new(project: project)
seeder.seed(backfill_weeks: 2, average_issues_per_week: 2)
end
end
def assign_issues_to_epics_and_milestones(project)
group_ids = project.group.self_and_ancestors.map(&:id)
project.issues.each do |issue|
issue_params = {
milestone: Milestone.where(group: group_ids).sample
}
issue_params[:epic] = Epic.where(group: group_ids).sample if Gitlab.ee?
issue.update(issue_params)
end
end
end
......@@ -1260,12 +1260,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
msgid "AdminCredentials|Personal Access Tokens"
msgstr ""
msgid "AdminCredentials|SSH Keys"
msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
......@@ -1413,9 +1407,6 @@ msgstr ""
msgid "AdminUsers|New user"
msgstr ""
msgid "AdminUsers|No credentials found"
msgstr ""
msgid "AdminUsers|No users found"
msgstr ""
......@@ -5622,6 +5613,15 @@ msgstr ""
msgid "Credentials"
msgstr ""
msgid "CredentialsInventory|No credentials found"
msgstr ""
msgid "CredentialsInventory|Personal Access Tokens"
msgstr ""
msgid "CredentialsInventory|SSH Keys"
msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
......
......@@ -144,14 +144,6 @@ describe Projects::ReleasesController do
end
end
context 'when feature flag `release_edit_page` is disabled' do
before do
stub_feature_flags(release_edit_page: false)
end
it_behaves_like 'not found'
end
context 'when release does not exist' do
let!(:release) { }
let(:tag) { 'non-existent-tag' }
......
......@@ -374,5 +374,10 @@ x6zG6WoibsbsJMj70nwseUnPTBQNDP+j61RJjC/r
-----END EC PRIVATE KEY-----'
end
end
trait :instance_serverless do
wildcard { true }
domain_type { :instance }
end
end
end
# frozen_string_literal: true
FactoryBot.define do
factory :serverless_domain_cluster, class: 'Serverless::DomainCluster' do
factory :serverless_domain_cluster, class: '::Serverless::DomainCluster' do
pages_domain { create(:pages_domain) }
knative { create(:clusters_applications_knative) }
creator { create(:user) }
......
......@@ -33,17 +33,22 @@ describe IssuesFinder do
before do
project2.add_developer(user3)
issue3.assignees = [user2, user3]
issue2.assignees = [user2]
issue3.assignees = [user3]
end
it_behaves_like 'assignee username filter' do
let(:params) { { assignee_username: [user2.username, user3.username] } }
let(:expected_issuables) { [issue3] }
let(:params) { { assignee_username: [user2.username] } }
let(:expected_issuables) { [issue2] }
end
it_behaves_like 'assignee NOT username filter' do
let(:params) { { not: { assignee_username: [user2.username, user3.username] } } }
let(:expected_issuables) { [issue1, issue2, issue4] }
before do
issue2.assignees = [user2]
end
let(:params) { { not: { assignee_username: [user.username, user2.username] } } }
let(:expected_issuables) { [issue3, issue4] }
end
end
......@@ -395,8 +400,8 @@ describe IssuesFinder do
context 'using NOT' do
let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
it 'returns issues that do not have ALL labels provided' do
expect(issues).to contain_exactly(issue1, issue3, issue4)
it 'returns issues that do not have any of the labels provided' do
expect(issues).to contain_exactly(issue1, issue4)
end
end
end
......@@ -417,8 +422,8 @@ describe IssuesFinder do
context 'using NOT' do
let(:params) { { not: { label_name: [label.title, label2.title].join(',') } } }
it 'returns issues that do not have ALL labels provided' do
expect(issues).to contain_exactly(issue1, issue3, issue4)
it 'returns issues that do not have ANY ONE of the labels provided' do
expect(issues).to contain_exactly(issue1, issue4)
end
end
end
......
......@@ -107,7 +107,7 @@ describe ApplicationSettingsHelper do
let(:project) { build(:project) }
before do
stub_application_setting(instance_administration_project: project)
stub_application_setting(self_monitoring_project: project)
end
it 'returns self_monitoring_project_exists true' do
......
......@@ -103,7 +103,7 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
end
it 'creates project with correct name and description' do
path = 'administration/monitoring/gitlab_instance_administration_project/index'
path = 'administration/monitoring/gitlab_self_monitoring_project/index'
docs_path = Rails.application.routes.url_helpers.help_page_path(path)
expect(result[:status]).to eq(:success)
......@@ -122,13 +122,13 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
it 'saves the project id' do
expect(result[:status]).to eq(:success)
expect(application_setting.instance_administration_project_id).to eq(project.id)
expect(application_setting.self_monitoring_project_id).to eq(project.id)
end
it 'returns error when saving project ID fails' do
allow(application_setting).to receive(:update).and_call_original
allow(application_setting).to receive(:update)
.with(instance_administration_project_id: anything)
.with(self_monitoring_project_id: anything)
.and_return(false)
expect(result).to eq(
......@@ -144,7 +144,7 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do
before do
application_setting.instance_administrators_group_id = existing_group.id
application_setting.instance_administration_project_id = existing_project.id
application_setting.self_monitoring_project_id = existing_project.id
end
it 'returns success' do
......
......@@ -24,7 +24,7 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::DeleteService do
let(:application_setting) do
create(
:application_setting,
instance_administration_project_id: project.id,
self_monitoring_project_id: project.id,
instance_administrators_group_id: group.id
)
end
......@@ -38,7 +38,7 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::DeleteService do
it 'deletes project ID from application settings' do
subject.execute
expect(application_setting.reload.instance_administration_project_id).to be_nil
expect(application_setting.reload.self_monitoring_project_id).to be_nil
end
it 'does not delete group' do
......
......@@ -6,7 +6,7 @@ describe Gitlab::Prometheus::Queries::KnativeInvocationQuery do
include PrometheusHelpers
let(:project) { create(:project) }
let(:serverless_func) { Serverless::Function.new(project, 'test-name', 'test-ns') }
let(:serverless_func) { ::Serverless::Function.new(project, 'test-name', 'test-ns') }
let(:client) { double('prometheus_client') }
subject { described_class.new(client) }
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Serverless::FunctionURI do
let(:function) { 'test-function' }
let(:domain) { 'serverless.gitlab.io' }
let(:pages_domain) { create(:pages_domain, :instance_serverless, domain: domain) }
let!(:cluster) { create(:serverless_domain_cluster, uuid: 'abcdef12345678', pages_domain: pages_domain) }
let(:valid_cluster) { 'aba1cdef123456f278' }
let(:invalid_cluster) { 'aba1cdef123456f178' }
let!(:environment) { create(:environment, name: 'test') }
let(:valid_uri) { "https://#{function}-#{valid_cluster}#{"%x" % environment.id}-#{environment.slug}.#{domain}" }
let(:valid_fqdn) { "#{function}-#{valid_cluster}#{"%x" % environment.id}-#{environment.slug}.#{domain}" }
let(:invalid_uri) { "https://#{function}-#{invalid_cluster}#{"%x" % environment.id}-#{environment.slug}.#{domain}" }
shared_examples 'a valid FunctionURI class' do
describe '#to_s' do
it 'matches valid URI' do
expect(subject.to_s).to eq valid_uri
end
end
describe '#function' do
it 'returns function' do
expect(subject.function).to eq function
end
end
describe '#cluster' do
it 'returns cluster' do
expect(subject.cluster).to eq cluster
end
end
describe '#environment' do
it 'returns environment' do
expect(subject.environment).to eq environment
end
end
end
describe '.new' do
context 'with valid arguments' do
subject { described_class.new(function: function, cluster: cluster, environment: environment) }
it_behaves_like 'a valid FunctionURI class'
end
context 'with invalid arguments' do
subject { described_class.new(function: function, environment: environment) }
it 'raises an exception' do
expect { subject }.to raise_error(ArgumentError)
end
end
end
describe '.parse' do
context 'with valid URI' do
subject { described_class.parse(valid_uri) }
it_behaves_like 'a valid FunctionURI class'
end
context 'with valid FQDN' do
subject { described_class.parse(valid_fqdn) }
it_behaves_like 'a valid FunctionURI class'
end
context 'with invalid URI' do
subject { described_class.parse(invalid_uri) }
it 'returns nil' do
expect(subject).to be_nil
end
end
end
end
# frozen_string_literal: true
require 'fast_spec_helper'
describe Gitlab::SidekiqConfig::CliMethods do
let(:dummy_root) { '/tmp/' }
describe '.worker_queues' do
def expand_path(path)
File.join(dummy_root, path)
end
def stub_exists(exists: true)
['app/workers/all_queues.yml', 'ee/app/workers/all_queues.yml'].each do |path|
allow(File).to receive(:exist?).with(expand_path(path)).and_return(exists)
end
end
def stub_contents(foss_queues, ee_queues)
allow(YAML).to receive(:load_file)
.with(expand_path('app/workers/all_queues.yml'))
.and_return(foss_queues)
allow(YAML).to receive(:load_file)
.with(expand_path('ee/app/workers/all_queues.yml'))
.and_return(ee_queues)
end
before do
described_class.clear_memoization!
end
context 'when the file exists' do
before do
stub_exists(exists: true)
end
shared_examples 'valid file contents' do
it 'memoizes the result' do
result = described_class.worker_queues(dummy_root)
stub_exists(exists: false)
expect(described_class.worker_queues(dummy_root)).to eq(result)
end
it 'flattens and joins the contents' do
expected_queues = %w[queue_a queue_b]
expected_queues = expected_queues.first(1) unless Gitlab.ee?
expect(described_class.worker_queues(dummy_root))
.to match_array(expected_queues)
end
end
context 'when the file contains an array of strings' do
before do
stub_contents(['queue_a'], ['queue_b'])
end
include_examples 'valid file contents'
end
context 'when the file contains an array of hashes' do
before do
stub_contents([{ name: 'queue_a' }], [{ name: 'queue_b' }])
end
include_examples 'valid file contents'
end
end
context 'when the file does not exist' do
before do
stub_exists(exists: false)
end
it 'returns an empty array' do
expect(described_class.worker_queues(dummy_root)).to be_empty
end
end
end
describe '.expand_queues' do
let(:all_queues) do
['cronjob:stuck_import_jobs', 'cronjob:stuck_merge_jobs', 'post_receive']
end
it 'defaults the value of the second argument to .worker_queues' do
allow(described_class).to receive(:worker_queues).and_return([])
expect(described_class.expand_queues(['cronjob']))
.to contain_exactly('cronjob')
allow(described_class).to receive(:worker_queues).and_return(all_queues)
expect(described_class.expand_queues(['cronjob']))
.to contain_exactly('cronjob', 'cronjob:stuck_import_jobs', 'cronjob:stuck_merge_jobs')
end
it 'expands queue namespaces to concrete queue names' do
expect(described_class.expand_queues(['cronjob'], all_queues))
.to contain_exactly('cronjob', 'cronjob:stuck_import_jobs', 'cronjob:stuck_merge_jobs')
end
it 'lets concrete queue names pass through' do
expect(described_class.expand_queues(['post_receive'], all_queues))
.to contain_exactly('post_receive')
end
it 'lets unknown queues pass through' do
expect(described_class.expand_queues(['unknown'], all_queues))
.to contain_exactly('unknown')
end
end
end
......@@ -3,9 +3,17 @@
require 'fast_spec_helper'
describe Gitlab::SidekiqConfig::Worker do
def create_worker(queue:, weight: 0)
def create_worker(queue:, **attributes)
namespace = queue.include?(':') && queue.split(':').first
inner_worker = double(queue: queue, queue_namespace: namespace, get_weight: weight)
inner_worker = double(
queue: queue,
queue_namespace: namespace,
get_feature_category: attributes[:feature_category],
get_weight: attributes[:weight],
get_worker_resource_boundary: attributes[:resource_boundary],
latency_sensitive_worker?: attributes[:latency_sensitive],
worker_has_external_dependencies?: attributes[:has_external_dependencies]
)
described_class.new(inner_worker, ee: false)
end
......@@ -75,13 +83,32 @@ describe Gitlab::SidekiqConfig::Worker do
end
describe 'YAML encoding' do
it 'encodes the worker in YAML as a string of the queue' do
worker_a = create_worker(queue: 'a')
worker_b = create_worker(queue: 'b')
it 'encodes the worker in YAML as a hash of the queue' do
attributes_a = {
feature_category: :source_code_management,
has_external_dependencies: false,
latency_sensitive: false,
resource_boundary: :memory,
weight: 2
}
attributes_b = {
feature_category: :not_owned,
has_external_dependencies: true,
latency_sensitive: true,
resource_boundary: :unknown,
weight: 1
}
worker_a = create_worker(queue: 'a', **attributes_a)
worker_b = create_worker(queue: 'b', **attributes_b)
expect(YAML.dump(worker_a))
.to eq(YAML.dump(attributes_a.reverse_merge(name: 'a')))
expect(YAML.dump(worker_a)).to eq(YAML.dump('a'))
expect(YAML.dump([worker_a, worker_b]))
.to eq(YAML.dump(%w[a b]))
.to eq(YAML.dump([attributes_a.reverse_merge(name: 'a'),
attributes_b.reverse_merge(name: 'b')]))
end
end
......
......@@ -24,27 +24,6 @@ describe Gitlab::SidekiqConfig do
end
end
describe '.expand_queues' do
it 'expands queue namespaces to concrete queue names' do
queues = described_class.expand_queues(%w[cronjob])
expect(queues).to include('cronjob:stuck_import_jobs')
expect(queues).to include('cronjob:stuck_merge_jobs')
end
it 'lets concrete queue names pass through' do
queues = described_class.expand_queues(%w[post_receive])
expect(queues).to include('post_receive')
end
it 'lets unknown queues pass through' do
queues = described_class.expand_queues(%w[unknown])
expect(queues).to include('unknown')
end
end
describe '.workers_for_all_queues_yml' do
it 'returns a tuple with FOSS workers first' do
expect(described_class.workers_for_all_queues_yml.first)
......@@ -53,29 +32,31 @@ describe Gitlab::SidekiqConfig do
end
describe '.all_queues_yml_outdated?' do
before do
workers = [
PostReceive,
let(:workers) do
[
MergeWorker,
PostReceive,
ProcessCommitWorker
].map { |worker| described_class::Worker.new(worker, ee: false) }
end
before do
allow(described_class).to receive(:workers).and_return(workers)
allow(Gitlab).to receive(:ee?).and_return(false)
end
it 'returns true if the YAML file does not match the application code' do
allow(File).to receive(:read)
it 'returns true if the YAML file does not matcph the application code' do
allow(YAML).to receive(:load_file)
.with(described_class::FOSS_QUEUE_CONFIG_PATH)
.and_return(YAML.dump(%w[post_receive merge]))
.and_return(workers.first(2).map(&:to_yaml))
expect(described_class.all_queues_yml_outdated?).to be(true)
end
it 'returns false if the YAML file matches the application code' do
allow(File).to receive(:read)
allow(YAML).to receive(:load_file)
.with(described_class::FOSS_QUEUE_CONFIG_PATH)
.and_return(YAML.dump(%w[merge post_receive process_commit]))
.and_return(workers.map(&:to_yaml))
expect(described_class.all_queues_yml_outdated?).to be(false)
end
......@@ -125,17 +106,17 @@ describe Gitlab::SidekiqConfig do
end
it 'returns true if the YAML file does not match the application code' do
allow(File).to receive(:read)
allow(YAML).to receive(:load_file)
.with(described_class::SIDEKIQ_QUEUES_PATH)
.and_return(YAML.dump(queues: expected_queues.reverse))
.and_return(queues: expected_queues.reverse)
expect(described_class.sidekiq_queues_yml_outdated?).to be(true)
end
it 'returns false if the YAML file matches the application code' do
allow(File).to receive(:read)
allow(YAML).to receive(:load_file)
.with(described_class::SIDEKIQ_QUEUES_PATH)
.and_return(YAML.dump(queues: expected_queues))
.and_return(queues: expected_queues)
expect(described_class.sidekiq_queues_yml_outdated?).to be(false)
end
......
......@@ -17,7 +17,7 @@ describe Clusters::Applications::Knative do
end
describe 'associations' do
it { is_expected.to have_one(:serverless_domain_cluster).class_name('Serverless::DomainCluster').with_foreign_key('clusters_applications_knative_id').inverse_of(:knative) }
it { is_expected.to have_one(:serverless_domain_cluster).class_name('::Serverless::DomainCluster').with_foreign_key('clusters_applications_knative_id').inverse_of(:knative) }
end
describe 'when cloud run is enabled' do
......
......@@ -70,7 +70,7 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
before do
service.api_url = 'http://localhost:9090'
stub_application_setting(instance_administration_project_id: project.id)
stub_application_setting(self_monitoring_project_id: project.id)
stub_config(prometheus: { enable: true, listen_address: 'localhost:9090' })
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
describe Serverless::DomainCluster do
describe ::Serverless::DomainCluster do
subject { create(:serverless_domain_cluster) }
describe 'validations' do
......@@ -46,4 +46,8 @@ describe Serverless::DomainCluster do
end
end
end
describe 'domain' do
it { is_expected.to respond_to(:domain) }
end
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
describe Serverless::Function do
describe ::Serverless::Function do
let(:project) { create(:project) }
let(:func) { described_class.new(project, 'test', 'test-ns') }
......
......@@ -84,8 +84,8 @@ describe 'Self-Monitoring project requests' do
let(:project) { build(:project) }
before do
stub_application_setting(instance_administration_project_id: 1)
stub_application_setting(instance_administration_project: project)
stub_application_setting(self_monitoring_project_id: 1)
stub_application_setting(self_monitoring_project: project)
end
it 'does not need job_id' do
......@@ -169,7 +169,7 @@ describe 'Self-Monitoring project requests' do
.with(job_id)
.and_return(true)
stub_application_setting(instance_administration_project_id: 1)
stub_application_setting(self_monitoring_project_id: 1)
end
it_behaves_like 'sets polling header and returns accepted' do
......@@ -179,7 +179,7 @@ describe 'Self-Monitoring project requests' do
context 'when self-monitoring project exists and job does not exist' do
before do
stub_application_setting(instance_administration_project_id: 1)
stub_application_setting(self_monitoring_project_id: 1)
end
it 'returns bad_request' do
......
......@@ -12,7 +12,7 @@ RSpec.shared_examples 'not accessible if feature flag is disabled' do
expect(response).to have_gitlab_http_status(:not_implemented)
expect(json_response).to eq(
'message' => _('Self-monitoring is not enabled on this GitLab server, contact your administrator.'),
'documentation_url' => help_page_path('administration/monitoring/gitlab_instance_administration_project/index')
'documentation_url' => help_page_path('administration/monitoring/gitlab_self_monitoring_project/index')
)
end
end
......
# frozen_string_literal: true
require 'rake_helper'
describe 'gitlab:seed:group_seed rake task' do
let(:username) { 'group_seed' }
let!(:user) { create(:user, username: username) }
let(:task_params) { [2, username] }
before do
Rake.application.rake_require('tasks/gitlab/seed/group_seed')
end
subject { run_rake_task('gitlab:seed:group_seed', task_params) }
it 'performs group seed successfully' do
expect { subject }.not_to raise_error
group = user.groups.first
expect(user.groups.count).to be 3
expect(group.projects.count).to be 2
expect(group.members.count).to be 3
expect(group.milestones.count).to be 2
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment