Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-07-03 12:08:53 +00:00
parent 1c75400c24
commit b922b2f47a
24 changed files with 145 additions and 65 deletions

View file

@ -11,7 +11,7 @@ import {
GlSprintf,
} from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { s__ } from '~/locale';
import { s__, __ } from '~/locale';
import alertSetAssignees from '../../graphql/mutations/alert_set_assignees.graphql';
import SidebarAssignee from './sidebar_assignee.vue';
import { debounce } from 'lodash';
@ -19,15 +19,18 @@ import { debounce } from 'lodash';
const DATA_REFETCH_DELAY = 250;
export default {
FETCH_USERS_ERROR: s__(
'AlertManagement|There was an error while updating the assignee(s) list. Please try again.',
),
UPDATE_ALERT_ASSIGNEES_ERROR: s__(
'AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again.',
),
UPDATE_ALERT_ASSIGNEES_GRAPHQL_ERROR: s__(
'AlertManagement|This assignee cannot be assigned to this alert.',
),
i18n: {
FETCH_USERS_ERROR: s__(
'AlertManagement|There was an error while updating the assignee(s) list. Please try again.',
),
UPDATE_ALERT_ASSIGNEES_ERROR: s__(
'AlertManagement|There was an error while updating the assignee(s) of the alert. Please try again.',
),
UPDATE_ALERT_ASSIGNEES_GRAPHQL_ERROR: s__(
'AlertManagement|This assignee cannot be assigned to this alert.',
),
ASSIGNEES_BLOCK: s__('AlertManagement|Alert assignee(s): %{assignees}'),
},
components: {
GlIcon,
GlDropdown,
@ -80,7 +83,7 @@ export default {
return this.alert?.assignees?.nodes[0]?.username;
},
assignedUser() {
return this.userName || s__('AlertManagement|None');
return this.userName || __('None');
},
sortedUsers() {
return this.users
@ -142,7 +145,7 @@ export default {
this.users = data;
})
.catch(() => {
this.$emit('alert-error', this.$options.FETCH_USERS_ERROR);
this.$emit('alert-error', this.$options.i18n.FETCH_USERS_ERROR);
})
.finally(() => {
this.isDropdownSearching = false;
@ -165,14 +168,14 @@ export default {
if (errors[0]) {
return this.$emit(
'alert-sidebar-error',
`${this.$options.UPDATE_ALERT_ASSIGNEES_GRAPHQL_ERROR} ${errors[0]}.`,
`${this.$options.i18n.UPDATE_ALERT_ASSIGNEES_GRAPHQL_ERROR} ${errors[0]}.`,
);
}
return this.$emit('alert-refresh');
})
.catch(() => {
this.$emit('alert-error', this.$options.UPDATE_ALERT_ASSIGNEES_ERROR);
this.$emit('alert-error', this.$options.i18n.UPDATE_ALERT_ASSIGNEES_ERROR);
})
.finally(() => {
this.isUpdating = false;
@ -189,7 +192,7 @@ export default {
<gl-loading-icon v-if="isUpdating" />
</div>
<gl-tooltip :target="() => $refs.status" boundary="viewport" placement="left">
<gl-sprintf :message="s__('AlertManagement|Alert assignee(s): %{assignees}')">
<gl-sprintf :message="$options.i18n.ASSIGNEES_BLOCK">
<template #assignees>
{{ assignedUser }}
</template>
@ -198,7 +201,7 @@ export default {
<div class="hide-collapsed">
<p class="title gl-display-flex gl-justify-content-space-between">
{{ s__('AlertManagement|Assignee') }}
{{ __('Assignee') }}
<a
v-if="isEditable"
ref="editButton"
@ -207,7 +210,7 @@ export default {
@click="toggleFormDropdown"
@keydown.esc="hideDropdown"
>
{{ s__('AlertManagement|Edit') }}
{{ __('Edit') }}
</a>
</p>
@ -222,7 +225,7 @@ export default {
@hide="hideDropdown"
>
<div class="dropdown-title">
<span class="alert-title">{{ s__('AlertManagement|Assign To') }}</span>
<span class="alert-title">{{ __('Assign To') }}</span>
<gl-button
:aria-label="__('Close')"
variant="link"
@ -247,12 +250,12 @@ export default {
active-class="is-active"
@click="updateAlertAssignees('')"
>
{{ s__('AlertManagement|Unassigned') }}
{{ __('Unassigned') }}
</gl-dropdown-item>
<gl-dropdown-divider />
<gl-dropdown-header class="mt-0">
{{ s__('AlertManagement|Assignee') }}
{{ __('Assignee') }}
</gl-dropdown-header>
<sidebar-assignee
v-for="user in sortedUsers"
@ -263,7 +266,7 @@ export default {
/>
</template>
<gl-dropdown-item v-else-if="userListEmpty">
{{ s__('AlertManagement|No Matching Results') }}
{{ __('No Matching Results') }}
</gl-dropdown-item>
<gl-loading-icon v-else />
</div>
@ -276,7 +279,7 @@ export default {
assignedUser
}}</span>
<span v-else class="gl-display-flex gl-align-items-center">
{{ s__('AlertManagement|None -') }}
{{ __('None') }} -
<gl-button
class="gl-pl-2"
href="#"
@ -284,7 +287,7 @@ export default {
data-testid="unassigned-users"
@click="updateAlertAssignees(currentUser)"
>
{{ s__('AlertManagement| assign yourself') }}
{{ __('assign yourself') }}
</gl-button>
</span>
</p>

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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'

View file

@ -0,0 +1,5 @@
---
title: Rolling 28 day time period counter for deployments
merge_request: 35493
author:
type: added

View file

@ -0,0 +1,5 @@
---
title: Resolve timeout in admin/jobs
merge_request: 35385
author:
type: fixed

View file

@ -0,0 +1,5 @@
---
title: Enable S3 Workhorse client if consolidated object settings used
merge_request: 35480
author:
type: added

View file

@ -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

View file

@ -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

View file

@ -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 |

View file

@ -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|

View file

@ -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

View file

@ -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

View file

@ -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 ""

View file

@ -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

View file

@ -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

View file

@ -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|

View file

@ -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

View file

@ -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

View file

@ -2,7 +2,7 @@
require 'spec_helper'
describe NotifyHelper do
RSpec.describe NotifyHelper do
include ActionView::Helpers::UrlHelper
describe 'merge_request_reference_link' do

View file

@ -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)

View file

@ -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

View file

@ -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)