Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
45205f0db5
commit
8132e39e1b
|
|
@ -30,6 +30,7 @@ If applicable, any groups/projects that are happy to have this feature turned on
|
|||
|
||||
## Roll Out Steps
|
||||
|
||||
- [ ] Confirm that QA tests pass with the feature flag enabled (if you're unsure how, contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors))
|
||||
- [ ] Enable on staging (`/chatops run feature set feature_name true --staging`)
|
||||
- [ ] Test on staging
|
||||
- [ ] Ensure that documentation has been updated
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
GlSearchBoxByType,
|
||||
GlSprintf,
|
||||
GlButton,
|
||||
GlAlert,
|
||||
} from '@gitlab/ui';
|
||||
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
|
||||
import { __, s__ } from '~/locale';
|
||||
|
|
@ -25,6 +26,7 @@ export default {
|
|||
GlDropdownItem,
|
||||
GlSearchBoxByType,
|
||||
GlSprintf,
|
||||
GlAlert,
|
||||
},
|
||||
props: {
|
||||
knative: {
|
||||
|
|
@ -106,12 +108,13 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="row">
|
||||
<div
|
||||
<gl-alert
|
||||
v-if="knative.updateFailed"
|
||||
class="bs-callout bs-callout-danger cluster-application-banner col-12 mt-2 mb-2 js-cluster-knative-domain-name-failure-message"
|
||||
class="gl-mb-5 col-12 js-cluster-knative-domain-name-failure-message"
|
||||
variant="danger"
|
||||
>
|
||||
{{ s__('ClusterIntegration|Something went wrong while updating Knative domain name.') }}
|
||||
</div>
|
||||
</gl-alert>
|
||||
|
||||
<div
|
||||
:class="{ 'col-md-6': knativeInstalled, 'col-12': !knativeInstalled }"
|
||||
|
|
|
|||
|
|
@ -58,22 +58,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.cluster-application-banner {
|
||||
height: 45px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.cluster-application-banner-close {
|
||||
align-self: flex-start;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
color: $orange-500;
|
||||
opacity: 1;
|
||||
margin: $gl-padding-8 14px 0 0;
|
||||
}
|
||||
|
||||
.cluster-application-description {
|
||||
flex: 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module OptimizedIssuableLabelFilter
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
prepended do
|
||||
extend Gitlab::Cache::RequestCache
|
||||
|
||||
# Avoid repeating label queries times when the finder is instantiated multiple times during the request.
|
||||
request_cache(:find_label_ids) { [root_namespace.id, params.label_names] }
|
||||
end
|
||||
|
||||
def by_label(items)
|
||||
return items unless params.labels?
|
||||
|
||||
|
|
@ -41,7 +50,7 @@ module OptimizedIssuableLabelFilter
|
|||
|
||||
def issuables_with_selected_labels(items, target_model)
|
||||
if root_namespace
|
||||
all_label_ids = find_label_ids(root_namespace)
|
||||
all_label_ids = find_label_ids
|
||||
# Found less labels in the DB than we were searching for. Return nothing.
|
||||
return items.none if all_label_ids.size != params.label_names.size
|
||||
|
||||
|
|
@ -57,18 +66,20 @@ module OptimizedIssuableLabelFilter
|
|||
items
|
||||
end
|
||||
|
||||
def find_label_ids(root_namespace)
|
||||
finder_params = {
|
||||
include_subgroups: true,
|
||||
include_ancestor_groups: true,
|
||||
include_descendant_groups: true,
|
||||
group: root_namespace,
|
||||
title: params.label_names
|
||||
}
|
||||
def find_label_ids
|
||||
group_labels = Label
|
||||
.where(project_id: nil)
|
||||
.where(title: params.label_names)
|
||||
.where(group_id: root_namespace.self_and_descendants.select(:id))
|
||||
|
||||
LabelsFinder
|
||||
.new(nil, finder_params)
|
||||
.execute(skip_authorization: true)
|
||||
project_labels = Label
|
||||
.where(group_id: nil)
|
||||
.where(title: params.label_names)
|
||||
.where(project_id: Project.select(:id).where(namespace_id: root_namespace.self_and_descendants.select(:id)))
|
||||
|
||||
Label
|
||||
.from_union([group_labels, project_labels], remove_duplicates: false)
|
||||
.reorder(nil)
|
||||
.pluck(:title, :id)
|
||||
.group_by(&:first)
|
||||
.values
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ class DiffNote < Note
|
|||
end
|
||||
|
||||
def supported?
|
||||
for_commit? || for_design? || self.noteable.has_complete_diff_refs?
|
||||
for_commit? || for_design? || self.noteable&.has_complete_diff_refs?
|
||||
end
|
||||
|
||||
def set_line_code
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@
|
|||
= render "projects/merge_requests/description"
|
||||
= render "projects/merge_requests/widget"
|
||||
= render "projects/merge_requests/awards_block"
|
||||
- if mr_action === "show"
|
||||
- add_page_startup_api_call discussions_path(@merge_request)
|
||||
#js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request).to_json,
|
||||
noteable_data: serialize_issuable(@merge_request, serializer: 'noteable'),
|
||||
noteable_type: 'MergeRequest',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Convert knative error alert to glalert
|
||||
merge_request: 47840
|
||||
author:
|
||||
type: changed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Repopulate historical vulnerability statistics
|
||||
merge_request: 48128
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Avoid exception when validating diff_note support
|
||||
merge_request: 48187
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Replace wrong index definition on labels (project_id, title)
|
||||
merge_request: 48238
|
||||
author:
|
||||
type: other
|
||||
|
|
@ -250,6 +250,8 @@
|
|||
- 1
|
||||
- - project_service
|
||||
- 1
|
||||
- - project_template_export
|
||||
- 1
|
||||
- - project_update_repository_storage
|
||||
- 1
|
||||
- - prometheus_create_default_alerts
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ comparison_cmd = [
|
|||
|
||||
comment = `cat #{markdown_result}`
|
||||
|
||||
markdown(<<~MARKDOWN)
|
||||
unless comment.strip.empty?
|
||||
markdown(<<~MARKDOWN)
|
||||
#{comment}
|
||||
MARKDOWN
|
||||
MARKDOWN
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ReplaceUnusedLabelsIndex < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
NEW_INDEX_NAME = 'index_labels_on_group_id_and_title_with_null_project_id'
|
||||
OLD_INDEX_NAME = 'index_labels_on_group_id_and_title'
|
||||
|
||||
def up
|
||||
add_concurrent_index :labels, [:group_id, :title], where: 'project_id IS NULL', name: NEW_INDEX_NAME
|
||||
remove_concurrent_index_by_name :labels, OLD_INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :labels, [:group_id, :title], where: 'project_id = NULL::integer', name: OLD_INDEX_NAME
|
||||
remove_concurrent_index_by_name :labels, NEW_INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ScheduleRepopulateHistoricalVulnerabilityStatistics < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
BATCH_SIZE = 50
|
||||
DELAY_INTERVAL = 5.minutes
|
||||
MIGRATION_CLASS = 'PopulateVulnerabilityHistoricalStatistics'
|
||||
DAY_COUNT = 365
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
class ProjectSetting < ActiveRecord::Base
|
||||
include EachBatch
|
||||
|
||||
self.table_name = 'project_settings'
|
||||
|
||||
scope :has_vulnerabilities, -> { where('has_vulnerabilities IS TRUE') }
|
||||
end
|
||||
|
||||
def up
|
||||
ProjectSetting.has_vulnerabilities.each_batch(of: BATCH_SIZE) do |batch, index|
|
||||
migrate_in(index * DELAY_INTERVAL, MIGRATION_CLASS, [batch.pluck(:project_id), DAY_COUNT])
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
9ff8ddefff1df81f1eac2ccfc6f3019bb77a6129280e799c0abe54f51e09277a
|
||||
|
|
@ -0,0 +1 @@
|
|||
8b60a6bc892f9700df81de9909595544f9f820621a210906a249428ddec9eefa
|
||||
|
|
@ -21202,7 +21202,7 @@ CREATE UNIQUE INDEX index_label_priorities_on_project_id_and_label_id ON label_p
|
|||
|
||||
CREATE UNIQUE INDEX index_labels_on_group_id_and_project_id_and_title ON labels USING btree (group_id, project_id, title);
|
||||
|
||||
CREATE INDEX index_labels_on_group_id_and_title ON labels USING btree (group_id, title) WHERE (project_id = NULL::integer);
|
||||
CREATE INDEX index_labels_on_group_id_and_title_with_null_project_id ON labels USING btree (group_id, title) WHERE (project_id IS NULL);
|
||||
|
||||
CREATE INDEX index_labels_on_project_id ON labels USING btree (project_id);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ addressed.
|
|||
},
|
||||
# Add your experiment here:
|
||||
signup_flow: {
|
||||
environment: ::Gitlab.dev_env_or_com?, # Target environment, defaults to enabled for development and GitLab.com
|
||||
tracking_category: 'Growth::Activation::Experiment::SignUpFlow' # Used for providing the category when setting up tracking data
|
||||
}
|
||||
}.freeze
|
||||
|
|
|
|||
|
|
@ -929,6 +929,13 @@ Gitlab::Elastic::Indexer::Error: time="2020-01-23T09:13:00Z" level=fatal msg="he
|
|||
You probably have not used either `http://` or `https://` as part of your value in the **"URL"** field of the Elasticsearch Integration Menu. Please make sure you are using either `http://` or `https://` in this field as the [Elasticsearch client for Go](https://github.com/olivere/elastic) that we are using [needs the prefix for the URL to be accepted as valid](https://github.com/olivere/elastic/commit/a80af35aa41856dc2c986204e2b64eab81ccac3a).
|
||||
Once you have corrected the formatting of the URL, delete the index (via the [dedicated Rake task](#gitlab-advanced-search-rake-tasks)) and [reindex the content of your instance](#enabling-advanced-search).
|
||||
|
||||
### My Elasticsearch cluster has a plugin and the integration is not working
|
||||
|
||||
Certain 3rd party plugins may introduce bugs in your cluster or for whatever
|
||||
reason may be incompatible with our integration. You should try disabling
|
||||
plugins so you can rule out the possibility that the plugin is causing the
|
||||
problem.
|
||||
|
||||
### Low-level troubleshooting
|
||||
|
||||
There is a [more structured, lower-level troubleshooting document](../administration/troubleshooting/elasticsearch.md) for when you experience other issues, including poor performance.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#
|
||||
# Utility module for A/B testing experimental features. Define your experiments in the `EXPERIMENTS` constant.
|
||||
# Experiment options:
|
||||
# - environment (optional, defaults to enabled for development and GitLab.com)
|
||||
# - tracking_category (optional, used to set the category when tracking an experiment event)
|
||||
# - use_backwards_compatible_subject_index (optional, set this to true if you need backwards compatibility)
|
||||
#
|
||||
|
|
@ -87,14 +86,13 @@ module Gitlab
|
|||
|
||||
class << self
|
||||
def experiment(key)
|
||||
Experiment.new(EXPERIMENTS[key].merge(key: key))
|
||||
Gitlab::Experimentation::Experiment.new(key, **EXPERIMENTS[key])
|
||||
end
|
||||
|
||||
def enabled?(experiment_key)
|
||||
return false unless EXPERIMENTS.key?(experiment_key)
|
||||
|
||||
experiment = experiment(experiment_key)
|
||||
experiment.enabled_for_environment? && experiment.enabled?
|
||||
experiment(experiment_key).enabled?
|
||||
end
|
||||
|
||||
def enabled_for_attribute?(experiment_key, attribute)
|
||||
|
|
@ -106,36 +104,5 @@ module Gitlab
|
|||
enabled?(experiment_key) && experiment(experiment_key).enabled_for_index?(value)
|
||||
end
|
||||
end
|
||||
|
||||
Experiment = Struct.new(
|
||||
:key,
|
||||
:environment,
|
||||
:tracking_category,
|
||||
:use_backwards_compatible_subject_index,
|
||||
keyword_init: true
|
||||
) do
|
||||
def enabled?
|
||||
experiment_percentage > 0
|
||||
end
|
||||
|
||||
def enabled_for_environment?
|
||||
return ::Gitlab.dev_env_or_com? if environment.nil?
|
||||
|
||||
environment
|
||||
end
|
||||
|
||||
def enabled_for_index?(index)
|
||||
return false if index.blank?
|
||||
|
||||
index <= experiment_percentage
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# When a feature does not exist, the `percentage_of_time_value` method will return 0
|
||||
def experiment_percentage
|
||||
@experiment_percentage ||= Feature.get(:"#{key}_experiment_percentage").percentage_of_time_value # rubocop:disable Gitlab/AvoidFeatureGet
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Experimentation
|
||||
class Experiment
|
||||
attr_reader :tracking_category, :use_backwards_compatible_subject_index
|
||||
|
||||
def initialize(key, **params)
|
||||
@tracking_category = params[:tracking_category]
|
||||
@use_backwards_compatible_subject_index = params[:use_backwards_compatible_subject_index]
|
||||
|
||||
@experiment_percentage = Feature.get(:"#{key}_experiment_percentage").percentage_of_time_value # rubocop:disable Gitlab/AvoidFeatureGet
|
||||
end
|
||||
|
||||
def enabled?
|
||||
::Gitlab.dev_env_or_com? && experiment_percentage > 0
|
||||
end
|
||||
|
||||
def enabled_for_index?(index)
|
||||
return false if index.blank?
|
||||
|
||||
index <= experiment_percentage
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :experiment_percentage
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -31,7 +31,8 @@ RSpec.describe 'Resolve an open thread in a merge request by creating an issue',
|
|||
visit project_merge_request_path(project, merge_request)
|
||||
end
|
||||
|
||||
it 'does not show a link to create a new issue' do
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/285453
|
||||
xit 'does not show a link to create a new issue' do
|
||||
expect(page).not_to have_css resolve_discussion_selector
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
|
|||
before do
|
||||
stub_const('Gitlab::Experimentation::EXPERIMENTS', {
|
||||
backwards_compatible_test_experiment: {
|
||||
environment: environment,
|
||||
tracking_category: 'Team',
|
||||
use_backwards_compatible_subject_index: true
|
||||
},
|
||||
test_experiment: {
|
||||
environment: environment,
|
||||
tracking_category: 'Team'
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +19,6 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
|
|||
Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
|
||||
end
|
||||
|
||||
let(:environment) { Rails.env.test? }
|
||||
let(:enabled_percentage) { 10 }
|
||||
|
||||
controller(ApplicationController) do
|
||||
|
|
@ -391,10 +388,8 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
|
|||
|
||||
context 'do not track' do
|
||||
before do
|
||||
stub_experiment(test_experiment: true)
|
||||
allow(controller).to receive(:current_user).and_return(user)
|
||||
allow_next_instance_of(described_class) do |instance|
|
||||
allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'is disabled' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Experimentation::Experiment do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:percentage) { 50 }
|
||||
let(:params) do
|
||||
{
|
||||
tracking_category: 'Category1',
|
||||
use_backwards_compatible_subject_index: true
|
||||
}
|
||||
end
|
||||
|
||||
before do
|
||||
feature = double('FeatureFlag', percentage_of_time_value: percentage )
|
||||
expect(Feature).to receive(:get).with(:experiment_key_experiment_percentage).and_return(feature)
|
||||
end
|
||||
|
||||
subject(:experiment) { described_class.new(:experiment_key, **params) }
|
||||
|
||||
describe '#enabled?' do
|
||||
before do
|
||||
allow(Gitlab).to receive(:dev_env_or_com?).and_return(on_gitlab_com)
|
||||
end
|
||||
|
||||
subject { experiment.enabled? }
|
||||
|
||||
where(:on_gitlab_com, :percentage, :is_enabled) do
|
||||
true | 0 | false
|
||||
true | 10 | true
|
||||
false | 0 | false
|
||||
false | 10 | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq(is_enabled) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enabled_for_index?' do
|
||||
subject { experiment.enabled_for_index?(index) }
|
||||
|
||||
where(:index, :percentage, :is_enabled) do
|
||||
50 | 40 | false
|
||||
40 | 50 | true
|
||||
nil | 50 | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq(is_enabled) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -33,27 +33,25 @@ RSpec.describe Gitlab::Experimentation, :snowplow do
|
|||
before do
|
||||
stub_const('Gitlab::Experimentation::EXPERIMENTS', {
|
||||
backwards_compatible_test_experiment: {
|
||||
environment: environment,
|
||||
tracking_category: 'Team',
|
||||
use_backwards_compatible_subject_index: true
|
||||
},
|
||||
test_experiment: {
|
||||
environment: environment,
|
||||
tracking_category: 'Team'
|
||||
}
|
||||
})
|
||||
|
||||
Feature.enable_percentage_of_time(:backwards_compatible_test_experiment_experiment_percentage, enabled_percentage)
|
||||
Feature.enable_percentage_of_time(:test_experiment_experiment_percentage, enabled_percentage)
|
||||
allow(Gitlab).to receive(:com?).and_return(true)
|
||||
end
|
||||
|
||||
let(:environment) { Rails.env.test? }
|
||||
let(:enabled_percentage) { 10 }
|
||||
|
||||
describe '.enabled?' do
|
||||
subject { described_class.enabled?(:test_experiment) }
|
||||
|
||||
context 'feature toggle is enabled, we are on the right environment and we are selected' do
|
||||
context 'feature toggle is enabled and we are selected' do
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
|
|
@ -68,20 +66,6 @@ RSpec.describe Gitlab::Experimentation, :snowplow do
|
|||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
|
||||
describe 'we are on the wrong environment' do
|
||||
let(:environment) { ::Gitlab.com? }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
|
||||
it 'ensures the typically less expensive environment is checked before the more expensive call to database for Feature' do
|
||||
expect_next_instance_of(described_class::Experiment) do |experiment|
|
||||
expect(experiment).not_to receive(:enabled?)
|
||||
end
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.enabled_for_value?' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe ScheduleRepopulateHistoricalVulnerabilityStatistics do
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:projects) { table(:projects) }
|
||||
let(:project_settings) { table(:project_settings) }
|
||||
|
||||
let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
|
||||
let!(:project_1) { projects.create!(namespace_id: namespace.id, name: 'foo_1') }
|
||||
let!(:project_2) { projects.create!(namespace_id: namespace.id, name: 'foo_2') }
|
||||
let!(:project_3) { projects.create!(namespace_id: namespace.id, name: 'foo_3') }
|
||||
let!(:project_4) { projects.create!(namespace_id: namespace.id, name: 'foo_4') }
|
||||
|
||||
around do |example|
|
||||
freeze_time { Sidekiq::Testing.fake! { example.run } }
|
||||
end
|
||||
|
||||
before do
|
||||
stub_const("#{described_class.name}::BATCH_SIZE", 1)
|
||||
|
||||
project_settings.create!(project_id: project_1.id, has_vulnerabilities: true)
|
||||
project_settings.create!(project_id: project_2.id, has_vulnerabilities: false)
|
||||
project_settings.create!(project_id: project_4.id, has_vulnerabilities: true)
|
||||
end
|
||||
|
||||
it 'schedules the background jobs', :aggregate_failures do
|
||||
migrate!
|
||||
|
||||
expect(BackgroundMigrationWorker.jobs.size).to be(2)
|
||||
expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(described_class::DELAY_INTERVAL, [project_1.id], described_class::DAY_COUNT)
|
||||
expect(described_class::MIGRATION_CLASS).to be_scheduled_delayed_migration(2 * described_class::DELAY_INTERVAL, [project_4.id], described_class::DAY_COUNT)
|
||||
end
|
||||
end
|
||||
|
|
@ -38,6 +38,14 @@ RSpec.describe DiffNote do
|
|||
it_behaves_like 'a valid diff positionable note' do
|
||||
subject { build(:diff_note_on_commit, project: project, commit_id: commit_id, position: position) }
|
||||
end
|
||||
|
||||
it "is not valid when noteable is empty" do
|
||||
note = build(:diff_note_on_merge_request, project: project, noteable: nil)
|
||||
|
||||
note.valid?
|
||||
|
||||
expect(note.errors[:noteable]).to include("doesn't support new-style diff notes")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#position=" do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'export worker' do
|
||||
describe '#perform' do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:project) { create(:project) }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(described_class) do |job|
|
||||
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it succeeds' do
|
||||
it 'calls the ExportService' do
|
||||
expect_next_instance_of(::Projects::ImportExport::ExportService) do |service|
|
||||
expect(service).to receive(:execute)
|
||||
end
|
||||
|
||||
subject.perform(user.id, project.id, { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' })
|
||||
end
|
||||
|
||||
context 'export job' do
|
||||
before do
|
||||
allow_next_instance_of(::Projects::ImportExport::ExportService) do |service|
|
||||
allow(service).to receive(:execute)
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates an export job record for the project' do
|
||||
expect { subject.perform(user.id, project.id, {}) }.to change { project.export_jobs.count }.from(0).to(1)
|
||||
end
|
||||
|
||||
it 'sets the export job status to started' do
|
||||
expect_next_instance_of(ProjectExportJob) do |job|
|
||||
expect(job).to receive(:start)
|
||||
end
|
||||
|
||||
subject.perform(user.id, project.id, {})
|
||||
end
|
||||
|
||||
it 'sets the export job status to finished' do
|
||||
expect_next_instance_of(ProjectExportJob) do |job|
|
||||
expect(job).to receive(:finish)
|
||||
end
|
||||
|
||||
subject.perform(user.id, project.id, {})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it fails' do
|
||||
it 'does not raise an exception when strategy is invalid' do
|
||||
expect(::Projects::ImportExport::ExportService).not_to receive(:new)
|
||||
|
||||
expect { subject.perform(user.id, project.id, { 'klass' => 'Whatever' }) }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'does not raise error when project cannot be found' do
|
||||
expect { subject.perform(user.id, non_existing_record_id, {}) }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'does not raise error when user cannot be found' do
|
||||
expect { subject.perform(non_existing_record_id, project.id, {}) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sidekiq options' do
|
||||
it 'disables retry' do
|
||||
expect(described_class.sidekiq_options['retry']).to eq(false)
|
||||
end
|
||||
|
||||
it 'disables dead' do
|
||||
expect(described_class.sidekiq_options['dead']).to eq(false)
|
||||
end
|
||||
|
||||
it 'sets default status expiration' do
|
||||
expect(described_class.sidekiq_options['status_expiration']).to eq(StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -3,84 +3,5 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ProjectExportWorker do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:project) { create(:project) }
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
before do
|
||||
allow_next_instance_of(described_class) do |job|
|
||||
allow(job).to receive(:jid).and_return(SecureRandom.hex(8))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it succeeds' do
|
||||
it 'calls the ExportService' do
|
||||
expect_next_instance_of(::Projects::ImportExport::ExportService) do |service|
|
||||
expect(service).to receive(:execute)
|
||||
end
|
||||
|
||||
subject.perform(user.id, project.id, { 'klass' => 'Gitlab::ImportExport::AfterExportStrategies::DownloadNotificationStrategy' })
|
||||
end
|
||||
|
||||
context 'export job' do
|
||||
before do
|
||||
allow_next_instance_of(::Projects::ImportExport::ExportService) do |service|
|
||||
allow(service).to receive(:execute)
|
||||
end
|
||||
end
|
||||
|
||||
it 'creates an export job record for the project' do
|
||||
expect { subject.perform(user.id, project.id, {}) }.to change { project.export_jobs.count }.from(0).to(1)
|
||||
end
|
||||
|
||||
it 'sets the export job status to started' do
|
||||
expect_next_instance_of(ProjectExportJob) do |job|
|
||||
expect(job).to receive(:start)
|
||||
end
|
||||
|
||||
subject.perform(user.id, project.id, {})
|
||||
end
|
||||
|
||||
it 'sets the export job status to finished' do
|
||||
expect_next_instance_of(ProjectExportJob) do |job|
|
||||
expect(job).to receive(:finish)
|
||||
end
|
||||
|
||||
subject.perform(user.id, project.id, {})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it fails' do
|
||||
it 'does not raise an exception when strategy is invalid' do
|
||||
expect(::Projects::ImportExport::ExportService).not_to receive(:new)
|
||||
|
||||
expect { subject.perform(user.id, project.id, { 'klass' => 'Whatever' }) }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'does not raise error when project cannot be found' do
|
||||
expect { subject.perform(user.id, non_existing_record_id, {}) }.not_to raise_error
|
||||
end
|
||||
|
||||
it 'does not raise error when user cannot be found' do
|
||||
expect { subject.perform(non_existing_record_id, project.id, {}) }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sidekiq options' do
|
||||
it 'disables retry' do
|
||||
expect(described_class.sidekiq_options['retry']).to eq(false)
|
||||
end
|
||||
|
||||
it 'disables dead' do
|
||||
expect(described_class.sidekiq_options['dead']).to eq(false)
|
||||
end
|
||||
|
||||
it 'sets default status expiration' do
|
||||
expect(described_class.sidekiq_options['status_expiration']).to eq(StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION)
|
||||
end
|
||||
end
|
||||
it_behaves_like 'export worker'
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue