- {{ s__('AlertManagement|Assignee') }}
+ {{ __('Assignee') }}
- {{ s__('AlertManagement|Edit') }}
+ {{ __('Edit') }}
@@ -222,7 +225,7 @@ export default {
@hide="hideDropdown"
>
- {{ s__('AlertManagement|Assign To') }}
+ {{ __('Assign To') }}
- {{ s__('AlertManagement|Unassigned') }}
+ {{ __('Unassigned') }}
- {{ s__('AlertManagement|Assignee') }}
+ {{ __('Assignee') }}
- {{ s__('AlertManagement|No Matching Results') }}
+ {{ __('No Matching Results') }}
@@ -276,7 +279,7 @@ export default {
assignedUser
}}
- {{ s__('AlertManagement|None -') }}
+ {{ __('None') }} -
- {{ s__('AlertManagement| assign yourself') }}
+ {{ __('assign yourself') }}
diff --git a/app/controllers/admin/jobs_controller.rb b/app/controllers/admin/jobs_controller.rb
index a3a18a115e9..7b50a45a9cd 100644
--- a/app/controllers/admin/jobs_controller.rb
+++ b/app/controllers/admin/jobs_controller.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::JobsController < Admin::ApplicationController
+ BUILDS_PER_PAGE = 30
+
def index
# We need all builds for tabs counters
@all_builds = Ci::JobsFinder.new(current_user: current_user).execute
@@ -8,7 +10,7 @@ class Admin::JobsController < Admin::ApplicationController
@scope = params[:scope]
@builds = Ci::JobsFinder.new(current_user: current_user, params: params).execute
@builds = @builds.eager_load_everything
- @builds = @builds.page(params[:page]).per(30)
+ @builds = @builds.page(params[:page]).per(BUILDS_PER_PAGE).without_count
end
def cancel_all
diff --git a/app/helpers/dropdowns_helper.rb b/app/helpers/dropdowns_helper.rb
index 64c5fae7d96..772a5f79a4d 100644
--- a/app/helpers/dropdowns_helper.rb
+++ b/app/helpers/dropdowns_helper.rb
@@ -15,7 +15,10 @@ module DropdownsHelper
dropdown_output = dropdown_toggle_link(toggle_text, data_attr, options)
end
- dropdown_output << content_tag(:div, class: "dropdown-menu dropdown-select #{options[:dropdown_class] if options.key?(:dropdown_class)}") do
+ content_tag_options = { class: "dropdown-menu dropdown-select #{options[:dropdown_class] if options.key?(:dropdown_class)}" }
+ content_tag_options[:data] = { qa_selector: "#{options[:dropdown_qa_selector]}" } if options[:dropdown_qa_selector]
+
+ dropdown_output << content_tag(:div, content_tag_options) do
output = []
if options.key?(:title)
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index 5297112eef8..63b6197a04d 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -169,6 +169,10 @@ module ObjectStorage
object_store_options.connection.to_hash.deep_symbolize_keys
end
+ def consolidated_settings?
+ object_store_options.fetch('consolidated_settings', false)
+ end
+
def remote_store_path
object_store_options.remote_directory
end
@@ -196,7 +200,7 @@ module ObjectStorage
id = [CarrierWave.generate_cache_id, SecureRandom.hex].join('-')
upload_path = File.join(TMP_UPLOAD_PATH, id)
direct_upload = ObjectStorage::DirectUpload.new(self.object_store_credentials, remote_store_path, upload_path,
- has_length: has_length, maximum_size: maximum_size)
+ has_length: has_length, maximum_size: maximum_size, consolidated_settings: consolidated_settings?)
direct_upload.to_hash.merge(ID: id)
end
diff --git a/app/views/projects/protected_tags/_create_protected_tag.html.haml b/app/views/projects/protected_tags/_create_protected_tag.html.haml
index 7a7390efe51..d19a6401fc8 100644
--- a/app/views/projects/protected_tags/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/_create_protected_tag.html.haml
@@ -1,8 +1,9 @@
- content_for :create_access_levels do
- .create_access_levels-container{ data: { qa_selector: 'access_levels_content' } }
+ .create_access_levels-container
= dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-create wide',
dropdown_class: 'dropdown-menu-selectable capitalize-header',
+ dropdown_qa_selector: 'access_levels_content',
data: { field_name: 'protected_tag[create_access_levels_attributes][0][access_level]', input_id: 'create_access_levels_attributes', qa_selector: 'access_levels_dropdown' }})
= render 'projects/protected_tags/shared/create_protected_tag'
diff --git a/changelogs/unreleased/221184-rolling-28-day-deployments-metrics.yml b/changelogs/unreleased/221184-rolling-28-day-deployments-metrics.yml
new file mode 100644
index 00000000000..772b40854a3
--- /dev/null
+++ b/changelogs/unreleased/221184-rolling-28-day-deployments-metrics.yml
@@ -0,0 +1,5 @@
+---
+title: Rolling 28 day time period counter for deployments
+merge_request: 35493
+author:
+type: added
diff --git a/changelogs/unreleased/lm-resolve-timeout.yml b/changelogs/unreleased/lm-resolve-timeout.yml
new file mode 100644
index 00000000000..d4a34db9ea9
--- /dev/null
+++ b/changelogs/unreleased/lm-resolve-timeout.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve timeout in admin/jobs
+merge_request: 35385
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-enable-workhorse-s3-client-consolidated.yml b/changelogs/unreleased/sh-enable-workhorse-s3-client-consolidated.yml
new file mode 100644
index 00000000000..3289469af5f
--- /dev/null
+++ b/changelogs/unreleased/sh-enable-workhorse-s3-client-consolidated.yml
@@ -0,0 +1,5 @@
+---
+title: Enable S3 Workhorse client if consolidated object settings used
+merge_request: 35480
+author:
+type: added
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index c6b4bcc36d8..dbbc946eaa7 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -210,7 +210,6 @@ production: &base
## within the types (e.g. artifacts, lfs, etc.).
# object_store:
# enabled: false
- # remote_directory: artifacts # The bucket name
# proxy_download: false # Passthrough all downloads via GitLab instead of using Redirects to Object Storage
# connection:
# provider: AWS # Only AWS supported at the moment
diff --git a/config/object_store_settings.rb b/config/object_store_settings.rb
index 0cd8fc98fb2..d8e1939a346 100644
--- a/config/object_store_settings.rb
+++ b/config/object_store_settings.rb
@@ -109,6 +109,7 @@ class ObjectStoreSettings
# Map bucket (external name) -> remote_directory (internal representation)
target_config['remote_directory'] = target_config.delete('bucket')
+ target_config['consolidated_settings'] = true
section['object_store'] = target_config
end
end
@@ -120,7 +121,7 @@ class ObjectStoreSettings
# 2. The legacy settings are not defined
def use_consolidated_settings?
return false unless settings.dig('object_store', 'enabled')
- return false unless settings.dig('object_store', 'connection')
+ return false unless settings.dig('object_store', 'connection').present?
SUPPORTED_TYPES.each do |store|
# to_h is needed because something strange happens to
@@ -135,7 +136,8 @@ class ObjectStoreSettings
next unless section
return false if section.dig('object_store', 'enabled')
- return false if section.dig('object_store', 'connection')
+ # Omnibus defaults to an empty hash
+ return false if section.dig('object_store', 'connection').present?
end
true
diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md
index a31a6ddb3db..c0bc986379c 100644
--- a/doc/development/telemetry/usage_ping.md
+++ b/doc/development/telemetry/usage_ping.md
@@ -422,9 +422,12 @@ appear to be associated to any of the services running, since they all appear to
| `auto_devops_disabled` | `counts` | `configure` | | | Projects with Auto DevOps template disabled |
| `deploy_keys` | `counts` | | | | |
| `deployments` | `counts` | `release` | | | Total deployments |
+| `deployments` | `counts_monthly` | `release` | | | Total deployments last 28 days |
| `dast_jobs` | `counts` | | | | |
| `successful_deployments` | `counts` | `release` | | | Total successful deployments |
+| `successful_deployments` | `counts_monthly` | `release` | | | Total successful deployments last 28 days |
| `failed_deployments` | `counts` | `release` | | | Total failed deployments |
+| `failed_deployments` | `counts_monthly` | `release` | | | Total failed deployments last 28 days |
| `environments` | `counts` | `release` | | | Total available and stopped environments |
| `clusters` | `counts` | `configure` | | | Total GitLab Managed clusters both enabled and disabled |
| `clusters_enabled` | `counts` | `configure` | | | Total GitLab Managed clusters currently enabled |
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index b1953aab4fd..073592797f0 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -170,6 +170,9 @@ module Gitlab
def system_usage_data_monthly
{
counts_monthly: {
+ deployments: count(Deployment.where(last_28_days_time_period)),
+ successful_deployments: count(Deployment.success.where(last_28_days_time_period)),
+ failed_deployments: count(Deployment.failed.where(last_28_days_time_period)),
personal_snippets: count(PersonalSnippet.where(last_28_days_time_period)),
project_snippets: count(ProjectSnippet.where(last_28_days_time_period))
}.tap do |data|
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 5e0a4faeba8..1551548d9b4 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -92,12 +92,6 @@ module Gitlab
end
end
- def can_read_project?
- return false unless can_access_git?
-
- user.can?(:read_project, project)
- end
-
private
def permission_cache
diff --git a/lib/object_storage/direct_upload.rb b/lib/object_storage/direct_upload.rb
index f973114e035..76f92f62e9c 100644
--- a/lib/object_storage/direct_upload.rb
+++ b/lib/object_storage/direct_upload.rb
@@ -23,9 +23,9 @@ module ObjectStorage
MINIMUM_MULTIPART_SIZE = 5.megabytes
attr_reader :credentials, :bucket_name, :object_name
- attr_reader :has_length, :maximum_size
+ attr_reader :has_length, :maximum_size, :consolidated_settings
- def initialize(credentials, bucket_name, object_name, has_length:, maximum_size: nil)
+ def initialize(credentials, bucket_name, object_name, has_length:, maximum_size: nil, consolidated_settings: false)
unless has_length
raise ArgumentError, 'maximum_size has to be specified if length is unknown' unless maximum_size
end
@@ -35,6 +35,7 @@ module ObjectStorage
@object_name = object_name
@has_length = has_length
@maximum_size = maximum_size
+ @consolidated_settings = consolidated_settings
end
def to_hash
@@ -80,10 +81,12 @@ module ObjectStorage
end
def use_workhorse_s3_client?
- Feature.enabled?(:use_workhorse_s3_client, default_enabled: true) &&
- credentials.fetch(:use_iam_profile, false) &&
- # The Golang AWS SDK does not support V2 signatures
- credentials.fetch(:aws_signature_version, 4).to_i >= 4
+ return false unless Feature.enabled?(:use_workhorse_s3_client, default_enabled: true)
+ return false unless credentials.fetch(:use_iam_profile, false) || consolidated_settings
+ # The Golang AWS SDK does not support V2 signatures
+ return false unless credentials.fetch(:aws_signature_version, 4).to_i >= 4
+
+ true
end
def provider
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d8bbaa33b40..e2891e57cc5 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1905,9 +1905,6 @@ msgid_plural "Alerts"
msgstr[0] ""
msgstr[1] ""
-msgid "AlertManagement| assign yourself"
-msgstr ""
-
msgid "AlertManagement|Acknowledged"
msgstr ""
@@ -1932,15 +1929,9 @@ msgstr ""
msgid "AlertManagement|All alerts"
msgstr ""
-msgid "AlertManagement|Assign To"
-msgstr ""
-
msgid "AlertManagement|Assign status"
msgstr ""
-msgid "AlertManagement|Assignee"
-msgstr ""
-
msgid "AlertManagement|Assignees"
msgstr ""
@@ -1980,9 +1971,6 @@ msgstr ""
msgid "AlertManagement|More information"
msgstr ""
-msgid "AlertManagement|No Matching Results"
-msgstr ""
-
msgid "AlertManagement|No alert data to display."
msgstr ""
@@ -1995,9 +1983,6 @@ msgstr ""
msgid "AlertManagement|None"
msgstr ""
-msgid "AlertManagement|None -"
-msgstr ""
-
msgid "AlertManagement|Open"
msgstr ""
@@ -3077,6 +3062,9 @@ msgstr ""
msgid "Assign Iteration"
msgstr ""
+msgid "Assign To"
+msgstr ""
+
msgid "Assign custom color like #FF0000"
msgstr ""
@@ -15193,6 +15181,9 @@ msgstr ""
msgid "No Epic"
msgstr ""
+msgid "No Matching Results"
+msgstr ""
+
msgid "No Scopes"
msgstr ""
@@ -24548,6 +24539,9 @@ msgstr ""
msgid "Unassign from commenting user"
msgstr ""
+msgid "Unassigned"
+msgstr ""
+
msgid "Unblock"
msgstr ""
diff --git a/qa/qa/page/project/settings/protected_tags.rb b/qa/qa/page/project/settings/protected_tags.rb
index 0b9765dd9ea..bf8f349cfd5 100644
--- a/qa/qa/page/project/settings/protected_tags.rb
+++ b/qa/qa/page/project/settings/protected_tags.rb
@@ -26,6 +26,8 @@ module QA
end
def choose_access_level_role(role)
+ return if find_element(:access_levels_dropdown).text == role
+
click_element :access_levels_dropdown
within_element(:access_levels_content) do
click_on role
diff --git a/spec/controllers/admin/jobs_controller_spec.rb b/spec/controllers/admin/jobs_controller_spec.rb
new file mode 100644
index 00000000000..2d1482f40d4
--- /dev/null
+++ b/spec/controllers/admin/jobs_controller_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::JobsController do
+ describe 'GET #index' do
+ context 'with an authenticated admin user' do
+ it 'paginates builds without a total count', :aggregate_failures do
+ stub_const("Admin::JobsController::BUILDS_PER_PAGE", 1)
+
+ sign_in(create(:admin))
+ create_list(:ci_build, 2)
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:builds)).to be_a(Kaminari::PaginatableWithoutCount)
+ expect(assigns(:builds).count).to be(1)
+ end
+ end
+
+ context 'without admin access' do
+ it 'returns `not_found`' do
+ sign_in(create(:user))
+
+ get :index
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index 42046464213..2aab9764560 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -7,7 +7,7 @@ FactoryBot.define do
tag { false }
user { nil }
project { nil }
- deployable { association :ci_build, environment: environment.name, project: environment.project }
+ deployable { association :ci_build, environment: environment.name, pipeline: association(:ci_pipeline, project: environment.project) }
environment factory: :environment
after(:build) do |deployment, evaluator|
diff --git a/spec/factories/usage_data.rb b/spec/factories/usage_data.rb
index dcc0b6acb0c..92d6e8d3062 100644
--- a/spec/factories/usage_data.rb
+++ b/spec/factories/usage_data.rb
@@ -5,7 +5,8 @@ FactoryBot.define do
skip_create # non-model factories (i.e. without #save)
initialize_with do
- projects = create_list(:project, 4)
+ projects = create_list(:project, 3)
+ projects << create(:project, :repository)
create(:board, project: projects[0])
create(:jira_service, project: projects[0])
create(:jira_service, :without_properties_callback, project: projects[1])
@@ -91,7 +92,11 @@ FactoryBot.define do
ProjectFeature.first.update_attribute('repository_access_level', 0)
# Create fresh & a month (28-days SMAU) old data
+ env = create(:environment, project: projects[3])
[2, 29].each do |n|
+ deployment_options = { created_at: n.days.ago, project: env.project, environment: env }
+ create(:deployment, :failed, deployment_options)
+ create(:deployment, :success, deployment_options)
create_list(:project_snippet, 2, project: projects[0], created_at: n.days.ago)
create(:personal_snippet, created_at: n.days.ago)
end
diff --git a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
index b81c0e49538..e7eb4bb41cc 100644
--- a/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
+++ b/spec/features/merge_request/user_suggests_changes_on_diff_spec.rb
@@ -155,7 +155,7 @@ RSpec.describe 'User comments on a diff', :js do
end
end
- it 'can apply multiple suggestions as a batch' do
+ it 'can apply multiple suggestions as a batch', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/224100' do
files.each_with_index do |file, index|
page.within("[id='#{file[:hash]}']") do
find("button[title='Show full file']").click
diff --git a/spec/helpers/notify_helper_spec.rb b/spec/helpers/notify_helper_spec.rb
index 5b2a06b11e9..9c9d745cb53 100644
--- a/spec/helpers/notify_helper_spec.rb
+++ b/spec/helpers/notify_helper_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-describe NotifyHelper do
+RSpec.describe NotifyHelper do
include ActionView::Helpers::UrlHelper
describe 'merge_request_reference_link' do
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 77a2c824fcb..149db85a9b2 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -130,7 +130,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:counts_monthly]).to be_an(Hash)
end
- it 'gathers projects data correctly' do
+ it 'gathers usage counts correctly' do
count_data = subject[:counts]
expect(count_data[:projects]).to eq(4)
@@ -188,6 +188,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:clusters_applications_jupyter]).to eq(1)
expect(count_data[:clusters_management_project]).to eq(1)
+ expect(count_data[:deployments]).to eq(4)
+ expect(count_data[:successful_deployments]).to eq(2)
+ expect(count_data[:failed_deployments]).to eq(2)
expect(count_data[:snippets]).to eq(6)
expect(count_data[:personal_snippets]).to eq(2)
expect(count_data[:project_snippets]).to eq(4)
@@ -274,9 +277,12 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.system_usage_data_monthly }
- it 'gathers projects data correctly' do
+ it 'gathers monthly usage counts correctly' do
counts_monthly = subject[:counts_monthly]
+ expect(counts_monthly[:deployments]).to eq(2)
+ expect(counts_monthly[:successful_deployments]).to eq(1)
+ expect(counts_monthly[:failed_deployments]).to eq(1)
expect(counts_monthly[:snippets]).to eq(3)
expect(counts_monthly[:personal_snippets]).to eq(1)
expect(counts_monthly[:project_snippets]).to eq(2)
diff --git a/spec/lib/object_storage/direct_upload_spec.rb b/spec/lib/object_storage/direct_upload_spec.rb
index e7d8b1de34e..1c1455e2456 100644
--- a/spec/lib/object_storage/direct_upload_spec.rb
+++ b/spec/lib/object_storage/direct_upload_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe ObjectStorage::DirectUpload do
let(:region) { 'us-east-1' }
let(:path_style) { false }
let(:use_iam_profile) { false }
+ let(:consolidated_settings) { false }
let(:credentials) do
{
provider: 'AWS',
@@ -23,7 +24,7 @@ RSpec.describe ObjectStorage::DirectUpload do
let(:object_name) { 'tmp/uploads/my-file' }
let(:maximum_size) { 1.gigabyte }
- let(:direct_upload) { described_class.new(credentials, bucket_name, object_name, has_length: has_length, maximum_size: maximum_size) }
+ let(:direct_upload) { described_class.new(credentials, bucket_name, object_name, has_length: has_length, maximum_size: maximum_size, consolidated_settings: consolidated_settings) }
before do
Fog.unmock!
@@ -141,6 +142,14 @@ RSpec.describe ObjectStorage::DirectUpload do
expect(subject[:UseWorkhorseClient]).to eq(use_iam_profile)
end
end
+
+ context 'when consolidated settings are used' do
+ let(:consolidated_settings) { true }
+
+ it 'enables the Workhorse client' do
+ expect(subject[:UseWorkhorseClient]).to be true
+ end
+ end
end
shared_examples 'a valid Google upload' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index c0712755396..c2c8b98df25 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -214,7 +214,7 @@ RSpec.describe User do
describe 'validations' do
describe 'password' do
- let!(:user) { create(:user) }
+ let!(:user) { build_stubbed(:user) }
before do
allow(Devise).to receive(:password_length).and_return(8..128)