Commit 5a1541a4 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@13-9-stable-ee

parent f1bc6c9f
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import { GlAlert, GlFormCheckbox, GlLink } from '@gitlab/ui'; import { GlAlert, GlFormCheckbox, GlLink } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import UpdateKeepLatestArtifactProjectSetting from './graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql'; import UpdateKeepLatestArtifactProjectSetting from './graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql';
import GetKeepLatestArtifactApplicationSetting from './graphql/queries/get_keep_latest_artifact_application_setting.query.graphql';
import GetKeepLatestArtifactProjectSetting from './graphql/queries/get_keep_latest_artifact_project_setting.query.graphql'; import GetKeepLatestArtifactProjectSetting from './graphql/queries/get_keep_latest_artifact_project_setting.query.graphql';
export default { export default {
...@@ -14,7 +13,6 @@ export default { ...@@ -14,7 +13,6 @@ export default {
enabledHelpText: __( enabledHelpText: __(
'The latest artifacts created by jobs in the most recent successful pipeline will be stored.', 'The latest artifacts created by jobs in the most recent successful pipeline will be stored.',
), ),
disabledHelpText: __('This feature is disabled at the instance level.'),
helpLinkText: __('More information'), helpLinkText: __('More information'),
checkboxText: __('Keep artifacts from most recent successful jobs'), checkboxText: __('Keep artifacts from most recent successful jobs'),
}, },
...@@ -46,19 +44,12 @@ export default { ...@@ -46,19 +44,12 @@ export default {
this.reportError(this.$options.errors.fetchError); this.reportError(this.$options.errors.fetchError);
}, },
}, },
projectSettingDisabled: {
query: GetKeepLatestArtifactApplicationSetting,
update(data) {
return !data.ciApplicationSettings?.keepLatestArtifact;
},
},
}, },
data() { data() {
return { return {
keepLatestArtifact: null, keepLatestArtifact: null,
errorMessage: '', errorMessage: '',
isAlertDismissed: false, isAlertDismissed: false,
projectSettingDisabled: true,
}; };
}, },
computed: { computed: {
...@@ -66,9 +57,7 @@ export default { ...@@ -66,9 +57,7 @@ export default {
return this.errorMessage && !this.isAlertDismissed; return this.errorMessage && !this.isAlertDismissed;
}, },
helpText() { helpText() {
return this.projectSettingDisabled return this.$options.i18n.enabledHelpText;
? this.$options.i18n.disabledHelpText
: this.$options.i18n.enabledHelpText;
}, },
}, },
methods: { methods: {
...@@ -106,10 +95,7 @@ export default { ...@@ -106,10 +95,7 @@ export default {
@dismiss="isAlertDismissed = true" @dismiss="isAlertDismissed = true"
>{{ errorMessage }}</gl-alert >{{ errorMessage }}</gl-alert
> >
<gl-form-checkbox <gl-form-checkbox v-model="keepLatestArtifact" @change="updateSetting"
v-model="keepLatestArtifact"
:disabled="projectSettingDisabled"
@change="updateSetting"
><strong class="gl-mr-3">{{ $options.i18n.checkboxText }}</strong> ><strong class="gl-mr-3">{{ $options.i18n.checkboxText }}</strong>
<gl-link :href="helpPagePath">{{ $options.i18n.helpLinkText }}</gl-link> <gl-link :href="helpPagePath">{{ $options.i18n.helpLinkText }}</gl-link>
<template v-if="!$apollo.loading" #help>{{ helpText }}</template> <template v-if="!$apollo.loading" #help>{{ helpText }}</template>
......
...@@ -15,7 +15,6 @@ export default function initClonePanel() { ...@@ -15,7 +15,6 @@ export default function initClonePanel() {
} }
$('a', $cloneOptions).on('click', (e) => { $('a', $cloneOptions).on('click', (e) => {
e.preventDefault();
const $this = $(e.currentTarget); const $this = $(e.currentTarget);
const url = $this.attr('href'); const url = $this.attr('href');
if (url && (url.startsWith('vscode://') || url.startsWith('xcode://'))) { if (url && (url.startsWith('vscode://') || url.startsWith('xcode://'))) {
......
...@@ -368,7 +368,7 @@ export default { ...@@ -368,7 +368,7 @@ export default {
<alert-details-table :alert="alert" :loading="loading" /> <alert-details-table :alert="alert" :loading="loading" />
</gl-tab> </gl-tab>
<gl-tab <gl-tab
v-if="isThreatMonitoringPage" v-if="!isThreatMonitoringPage"
:data-testid="$options.tabsConfig[1].id" :data-testid="$options.tabsConfig[1].id"
:title="$options.tabsConfig[1].title" :title="$options.tabsConfig[1].title"
> >
......
...@@ -280,7 +280,7 @@ module ApplicationHelper ...@@ -280,7 +280,7 @@ module ApplicationHelper
def page_class def page_class
class_names = [] class_names = []
class_names << 'issue-boards-page gl-overflow-hidden' if current_controller?(:boards) class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
class_names << 'environment-logs-page' if current_controller?(:logs) class_names << 'environment-logs-page' if current_controller?(:logs)
class_names << 'with-performance-bar' if performance_bar_enabled? class_names << 'with-performance-bar' if performance_bar_enabled?
class_names << system_message_class class_names << system_message_class
......
...@@ -43,7 +43,7 @@ class Repository ...@@ -43,7 +43,7 @@ class Repository
changelog license_blob license_key gitignore changelog license_blob license_key gitignore
gitlab_ci_yml branch_names tag_names branch_count gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref merged_branch_names tag_count avatar exists? root_ref merged_branch_names
has_visible_content? issue_template_names_by_category merge_request_template_names_by_category has_visible_content? issue_template_names_hash merge_request_template_names_hash
user_defined_metrics_dashboard_paths xcode_project? has_ambiguous_refs?).freeze user_defined_metrics_dashboard_paths xcode_project? has_ambiguous_refs?).freeze
# Methods that use cache_method but only memoize the value # Methods that use cache_method but only memoize the value
...@@ -60,8 +60,8 @@ class Repository ...@@ -60,8 +60,8 @@ class Repository
gitignore: :gitignore, gitignore: :gitignore,
gitlab_ci: :gitlab_ci_yml, gitlab_ci: :gitlab_ci_yml,
avatar: :avatar, avatar: :avatar,
issue_template: :issue_template_names_by_category, issue_template: :issue_template_names_hash,
merge_request_template: :merge_request_template_names_by_category, merge_request_template: :merge_request_template_names_hash,
metrics_dashboard: :user_defined_metrics_dashboard_paths, metrics_dashboard: :user_defined_metrics_dashboard_paths,
xcode_config: :xcode_project? xcode_config: :xcode_project?
}.freeze }.freeze
...@@ -573,15 +573,15 @@ class Repository ...@@ -573,15 +573,15 @@ class Repository
cache_method :avatar cache_method :avatar
# store issue_template_names as hash # store issue_template_names as hash
def issue_template_names_by_category def issue_template_names_hash
Gitlab::Template::IssueTemplate.repository_template_names(project) Gitlab::Template::IssueTemplate.repository_template_names(project)
end end
cache_method :issue_template_names_by_category, fallback: {} cache_method :issue_template_names_hash, fallback: {}
def merge_request_template_names_by_category def merge_request_template_names_hash
Gitlab::Template::MergeRequestTemplate.repository_template_names(project) Gitlab::Template::MergeRequestTemplate.repository_template_names(project)
end end
cache_method :merge_request_template_names_by_category, fallback: {} cache_method :merge_request_template_names_hash, fallback: {}
def user_defined_metrics_dashboard_paths def user_defined_metrics_dashboard_paths
Gitlab::Metrics::Dashboard::RepoDashboardFinder.list_dashboards(project) Gitlab::Metrics::Dashboard::RepoDashboardFinder.list_dashboards(project)
......
...@@ -5,6 +5,12 @@ module Issues ...@@ -5,6 +5,12 @@ module Issues
include Gitlab::Routing.url_helpers include Gitlab::Routing.url_helpers
include GitlabRoutingHelper include GitlabRoutingHelper
def initialize(issuables_relation, project)
super
@labels = @issuables.labels_hash.transform_values { |labels| labels.sort.join(',').presence }
end
def email(user) def email(user)
Notify.issues_csv_email(user, project, csv_data, csv_builder.status).deliver_now Notify.issues_csv_email(user, project, csv_data, csv_builder.status).deliver_now
end end
...@@ -12,7 +18,7 @@ module Issues ...@@ -12,7 +18,7 @@ module Issues
private private
def associations_to_preload def associations_to_preload
%i(author assignees timelogs milestone) %i(author assignees timelogs milestone project)
end end
def header_to_value_hash def header_to_value_hash
...@@ -41,7 +47,7 @@ module Issues ...@@ -41,7 +47,7 @@ module Issues
end end
def issue_labels(issue) def issue_labels(issue)
issuables.labels_hash[issue.id].sort.join(',').presence @labels[issue.id]
end end
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
......
...@@ -45,16 +45,17 @@ ...@@ -45,16 +45,17 @@
.settings-content .settings-content
= render 'projects/runners/index' = render 'projects/runners/index'
%section.settings.no-animate#js-artifacts-settings{ class: ('expanded' if expanded) } - if Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact?
.settings-header %section.settings.no-animate#js-artifacts-settings{ class: ('expanded' if expanded) }
%h4 .settings-header
= _("Artifacts") %h4
%button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' } = _("Artifacts")
= expanded ? _('Collapse') : _('Expand') %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
%p = expanded ? _('Collapse') : _('Expand')
= _("A job artifact is an archive of files and directories saved by a job when it finishes.") %p
.settings-content = _("A job artifact is an archive of files and directories saved by a job when it finishes.")
#js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } } .settings-content
#js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
%section.qa-variables-settings.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { qa_selector: 'variables_settings_content' } } %section.qa-variables-settings.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { qa_selector: 'variables_settings_content' } }
.settings-header .settings-header
......
...@@ -36,7 +36,7 @@ start_foreground() ...@@ -36,7 +36,7 @@ start_foreground()
stop() stop()
{ {
get_puma_pid get_puma_pid
kill -QUIT "$(get_puma_pid)" kill -INT "$(get_puma_pid)"
} }
reload() reload()
......
...@@ -36,7 +36,7 @@ start_foreground() ...@@ -36,7 +36,7 @@ start_foreground()
stop() stop()
{ {
get_puma_pid get_puma_pid
kill -QUIT "$(get_puma_pid)" kill -INT "$(get_puma_pid)"
} }
reload() reload()
......
---
title: Fix Metric tab not showing up on operations page
merge_request: 54736
author:
type: fixed
---
title: Fix creating the idx_on_issues_where_service_desk_reply_to_is_not_null index
before the post migration
merge_request: 54346
author:
type: other
---
title: Fix keep latest artifacts checkbox being always disabled
merge_request: 54669
author:
type: fixed
---
title: Updates authorization for linting endpoint
merge_request: 54492
author:
type: changed
---
title: Restore missing horizontal scrollbar on issue boards
merge_request: 54634
author:
type: fixed
---
title: Send SIGINT instead of SIGQUIT to puma
merge_request: 54446
author: Jörg Behrmann @behrmann
type: fixed
---
title: Reset description template names cache key to reload an updated templates structure
merge_request: 54614
author:
type: fixed
---
title: Fix S3 object storage failing when endpoint is not specified
merge_request: 54868
author:
type: fixed
---
title: Fix N+1 SQL regression in exporting issues to CSV
merge_request: 54287
author:
type: performance
This diff is collapsed.
# frozen_string_literal: true
class AddServiceDeskReplyToIsNotNullIndexOnIssuesFix < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'idx_on_issues_where_service_desk_reply_to_is_not_null'
disable_ddl_transaction!
def up
add_concurrent_index(:issues, [:id], name: INDEX_NAME, where: 'service_desk_reply_to IS NOT NULL')
end
def down
remove_concurrent_index_by_name(:issues, INDEX_NAME)
end
end
# frozen_string_literal: true # frozen_string_literal: true
class AddServiceDeskReplyToIsNotNullIndexOnIssues < ActiveRecord::Migration[6.0] class AddServiceDeskReplyToIsNotNullIndexOnIssues < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false DOWNTIME = false
INDEX_NAME = 'idx_on_issues_where_service_desk_reply_to_is_not_null'
disable_ddl_transaction!
def up
add_concurrent_index(:issues, [:id], name: INDEX_NAME, where: 'service_desk_reply_to IS NOT NULL')
end
def down def change
remove_concurrent_index_by_name(:issues, INDEX_NAME) # no-op, the migration's version number was lowered to be executed earlier than db/post_migrate/20201128210234_schedule_populate_issue_email_participants.rb
#
# The new migration is located here: db/migrate/20201128210000_add_service_desk_reply_to_is_not_null_index_on_issues_fix.rb
end end
end end
2f7415e3e3e66f326f2f65c38406c2103d5075493c86a836497c3541655f4e86
\ No newline at end of file
...@@ -11,7 +11,7 @@ module API ...@@ -11,7 +11,7 @@ module API
optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response' optional :include_merged_yaml, type: Boolean, desc: 'Whether or not to include merged CI config yaml in the response'
end end
post '/lint' do post '/lint' do
unauthorized! unless Gitlab::CurrentSettings.signup_enabled? && current_user unauthorized! if Gitlab::CurrentSettings.signup_disabled? && current_user.nil?
result = Gitlab::Ci::YamlProcessor.new(params[:content], user: current_user).execute result = Gitlab::Ci::YamlProcessor.new(params[:content], user: current_user).execute
......
...@@ -3,6 +3,10 @@ ...@@ -3,6 +3,10 @@
module Gitlab module Gitlab
module CurrentSettings module CurrentSettings
class << self class << self
def signup_disabled?
!signup_enabled?
end
def current_application_settings def current_application_settings
Gitlab::SafeRequestStore.fetch(:current_application_settings) { ensure_application_settings! } Gitlab::SafeRequestStore.fetch(:current_application_settings) { ensure_application_settings! }
end end
......
...@@ -42,7 +42,7 @@ module Gitlab ...@@ -42,7 +42,7 @@ module Gitlab
def ensure_repository_does_not_exist! def ensure_repository_does_not_exist!
if repository.exists? if repository.exists?
shared.logger.info( shared.logger.info(
message: %Q{Deleting existing "#{repository.path}" to re-import it.} message: %Q{Deleting existing "#{repository.disk_path}" to re-import it.}
) )
Repositories::DestroyService.new(repository).execute Repositories::DestroyService.new(repository).execute
......
...@@ -108,7 +108,7 @@ module Gitlab ...@@ -108,7 +108,7 @@ module Gitlab
# Gitaly the actual template names within a given project's repository for all file templates # Gitaly the actual template names within a given project's repository for all file templates
# other than `issue` and `merge request` description templates, which would instead # other than `issue` and `merge request` description templates, which would instead
# overwrite the `template_names` method to return a redis cached version, by reading cached values # overwrite the `template_names` method to return a redis cached version, by reading cached values
# from `repository.issue_template_names_by_category` and `repository.merge_request_template_names_by_category` # from `repository.issue_template_names_hash` and `repository.merge_request_template_names_hash`
# methods. # methods.
def repository_template_names(project) def repository_template_names(project)
template_names_by_category(self.all(project)) template_names_by_category(self.all(project))
......
...@@ -23,7 +23,7 @@ module Gitlab ...@@ -23,7 +23,7 @@ module Gitlab
# own caching mechanism to avoid the back and forth call jumps between finder and model. # own caching mechanism to avoid the back and forth call jumps between finder and model.
# #
# follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279 # follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279
project.repository.issue_template_names_by_category project.repository.issue_template_names_hash
end end
end end
end end
......
...@@ -23,7 +23,7 @@ module Gitlab ...@@ -23,7 +23,7 @@ module Gitlab
# own caching mechanism to avoid the back and forth call jumps between finder and model. # own caching mechanism to avoid the back and forth call jumps between finder and model.
# #
# follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279 # follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300279
project.repository.merge_request_template_names_by_category project.repository.merge_request_template_names_hash
end end
end end
end end
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
module ObjectStorage module ObjectStorage
class Config class Config
include Gitlab::Utils::StrongMemoize
AWS_PROVIDER = 'AWS' AWS_PROVIDER = 'AWS'
AZURE_PROVIDER = 'AzureRM' AZURE_PROVIDER = 'AzureRM'
GOOGLE_PROVIDER = 'Google' GOOGLE_PROVIDER = 'Google'
...@@ -68,36 +66,6 @@ module ObjectStorage ...@@ -68,36 +66,6 @@ module ObjectStorage
def provider def provider
credentials[:provider].to_s credentials[:provider].to_s
end end
# This method converts fog-aws parameters to an endpoint for the
# Workhorse S3 client.
def s3_endpoint
strong_memoize(:s3_endpoint) do
# We could omit this line and let the following code handle this, but
# this will ensure that working configurations that use `endpoint`
# will continue to work.
next credentials[:endpoint] if credentials[:endpoint].present?
generate_s3_endpoint_from_credentials
end
end
def generate_s3_endpoint_from_credentials
# fog-aws has special handling of the host, region, scheme, etc:
# https://github.com/fog/fog-aws/blob/c7a11ba377a76d147861d0e921eb1e245bc11b6c/lib/fog/aws/storage.rb#L440-L449
# Rather than reimplement this, we derive it from a sample GET URL.
url = fog_connection.get_object_url(bucket, "tmp", nil)
uri = ::Addressable::URI.parse(url)
return unless uri&.scheme && uri&.host
endpoint = "#{uri.scheme}://#{uri.host}"
endpoint += ":#{uri.port}" if uri.port
endpoint
rescue ::URI::InvalidComponentError, ::Addressable::URI::InvalidURIError => e
Gitlab::ErrorTracking.track_exception(e)
nil
end
# End AWS-specific options # End AWS-specific options
# Begin Azure-specific options # Begin Azure-specific options
...@@ -123,10 +91,6 @@ module ObjectStorage ...@@ -123,10 +91,6 @@ module ObjectStorage
end end
end end
def fog_connection
@connection ||= ::Fog::Storage.new(credentials)
end
private private
# This returns a Hash of HTTP encryption headers to send along to S3. # This returns a Hash of HTTP encryption headers to send along to S3.
......
...@@ -80,7 +80,7 @@ module ObjectStorage ...@@ -80,7 +80,7 @@ module ObjectStorage
S3Config: { S3Config: {
Bucket: bucket_name, Bucket: bucket_name,
Region: credentials[:region], Region: credentials[:region],
Endpoint: config.s3_endpoint, Endpoint: credentials[:endpoint],
PathStyle: config.use_path_style?, PathStyle: config.use_path_style?,
UseIamProfile: config.use_iam_profile?, UseIamProfile: config.use_iam_profile?,
ServerSideEncryption: config.server_side_encryption, ServerSideEncryption: config.server_side_encryption,
...@@ -229,7 +229,7 @@ module ObjectStorage ...@@ -229,7 +229,7 @@ module ObjectStorage
end end
def connection def connection
config.fog_connection @connection ||= ::Fog::Storage.new(credentials)
end end
end end
end end
...@@ -30012,9 +30012,6 @@ msgstr "" ...@@ -30012,9 +30012,6 @@ msgstr ""
msgid "This epic does not exist or you don't have sufficient permission." msgid "This epic does not exist or you don't have sufficient permission."
msgstr "" msgstr ""
msgid "This feature is disabled at the instance level."
msgstr ""
msgid "This feature requires local storage to be enabled" msgid "This feature requires local storage to be enabled"
msgstr "" msgstr ""
......
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Keep latest artifact checkbox when application keep latest artifact setting is disabled checkbox is disabled when application setting is disabled 1`] = `
<div>
<!---->
<b-form-checkbox-stub
checked="true"
class="gl-form-checkbox"
disabled="true"
plain="true"
value="true"
>
<strong
class="gl-mr-3"
>
Keep artifacts from most recent successful jobs
</strong>
<gl-link-stub
href="/help/ci/pipelines/job_artifacts"
>
More information
</gl-link-stub>
<p
class="help-text"
>
This feature is disabled at the instance level.
</p>
</b-form-checkbox-stub>
</div>
`;
exports[`Keep latest artifact checkbox when application keep latest artifact setting is enabled sets correct setting value in checkbox with query result 1`] = ` exports[`Keep latest artifact checkbox when application keep latest artifact setting is enabled sets correct setting value in checkbox with query result 1`] = `
<div> <div>
<!----> <!---->
......
...@@ -120,23 +120,4 @@ describe('Keep latest artifact checkbox', () => { ...@@ -120,23 +120,4 @@ describe('Keep latest artifact checkbox', () => {
expect(findCheckbox().attributes('disabled')).toBeUndefined(); expect(findCheckbox().attributes('disabled')).toBeUndefined();
}); });
}); });
describe('when application keep latest artifact setting is disabled', () => {
it('checkbox is disabled when application setting is disabled', async () => {
createComponent({
keepLatestArtifactApplicationQueryHandler: jest.fn().mockResolvedValue({
data: {
ciApplicationSettings: {
keepLatestArtifact: false,
},
},
}),
});
await wrapper.vm.$nextTick();
expect(wrapper.element).toMatchSnapshot();
expect(findCheckbox().attributes('disabled')).toBe('true');
});
});
}); });
...@@ -128,6 +128,10 @@ describe('AlertDetails', () => { ...@@ -128,6 +128,10 @@ describe('AlertDetails', () => {
expect(wrapper.findByTestId('startTimeItem').exists()).toBe(true); expect(wrapper.findByTestId('startTimeItem').exists()).toBe(true);
expect(wrapper.findByTestId('startTimeItem').props('time')).toBe(mockAlert.startedAt); expect(wrapper.findByTestId('startTimeItem').props('time')).toBe(mockAlert.startedAt);
}); });
it('renders the metrics tab', () => {
expect(findMetricsTab().exists()).toBe(true);
});
}); });
describe('individual alert fields', () => { describe('individual alert fields', () => {
...@@ -179,7 +183,8 @@ describe('AlertDetails', () => { ...@@ -179,7 +183,8 @@ describe('AlertDetails', () => {
describe('Threat Monitoring details', () => { describe('Threat Monitoring details', () => {
it('should not render the metrics tab', () => { it('should not render the metrics tab', () => {
mountComponent({ mountComponent({
data: { alert: mockAlert, provide: { isThreatMonitoringPage: true } }, data: { alert: mockAlert },
provide: { isThreatMonitoringPage: true },
}); });
expect(findMetricsTab().exists()).toBe(false); expect(findMetricsTab().exists()).toBe(false);
}); });
......
...@@ -24,6 +24,26 @@ RSpec.describe Gitlab::CurrentSettings do ...@@ -24,6 +24,26 @@ RSpec.describe Gitlab::CurrentSettings do
end end
end end
describe '.signup_disabled?' do
subject { described_class.signup_disabled? }
context 'when signup is enabled' do
before do
create(:application_setting, signup_enabled: true)
end
it { is_expected.to be_falsey }
end
context 'when signup is disabled' do
before do
create(:application_setting, signup_enabled: false)
end
it { is_expected.to be_truthy }
end
end
describe '#current_application_settings', :use_clean_rails_memory_store_caching do describe '#current_application_settings', :use_clean_rails_memory_store_caching do
it 'allows keys to be called directly' do it 'allows keys to be called directly' do
db_settings = create(:application_setting, db_settings = create(:application_setting,
......
...@@ -46,7 +46,7 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do ...@@ -46,7 +46,7 @@ RSpec.describe Gitlab::ImportExport::RepoRestorer do
context 'when the repository already exists' do context 'when the repository already exists' do
it 'deletes the existing repository before importing' do it 'deletes the existing repository before importing' do
allow(project.repository).to receive(:exists?).and_return(true) allow(project.repository).to receive(:exists?).and_return(true)
allow(project.repository).to receive(:path).and_return('repository_path') allow(project.repository).to receive(:disk_path).and_return('repository_path')
expect_next_instance_of(Repositories::DestroyService) do |instance| expect_next_instance_of(Repositories::DestroyService) do |instance|
expect(instance).to receive(:execute).and_call_original expect(instance).to receive(:execute).and_call_original
......
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper' require 'fast_spec_helper'
require 'rspec-parameterized' require 'rspec-parameterized'
require 'fog/core'
RSpec.describe ObjectStorage::Config do RSpec.describe ObjectStorage::Config do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
...@@ -33,9 +34,7 @@ RSpec.describe ObjectStorage::Config do ...@@ -33,9 +34,7 @@ RSpec.describe ObjectStorage::Config do
} }
end end
subject do subject { described_class.new(raw_config.as_json) }
described_class.new(raw_config.as_json)
end
describe '#load_provider' do describe '#load_provider' do
before do before do
...@@ -46,10 +45,6 @@ RSpec.describe ObjectStorage::Config do ...@@ -46,10 +45,6 @@ RSpec.describe ObjectStorage::Config do
it 'registers AWS as a provider' do it 'registers AWS as a provider' do
expect(Fog.providers.keys).to include(:aws) expect(Fog.providers.keys).to include(:aws)
end end
describe '#fog_connection' do
it { expect(subject.fog_connection).to be_a_kind_of(Fog::AWS::Storage::Real) }
end
end end
context 'with Google' do context 'with Google' do
...@@ -64,10 +59,6 @@ RSpec.describe ObjectStorage::Config do ...@@ -64,10 +59,6 @@ RSpec.describe ObjectStorage::Config do
it 'registers Google as a provider' do it 'registers Google as a provider' do
expect(Fog.providers.keys).to include(:google) expect(Fog.providers.keys).to include(:google)
end end
describe '#fog_connection' do
it { expect(subject.fog_connection).to be_a_kind_of(Fog::Storage::GoogleXML::Real) }
end
end end
context 'with Azure' do context 'with Azure' do
...@@ -82,10 +73,6 @@ RSpec.describe ObjectStorage::Config do ...@@ -82,10 +73,6 @@ RSpec.describe ObjectStorage::Config do
it 'registers AzureRM as a provider' do it 'registers AzureRM as a provider' do
expect(Fog.providers.keys).to include(:azurerm) expect(Fog.providers.keys).to include(:azurerm)
end end
describe '#fog_connection' do
it { expect(subject.fog_connection).to be_a_kind_of(Fog::Storage::AzureRM::Real) }
end
end end
end end
...@@ -183,50 +170,6 @@ RSpec.describe ObjectStorage::Config do ...@@ -183,50 +170,6 @@ RSpec.describe ObjectStorage::Config do
it { expect(subject.provider).to eq('AWS') } it { expect(subject.provider).to eq('AWS') }
it { expect(subject.aws?).to be true } it { expect(subject.aws?).to be true }
it { expect(subject.google?).to be false } it { expect(subject.google?).to be false }
it 'returns the default S3 endpoint' do
subject.load_provider
expect(subject.s3_endpoint).to eq("https://test-bucket.s3.amazonaws.com")
end
describe 'with a custom endpoint' do
let(:endpoint) { 'https://my.example.com' }
before do
credentials[:endpoint] = endpoint
end
it 'returns the custom endpoint' do
subject.load_provider
expect(subject.s3_endpoint).to eq(endpoint)
end
end
context 'with custom S3 host and port' do
where(:host, :port, :scheme, :expected) do
's3.example.com' | 8080 | nil | 'https://test-bucket.s3.example.com:8080'
's3.example.com' | 443 | nil | 'https://test-bucket.s3.example.com'
's3.example.com' | 443 | "https" | 'https://test-bucket.s3.example.com'
's3.example.com' | nil | nil | 'https://test-bucket.s3.example.com'
's3.example.com' | 80 | "http" | 'http://test-bucket.s3.example.com'
's3.example.com' | "bogus" | nil | nil
end
with_them do
before do
credentials[:host] = host
credentials[:port] = port
credentials[:scheme] = scheme
subject.load_provider
end
it 'returns expected host' do
expect(subject.s3_endpoint).to eq(expected)
end
end
end
end end
context 'with Google credentials' do context 'with Google credentials' do
......
...@@ -1949,8 +1949,8 @@ RSpec.describe Repository do ...@@ -1949,8 +1949,8 @@ RSpec.describe Repository do
:root_ref, :root_ref,
:merged_branch_names, :merged_branch_names,
:has_visible_content?, :has_visible_content?,
:issue_template_names_by_category, :issue_template_names_hash,
:merge_request_template_names_by_category, :merge_request_template_names_hash,
:user_defined_metrics_dashboard_paths, :user_defined_metrics_dashboard_paths,
:xcode_project?, :xcode_project?,
:has_ambiguous_refs? :has_ambiguous_refs?
......
...@@ -5,7 +5,9 @@ require 'spec_helper' ...@@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe API::Lint do RSpec.describe API::Lint do
describe 'POST /ci/lint' do describe 'POST /ci/lint' do
context 'when signup settings are disabled' do context 'when signup settings are disabled' do
Gitlab::CurrentSettings.signup_enabled = false before do
Gitlab::CurrentSettings.signup_enabled = false
end
context 'when unauthenticated' do context 'when unauthenticated' do
it 'returns authentication error' do it 'returns authentication error' do
...@@ -16,22 +18,25 @@ RSpec.describe API::Lint do ...@@ -16,22 +18,25 @@ RSpec.describe API::Lint do
end end
context 'when authenticated' do context 'when authenticated' do
it 'returns unauthorized error' do let_it_be(:api_user) { create(:user) }
post api('/ci/lint'), params: { content: 'content' } it 'returns authorized' do
post api('/ci/lint', api_user), params: { content: 'content' }
expect(response).to have_gitlab_http_status(:unauthorized) expect(response).to have_gitlab_http_status(:ok)
end end
end end
end end
context 'when signup settings are enabled' do context 'when signup settings are enabled' do
Gitlab::CurrentSettings.signup_enabled = true before do
Gitlab::CurrentSettings.signup_enabled = true
end
context 'when unauthenticated' do context 'when unauthenticated' do
it 'returns authentication error' do it 'returns authorized success' do
post api('/ci/lint'), params: { content: 'content' } post api('/ci/lint'), params: { content: 'content' }
expect(response).to have_gitlab_http_status(:unauthorized) expect(response).to have_gitlab_http_status(:ok)
end end
end end
......
...@@ -4,11 +4,11 @@ require 'spec_helper' ...@@ -4,11 +4,11 @@ require 'spec_helper'
RSpec.describe Issues::ExportCsvService do RSpec.describe Issues::ExportCsvService do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:group) { create(:group) } let_it_be(:group) { create(:group) }
let(:project) { create(:project, :public, group: group) } let_it_be(:project) { create(:project, :public, group: group) }
let!(:issue) { create(:issue, project: project, author: user) } let_it_be(:issue) { create(:issue, project: project, author: user) }
let!(:bad_issue) { create(:issue, project: project, author: user) } let_it_be(:bad_issue) { create(:issue, project: project, author: user) }
let(:subject) { described_class.new(Issue.all, project) } subject { described_class.new(Issue.all, project) }
it 'renders csv to string' do it 'renders csv to string' do
expect(subject.csv_data).to be_a String expect(subject.csv_data).to be_a String
...@@ -33,11 +33,11 @@ RSpec.describe Issues::ExportCsvService do ...@@ -33,11 +33,11 @@ RSpec.describe Issues::ExportCsvService do
end end
context 'includes' do context 'includes' do
let(:milestone) { create(:milestone, title: 'v1.0', project: project) } let_it_be(:milestone) { create(:milestone, title: 'v1.0', project: project) }
let(:idea_label) { create(:label, project: project, title: 'Idea') } let_it_be(:idea_label) { create(:label, project: project, title: 'Idea') }
let(:feature_label) { create(:label, project: project, title: 'Feature') } let_it_be(:feature_label) { create(:label, project: project, title: 'Feature') }
before do before_all do
# Creating a timelog touches the updated_at timestamp of issue, # Creating a timelog touches the updated_at timestamp of issue,
# so create these first. # so create these first.
issue.timelogs.create!(time_spent: 360, user: user) issue.timelogs.create!(time_spent: 360, user: user)
...@@ -60,6 +60,10 @@ RSpec.describe Issues::ExportCsvService do ...@@ -60,6 +60,10 @@ RSpec.describe Issues::ExportCsvService do
expect(csv.headers).to include('Title', 'Description') expect(csv.headers).to include('Title', 'Description')
end end
it 'returns two issues' do
expect(csv.count).to eq(2)
end
specify 'iid' do specify 'iid' do
expect(csv[0]['Issue ID']).to eq issue.iid.to_s expect(csv[0]['Issue ID']).to eq issue.iid.to_s
end end
...@@ -150,7 +154,7 @@ RSpec.describe Issues::ExportCsvService do ...@@ -150,7 +154,7 @@ RSpec.describe Issues::ExportCsvService do
end end
context 'with issues filtered by labels and project' do context 'with issues filtered by labels and project' do
let(:subject) do subject do
described_class.new( described_class.new(
IssuesFinder.new(user, IssuesFinder.new(user,
project_id: project.id, project_id: project.id,
...@@ -162,6 +166,27 @@ RSpec.describe Issues::ExportCsvService do ...@@ -162,6 +166,27 @@ RSpec.describe Issues::ExportCsvService do
expect(csv[0]['Issue ID']).to eq issue.iid.to_s expect(csv[0]['Issue ID']).to eq issue.iid.to_s
end end
end end
context 'with label links' do
let(:labeled_issues) { create_list(:labeled_issue, 2, project: project, author: user, labels: [feature_label, idea_label]) }
it 'does not run a query for each label link' do
control_count = ActiveRecord::QueryRecorder.new { csv }.count
labeled_issues
expect { csv }.not_to exceed_query_limit(control_count)
expect(csv.count).to eq(4)
end
it 'returns the labels in sorted order' do
labeled_issues
labeled_rows = csv.select { |entry| labeled_issues.map(&:iid).include?(entry['Issue ID'].to_i) }
expect(labeled_rows.count).to eq(2)
expect(labeled_rows.map { |entry| entry['Labels'] }).to all( eq("Feature,Idea") )
end
end
end end
context 'with minimal details' do context 'with minimal details' do
......
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