Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-01-19 21:14:54 +00:00
parent d738ba980c
commit e7cbe1006f
21 changed files with 324 additions and 90 deletions

View file

@ -0,0 +1,103 @@
<!-- Set the correct label and milestone using autocomplete for guidance. Please @mention only the DRI(s) for each stage or group rather than an entire department. -->
**Be sure to link this MR to the relevant deprecation issue(s).**
If the MR does not have a deprecation issue, hit pause and:
- Review [this handbook documentation](https://about.gitlab.com/handbook/product/gitlab-the-product/#process-for-deprecating-and-removing-a-feature).
- Connect with the Product Manager DRI.
Removals must be [announced as Deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations) at least 2 milestones in advance of the planned removal date. Removals can only be removed in a XX.0 major release if it creates a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features).
**By the 10th**: Assign this MR to these team members as reviewers, and for approval:
- Required:
- Product Group Manager or Director: `@PM`
- Engineering Manager: `@EM`
- Technical writer: `@TW`
- Optional:
- Product Designer(s): `@ProductDesigners`
- Product Marketing: `@PMM`
**By 7:59 PM UTC 15th (11:59 AM PT)**: EM/PM assigns this MR to the TW reviewer for final review and merge: `@EM/PM`
**By 7:59 AM UTC 18th (11:59 PM PT 17th)**: TW Reviewer updates Docs by merging this MR to `master`: `@TW`
---
Please review the [guidelines for removals](https://about.gitlab.com/handbook/marketing/blog/release-posts/#removals).
## Links
- Removal Issue:
- Removal MR (optional):
## EM/PM release post item checklist
- [ ] Set yourself as the Assignee, meaning you are the DRI.
- [ ] If the removal is a [breaking change](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-change), add label `breaking change`.
- [ ] Follow the process to [create a removal YAML file](https://about.gitlab.com/handbook/marketing/blog/release-posts/#creating-a-removal-entry).
- [ ] Add reviewers by the 10th.
- [ ] When ready to be merged and not later than the 15th, add the ~ready label and @ message the TW for final review and merge.
## Reviewers
When the content is ready for review, the Technical Writer and Engineering Manager _must_
review it. Optional reviewers can include Product Marketing, Product Design, and the Product Leaders
for this area. Use the
[Reviewers for Merge Requests](https://docs.gitlab.com/ee/user/project/merge_requests/getting_started#reviewer)
feature for all reviews. Reviewers will `approve` the MR and remove themselves from the reviewers list when their review is complete.
- [ ] (Recommended) PMM
- [ ] (Optional) Product Designer
- [ ] (Optional) Group Manager or Director
- [ ] Required review and approval: [Technical Writer designated to the corresponding DevOps stage/group](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments).
### Tech writer review
The TW should review according to the criteria listed below. Review a removal MR
with the same process as regular docs MRs. Add suggestions as needed, @ message
the PM to inform them the first review is complete, and remove
yourself as a reviewer if it's not yet ready for merge.
<details>
<summary>Expand for Details</summary>
- [ ] Title:
- Length limit: 7 words (not including articles or prepositions).
- Capitalization: ensure the title is [sentence cased](https://design.gitlab.com/content/punctuation#case).
- No Markdown `` `code` `` formatting in the title, as it doesn't render correctly in the release post.
- [ ] Consistency:
- Ensure that all resources (docs, removal, etc.) refer to the feature with the same term / feature name.
- [ ] Content:
- Make sure the removal is accurate based on your understanding. Look for typos or grammar mistakes. Work with PM and PMM to ensure a consistent GitLab style and tone for messaging, based on other features and removals.
- Review use of whitespace and bullet lists. Will the removal item be easily scannable when published? Consider adding line breaks or breaking content into bullets if you have more than a few sentences.
- Make sure there aren't acronyms readers may not understand per <https://about.gitlab.com/handbook/communication/#writing-style-guidelines>.
- [ ] Links:
- All links must be full URLs, as the removal YAML files are used in multiple projects. Do not use relative links. The generated doc is an exception to the relative link rule and currently uses absolute links only.
- Make sure all links and anchors are correct. Do not link to the H1 (top) anchor on a docs page.
- [ ] Code. Make sure any included code is wrapped in code blocks.
- [ ] Capitalization. Make sure to capitalize feature names. Stay consistent with the Documentation Style Guidance on [Capitalization](https://docs.gitlab.com/ee/development/documentation/styleguide.html#capitalization).
- [ ] Blank spaces. Remove unnecessary spaces (end of line spaces, double spaces, extra blank lines, and lines with only spaces).
</details>
When the PM indicates it is ready for merge and all issues have been addressed, start the merge process.
#### Technical writer merge process
The [removals doc's `.md` file](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/update/removals.md)
must be updated before this MR is merged:
1. Check out the MR's branch (in the [`gitlab-org/gitlab`](https://gitlab.com/gitlab-org/gitlab) project).
1. From the command line (in the branch), run `bin/rake gitlab:docs:compile_removals`.
If you want to double check that it worked, you can run `bin/rake gitlab:docs:check_removals`
to verify that the doc is up to date.
1. Commit the updated file and push the changes.
1. Set the MR to merge when the pipeline succeeds (or merge if the pipeline is already complete).
If you have trouble running the rake task, check the [troubleshooting steps](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecation-rake-task-troubleshooting).
/label ~"release post" ~"release post item" ~"Technical Writing" ~devops:: ~group:: ~"release post item::removal"
/milestone %
/assign `@EM/PM` (choose the DRI; remove backticks here, and below)

View file

@ -1,5 +1,6 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VueRouter from 'vue-router';
import TableOfContents from '~/blob/components/table_contents.vue';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
import { BlobViewer, initAuxiliaryViewer } from '~/blob/viewer/index';
@ -12,11 +13,14 @@ import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
import '~/sourcegraph/load';
Vue.use(VueApollo);
Vue.use(VueRouter);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
const router = new VueRouter({ mode: 'history' });
const viewBlobEl = document.querySelector('#js-view-blob-app');
if (viewBlobEl) {
@ -25,6 +29,7 @@ if (viewBlobEl) {
// eslint-disable-next-line no-new
new Vue({
el: viewBlobEl,
router,
apolloProvider,
provide: {
targetBranch,

View file

@ -20,10 +20,9 @@ export default {
v-for="line in lines"
:id="`L${line}`"
:key="line"
class="diff-line-num"
:href="`#LC${line}`"
class="diff-line-num gl-shadow-none!"
:to="`#LC${line}`"
:data-line-number="line"
@click="$emit('select-line', `#LC${line}`)"
>
<gl-icon :size="12" name="link" />
{{ line }}

View file

@ -56,6 +56,9 @@ export default {
highlightedContent() {
this.$nextTick(() => this.selectLine());
},
$route() {
this.selectLine();
},
},
async mounted() {
this.hljs = await this.loadHighlightJS();
@ -90,7 +93,8 @@ export default {
.join('\r\n')
);
},
selectLine(hash = sanitize(window.location.hash)) {
selectLine() {
const hash = sanitize(this.$route.hash);
const lineToSelect = hash && this.$el.querySelector(hash);
if (!lineToSelect) {
@ -112,7 +116,7 @@ export default {
</script>
<template>
<div class="file-content code js-syntax-highlight" :class="$options.userColorScheme">
<line-numbers :lines="lineNumbers" @select-line="selectLine" />
<line-numbers :lines="lineNumbers" />
<pre class="code"><code v-safe-html="highlightedContent"></code>
</pre>
</div>

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
class LooseForeignKeys::DeletedRecord < ApplicationRecord
class LooseForeignKeys::DeletedRecord < Gitlab::Database::SharedModel
PARTITION_DURATION = 1.day
include PartitionedTable

View file

@ -4,7 +4,7 @@ module LooseForeignKeys
class ModificationTracker
MAX_DELETES = 100_000
MAX_UPDATES = 50_000
MAX_RUNTIME = 3.minutes
MAX_RUNTIME = 30.seconds # must be less than the scheduling frequency of the LooseForeignKeys::CleanupWorker cron worker
delegate :monotonic_time, to: :'Gitlab::Metrics::System'

View file

@ -10,7 +10,6 @@ module LooseForeignKeys
def execute
modification_tracker = ModificationTracker.new
tracked_tables.cycle do |table|
records = load_batch_for_table(table)

View file

@ -1,26 +1,25 @@
= cache_if(Feature.enabled?(:cached_mr_widget, @merge_request.project), [@merge_request.project, @merge_request, current_user], expires_in: 10.minutes) do
- artifacts_endpoint_placeholder = ':pipeline_artifacts_id'
- artifacts_endpoint_placeholder = ':pipeline_artifacts_id'
= javascript_tag do
:plain
window.gl = window.gl || {};
window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)}
= javascript_tag do
:plain
window.gl = window.gl || {};
window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget', issues_links: true)}
window.gl.mrWidgetData.artifacts_endpoint = '#{downloadable_artifacts_project_pipeline_path(@project, artifacts_endpoint_placeholder, format: :json)}';
window.gl.mrWidgetData.artifacts_endpoint_placeholder = '#{artifacts_endpoint_placeholder}';
window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
window.gl.mrWidgetData.ci_troubleshooting_docs_path = '#{help_page_path('ci/troubleshooting.md')}';
window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviews/index.md', anchor: 'troubleshooting')}';
window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds')}';
window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/approvals/rules.md', anchor: 'eligible-approvers')}';
window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/approvals/index.md")}';
window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
window.gl.mrWidgetData.codequality_help_path = '#{help_page_path("user/project/merge_requests/code_quality", anchor: "code-quality-reports")}';
window.gl.mrWidgetData.false_positive_doc_url = '#{help_page_path('user/application_security/vulnerabilities/index')}';
window.gl.mrWidgetData.can_view_false_positive = '#{@merge_request.project.licensed_feature_available?(:sast_fp_reduction).to_s}';
window.gl.mrWidgetData.user_preferences_gitpod_path = '#{profile_preferences_path(anchor: 'user_gitpod_enabled')}';
window.gl.mrWidgetData.user_profile_enable_gitpod_path = '#{profile_path(user: { gitpod_enabled: true })}';
window.gl.mrWidgetData.artifacts_endpoint = '#{downloadable_artifacts_project_pipeline_path(@project, artifacts_endpoint_placeholder, format: :json)}';
window.gl.mrWidgetData.artifacts_endpoint_placeholder = '#{artifacts_endpoint_placeholder}';
window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
window.gl.mrWidgetData.ci_troubleshooting_docs_path = '#{help_page_path('ci/troubleshooting.md')}';
window.gl.mrWidgetData.mr_troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/reviews/index.md', anchor: 'troubleshooting')}';
window.gl.mrWidgetData.pipeline_must_succeed_docs_path = '#{help_page_path('user/project/merge_requests/merge_when_pipeline_succeeds.md', anchor: 'only-allow-merge-requests-to-be-merged-if-the-pipeline-succeeds')}';
window.gl.mrWidgetData.security_approvals_help_page_path = '#{help_page_path('user/application_security/index.md', anchor: 'security-approvals-in-merge-requests')}';
window.gl.mrWidgetData.license_compliance_docs_path = '#{help_page_path('user/compliance/license_compliance/index.md', anchor: 'policies')}';
window.gl.mrWidgetData.eligible_approvers_docs_path = '#{help_page_path('user/project/merge_requests/approvals/rules.md', anchor: 'eligible-approvers')}';
window.gl.mrWidgetData.approvals_help_path = '#{help_page_path("user/project/merge_requests/approvals/index.md")}';
window.gl.mrWidgetData.pipelines_empty_svg_path = '#{image_path('illustrations/pipelines_empty.svg')}';
window.gl.mrWidgetData.codequality_help_path = '#{help_page_path("user/project/merge_requests/code_quality", anchor: "code-quality-reports")}';
window.gl.mrWidgetData.false_positive_doc_url = '#{help_page_path('user/application_security/vulnerabilities/index')}';
window.gl.mrWidgetData.can_view_false_positive = '#{@merge_request.project.licensed_feature_available?(:sast_fp_reduction).to_s}';
window.gl.mrWidgetData.user_preferences_gitpod_path = '#{profile_preferences_path(anchor: 'user_gitpod_enabled')}';
window.gl.mrWidgetData.user_profile_enable_gitpod_path = '#{profile_path(user: { gitpod_enabled: true })}';
#js-vue-mr-widget.mr-widget
#js-vue-mr-widget.mr-widget

View file

@ -6,6 +6,7 @@ module LooseForeignKeys
include Gitlab::ExclusiveLeaseHelpers
include CronjobQueue # rubocop: disable Scalability/CronWorkerContext
sidekiq_options retry: false
feature_category :sharding
data_consistency :always
idempotent!
@ -13,13 +14,30 @@ module LooseForeignKeys
def perform
return if Feature.disabled?(:loose_foreign_key_cleanup, default_enabled: :yaml)
ttl = ModificationTracker::MAX_RUNTIME + 1.minute
in_lock(self.class.name.underscore, ttl: ttl, retries: 0) do
# TODO: Iterate over the connections
# https://gitlab.com/gitlab-org/gitlab/-/issues/341513
stats = ProcessDeletedRecordsService.new(connection: ApplicationRecord.connection).execute
in_lock(self.class.name.underscore, ttl: ModificationTracker::MAX_RUNTIME, retries: 0) do
stats = {}
connection_name, base_model = current_connection_name_and_base_model
Gitlab::Database::SharedModel.using_connection(base_model.connection) do
stats = ProcessDeletedRecordsService.new(connection: base_model.connection).execute
stats[:connection] = connection_name
end
log_extra_metadata_on_done(:stats, stats)
end
end
private
# Rotate the databases every minute
#
# If one DB is configured: every minute use the configured DB
# If two DBs are configured (Main, CI): minute 1 -> Main, minute 2 -> CI
def current_connection_name_and_base_model
minutes_since_epoch = Time.current.to_i / 60
connections_with_name = Gitlab::Database.database_base_models.to_a # this will never be empty
connections_with_name[minutes_since_epoch % connections_with_name.count]
end
end
end

View file

@ -1,8 +0,0 @@
---
name: cached_mr_widget
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61584
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330803
milestone: '13.12'
type: development
group: group::code review
default_enabled: false

View file

@ -735,7 +735,7 @@ Gitlab.ee do
Settings.cron_jobs['app_sec_dast_profile_schedule_worker']['cron'] ||= '7-59/15 * * * *'
Settings.cron_jobs['app_sec_dast_profile_schedule_worker']['job_class'] = 'AppSec::Dast::ProfileScheduleWorker'
Settings.cron_jobs['loose_foreign_keys_cleanup_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['cron'] ||= '*/5 * * * *'
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['cron'] ||= '*/1 * * * *'
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['job_class'] = 'LooseForeignKeys::CleanupWorker'
end

View file

@ -43,7 +43,7 @@ we can:
1. Create a `DELETE` trigger on the `projects` table.
Record the deletions in a separate table (`deleted_records`).
1. A job checks the `deleted_records` table every 5 minutes.
1. A job checks the `deleted_records` table every minute or two.
1. For each record in the table, delete the associated `ci_pipelines` records
using the `project_id` column.

View file

@ -169,7 +169,8 @@ module Gitlab
return -1 if args.any?(&:negative?)
args.sum
rescue StandardError
rescue StandardError => error
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
FALLBACK
end
@ -179,7 +180,8 @@ module Gitlab
else
value
end
rescue StandardError
rescue StandardError => error
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
fallback
end
@ -295,13 +297,15 @@ module Gitlab
def redis_usage_counter
yield
rescue ::Redis::CommandError, Gitlab::UsageDataCounters::BaseCounter::UnknownEvent, Gitlab::UsageDataCounters::HLLRedisCounter::EventError
rescue ::Redis::CommandError, Gitlab::UsageDataCounters::BaseCounter::UnknownEvent, Gitlab::UsageDataCounters::HLLRedisCounter::EventError => error
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
FALLBACK
end
def redis_usage_data_totals(counter)
counter.totals
rescue ::Redis::CommandError, Gitlab::UsageDataCounters::BaseCounter::UnknownEvent
rescue ::Redis::CommandError, Gitlab::UsageDataCounters::BaseCounter::UnknownEvent => error
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
counter.fallback_totals
end
end

View file

@ -13300,6 +13300,12 @@ msgstr ""
msgid "Enable repository checks"
msgstr ""
msgid "Enable security training"
msgstr ""
msgid "Enable security training to help your developers learn how to fix vulnerabilities. Developers can view security training from selected educational providers, relevant to the detected vulnerability."
msgstr ""
msgid "Enable shared runners for all projects and subgroups in this group."
msgstr ""
@ -29353,6 +29359,9 @@ msgstr ""
msgid "Reduce project visibility"
msgstr ""
msgid "Reduce risk and triage fewer vulnerabilities with security training"
msgstr ""
msgid "Reduce this projects visibility?"
msgstr ""

View file

@ -23,7 +23,7 @@ describe('Line Numbers component', () => {
expect(findLineNumbers().length).toBe(lines);
expect(findFirstLineNumber().attributes()).toMatchObject({
id: 'L1',
href: '#LC1',
to: '#LC1',
});
});
@ -34,15 +34,4 @@ describe('Line Numbers component', () => {
});
});
});
describe('clicking a line number', () => {
beforeEach(() => {
jest.spyOn(wrapper.vm, '$emit');
findFirstLineNumber().vm.$emit('click');
});
it('emits a select-line event', () => {
expect(wrapper.vm.$emit).toHaveBeenCalledWith('select-line', '#LC1');
});
});
});

View file

@ -1,10 +1,14 @@
import hljs from 'highlight.js/lib/core';
import Vue, { nextTick } from 'vue';
import VueRouter from 'vue-router';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SourceViewer from '~/vue_shared/components/source_viewer.vue';
import LineNumbers from '~/vue_shared/components/line_numbers.vue';
import waitForPromises from 'helpers/wait_for_promises';
jest.mock('highlight.js/lib/core');
Vue.use(VueRouter);
const router = new VueRouter();
describe('Source Viewer component', () => {
let wrapper;
@ -16,7 +20,10 @@ describe('Source Viewer component', () => {
hljs.highlightAuto.mockImplementation(() => ({ value: highlightedContent }));
const createComponent = async (props = {}) => {
wrapper = shallowMountExtended(SourceViewer, { propsData: { content, language, ...props } });
wrapper = shallowMountExtended(SourceViewer, {
router,
propsData: { content, language, ...props },
});
await waitForPromises();
};
@ -69,16 +76,18 @@ describe('Source Viewer component', () => {
jest.spyOn(firstLineElement, 'scrollIntoView');
jest.spyOn(firstLineElement.classList, 'add');
jest.spyOn(firstLineElement.classList, 'remove');
findLineNumbers().vm.$emit('select-line', '#LC1');
});
it('adds the highlight (hll) class', () => {
it('adds the highlight (hll) class', async () => {
wrapper.vm.$router.push('#LC1');
await nextTick();
expect(firstLineElement.classList.add).toHaveBeenCalledWith('hll');
});
it('removes the highlight (hll) class from a previously highlighted line', () => {
findLineNumbers().vm.$emit('select-line', '#LC2');
it('removes the highlight (hll) class from a previously highlighted line', async () => {
wrapper.vm.$router.push('#LC2');
await nextTick();
expect(firstLineElement.classList.remove).toHaveBeenCalledWith('hll');
});

View file

@ -17,9 +17,25 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::GenericMetric do
end
context 'when raising an exception' do
it 'return the custom fallback' do
before do
allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
expect(ApplicationRecord.database).to receive(:version).and_raise('Error')
expect(subject.value).to eq(custom_fallback)
end
context 'with should_raise_for_dev? false' do
let(:should_raise_for_dev) { false }
it 'return the custom fallback' do
expect(subject.value).to eq(custom_fallback)
end
end
context 'with should_raise_for_dev? true' do
let(:should_raise_for_dev) { true }
it 'raises an error' do
expect { subject.value }.to raise_error('Error')
end
end
end
end
@ -38,9 +54,25 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::GenericMetric do
end
context 'when raising an exception' do
it 'return the default fallback' do
before do
allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
expect(ApplicationRecord.database).to receive(:version).and_raise('Error')
expect(subject.value).to eq(described_class::FALLBACK)
end
context 'with should_raise_for_dev? false' do
let(:should_raise_for_dev) { false }
it 'return the default fallback' do
expect(subject.value).to eq(described_class::FALLBACK)
end
end
context 'with should_raise_for_dev? true' do
let(:should_raise_for_dev) { true }
it 'raises an error' do
expect { subject.value }.to raise_error('Error')
end
end
end
end

View file

@ -925,10 +925,25 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
context 'when retrieve component setting meets exception' do
it 'returns -1 for component enable status' do
before do
allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
allow(Settings).to receive(:[]).with(component).and_raise(StandardError)
end
expect(subject).to eq({ enabled: -1 })
context 'with should_raise_for_dev? false' do
let(:should_raise_for_dev) { false }
it 'returns -1 for component enable status' do
expect(subject).to eq({ enabled: -1 })
end
end
context 'with should_raise_for_dev? true' do
let(:should_raise_for_dev) { true }
it 'raises an error' do
expect { subject.value }.to raise_error(StandardError)
end
end
end
end

View file

@ -5,11 +5,13 @@ require 'spec_helper'
RSpec.describe Gitlab::Utils::UsageData do
include Database::DatabaseHelpers
shared_examples 'failing hardening method' do
shared_examples 'failing hardening method' do |raised_exception|
let(:exception) { raised_exception || ActiveRecord::StatementInvalid }
before do
allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
stub_const("Gitlab::Utils::UsageData::FALLBACK", fallback)
allow(failing_class).to receive(failing_method).and_raise(ActiveRecord::StatementInvalid)
allow(failing_class).to receive(failing_method).and_raise(exception) unless failing_class.nil?
end
context 'with should_raise_for_dev? false' do
@ -24,7 +26,7 @@ RSpec.describe Gitlab::Utils::UsageData do
let(:should_raise_for_dev) { true }
it 'raises an error' do
expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
expect { subject }.to raise_error(exception)
end
end
end
@ -366,8 +368,13 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(described_class.add).to eq(0)
end
it 'returns the fallback value when adding fails' do
expect(described_class.add(nil, 3)).to eq(-1)
context 'when adding fails' do
subject { described_class.add(nil, 3) }
let(:fallback) { -1 }
let(:failing_class) { nil }
it_behaves_like 'failing hardening method', StandardError
end
it 'returns the fallback value one of the arguments is negative' do
@ -376,8 +383,13 @@ RSpec.describe Gitlab::Utils::UsageData do
end
describe '#alt_usage_data' do
it 'returns the fallback when it gets an error' do
expect(described_class.alt_usage_data { raise StandardError } ).to eq(-1)
context 'when method fails' do
subject { described_class.alt_usage_data { raise StandardError } }
let(:fallback) { -1 }
let(:failing_class) { nil }
it_behaves_like 'failing hardening method', StandardError
end
it 'returns the evaluated block when give' do
@ -391,14 +403,22 @@ RSpec.describe Gitlab::Utils::UsageData do
describe '#redis_usage_data' do
context 'with block given' do
it 'returns the fallback when it gets an error' do
expect(described_class.redis_usage_data { raise ::Redis::CommandError } ).to eq(-1)
context 'when method fails' do
subject { described_class.redis_usage_data { raise ::Redis::CommandError } }
let(:fallback) { -1 }
let(:failing_class) { nil }
it_behaves_like 'failing hardening method', ::Redis::CommandError
end
it 'returns the fallback when Redis HLL raises any error' do
stub_const("Gitlab::Utils::UsageData::FALLBACK", 15)
context 'when Redis HLL raises any error' do
subject { described_class.redis_usage_data { raise Gitlab::UsageDataCounters::HLLRedisCounter::CategoryMismatch } }
expect(described_class.redis_usage_data { raise Gitlab::UsageDataCounters::HLLRedisCounter::CategoryMismatch } ).to eq(15)
let(:fallback) { 15 }
let(:failing_class) { nil }
it_behaves_like 'failing hardening method', Gitlab::UsageDataCounters::HLLRedisCounter::CategoryMismatch
end
it 'returns the evaluated block when given' do
@ -407,9 +427,14 @@ RSpec.describe Gitlab::Utils::UsageData do
end
context 'with counter given' do
it 'returns the falback values for all counter keys when it gets an error' do
allow(::Gitlab::UsageDataCounters::WikiPageCounter).to receive(:totals).and_raise(::Redis::CommandError)
expect(described_class.redis_usage_data(::Gitlab::UsageDataCounters::WikiPageCounter)).to eql(::Gitlab::UsageDataCounters::WikiPageCounter.fallback_totals)
context 'when gets an error' do
subject { described_class.redis_usage_data(::Gitlab::UsageDataCounters::WikiPageCounter) }
let(:fallback) { ::Gitlab::UsageDataCounters::WikiPageCounter.fallback_totals }
let(:failing_class) { ::Gitlab::UsageDataCounters::WikiPageCounter }
let(:failing_method) { :totals }
it_behaves_like 'failing hardening method', ::Redis::CommandError
end
it 'returns the totals when couter is given' do

View file

@ -1167,9 +1167,13 @@ RSpec.describe GroupPolicy do
end
context 'when crm_enabled is false' do
let(:group) { create(:group, :crm_enabled) }
let(:current_user) { owner }
before_all do
group.crm_settings.enabled = false
group.crm_settings.save!
end
it { is_expected.to be_disallowed(:read_crm_contact) }
it { is_expected.to be_disallowed(:read_crm_organization) }
it { is_expected.to be_disallowed(:admin_crm_contact) }

View file

@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe LooseForeignKeys::CleanupWorker do
include MigrationsHelpers
using RSpec::Parameterized::TableSyntax
def create_table_structure
migration = ActiveRecord::Migration.new.extend(Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers)
@ -149,4 +150,31 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
expect { described_class.new.perform }.not_to change { LooseForeignKeys::DeletedRecord.status_processed.count }
end
end
describe 'multi-database support' do
where(:current_minute, :configured_base_models, :expected_connection) do
2 | { main: ApplicationRecord, ci: Ci::ApplicationRecord } | ApplicationRecord.connection
3 | { main: ApplicationRecord, ci: Ci::ApplicationRecord } | Ci::ApplicationRecord.connection
2 | { main: ApplicationRecord } | ApplicationRecord.connection
3 | { main: ApplicationRecord } | ApplicationRecord.connection
end
with_them do
before do
allow(Gitlab::Database).to receive(:database_base_models).and_return(configured_base_models)
end
it 'uses the correct connection' do
LooseForeignKeys::DeletedRecord.count.times do
expect_next_found_instance_of(LooseForeignKeys::DeletedRecord) do |instance|
expect(instance.class.connection).to eq(expected_connection)
end
end
travel_to DateTime.new(2019, 1, 1, 10, current_minute) do
described_class.new.perform
end
end
end
end
end