Skip to content
Snippets Groups Projects
Commit 6b833f1e authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 88a08249
No related branches found
No related tags found
No related merge requests found
Showing
with 562 additions and 157 deletions
Loading
@@ -8,7 +8,7 @@ module Gitlab
Loading
@@ -8,7 +8,7 @@ module Gitlab
def initialize(commit) def initialize(commit)
@commit = commit @commit = commit
   
repo = commit.project.repository.raw_repository repo = commit.container.repository.raw_repository
@signature_data = Gitlab::Git::Commit.extract_signature_lazily(repo, commit.sha || commit.id) @signature_data = Gitlab::Git::Commit.extract_signature_lazily(repo, commit.sha || commit.id)
   
lazy_signature lazy_signature
Loading
Loading
Loading
@@ -340,6 +340,9 @@ msgstr ""
Loading
@@ -340,6 +340,9 @@ msgstr ""
msgid "%{name}'s avatar" msgid "%{name}'s avatar"
msgstr "" msgstr ""
   
msgid "%{numberOfDays} days"
msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead" msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "" msgstr ""
   
Loading
@@ -537,6 +540,9 @@ msgstr ""
Loading
@@ -537,6 +540,9 @@ msgstr ""
msgid "+%{extraOptionCount} more" msgid "+%{extraOptionCount} more"
msgstr "" msgstr ""
   
msgid "+%{tags} more"
msgstr ""
msgid ", or " msgid ", or "
msgstr "" msgstr ""
   
Loading
@@ -2146,6 +2152,9 @@ msgstr ""
Loading
@@ -2146,6 +2152,9 @@ msgstr ""
msgid "Are you sure you want to cancel editing this comment?" msgid "Are you sure you want to cancel editing this comment?"
msgstr "" msgstr ""
   
msgid "Are you sure you want to delete %{name}?"
msgstr ""
msgid "Are you sure you want to delete these artifacts?" msgid "Are you sure you want to delete these artifacts?"
msgstr "" msgstr ""
   
Loading
@@ -2411,6 +2420,9 @@ msgstr ""
Loading
@@ -2411,6 +2420,9 @@ msgstr ""
msgid "Author" msgid "Author"
msgstr "" msgstr ""
   
msgid "Authored %{timeago} by %{author}"
msgstr ""
msgid "Authorization code:" msgid "Authorization code:"
msgstr "" msgstr ""
   
Loading
@@ -5903,6 +5915,9 @@ msgstr ""
Loading
@@ -5903,6 +5915,9 @@ msgstr ""
msgid "CycleAnalytics|Tasks by type" msgid "CycleAnalytics|Tasks by type"
msgstr "" msgstr ""
   
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr ""
msgid "CycleAnalytics|Total days to completion" msgid "CycleAnalytics|Total days to completion"
msgstr "" msgstr ""
   
Loading
@@ -6918,6 +6933,9 @@ msgstr ""
Loading
@@ -6918,6 +6933,9 @@ msgstr ""
msgid "Edit your most recent comment in a thread (from an empty textarea)" msgid "Edit your most recent comment in a thread (from an empty textarea)"
msgstr "" msgstr ""
   
msgid "Edited %{timeago}"
msgstr ""
msgid "Editing" msgid "Editing"
msgstr "" msgstr ""
   
Loading
@@ -13266,6 +13284,18 @@ msgstr ""
Loading
@@ -13266,6 +13284,18 @@ msgstr ""
msgid "PackageRegistry|yarn" msgid "PackageRegistry|yarn"
msgstr "" msgstr ""
   
msgid "PackageType|Conan"
msgstr ""
msgid "PackageType|Maven"
msgstr ""
msgid "PackageType|NPM"
msgstr ""
msgid "PackageType|NuGet"
msgstr ""
msgid "Packages" msgid "Packages"
msgstr "" msgstr ""
   
Loading
@@ -18669,6 +18699,9 @@ msgstr ""
Loading
@@ -18669,6 +18699,9 @@ msgstr ""
msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential." msgid "The application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential."
msgstr "" msgstr ""
   
msgid "The associated issue #%{issueId} has been closed as the error is now resolved."
msgstr ""
msgid "The branch for this project has no active pipeline configuration." msgid "The branch for this project has no active pipeline configuration."
msgstr "" msgstr ""
   
Loading
@@ -22155,6 +22188,9 @@ msgstr ""
Loading
@@ -22155,6 +22188,9 @@ msgstr ""
msgid "by" msgid "by"
msgstr "" msgstr ""
   
msgid "by %{user}"
msgstr ""
msgid "cannot be changed if a personal project has container registry tags." msgid "cannot be changed if a personal project has container registry tags."
msgstr "" msgstr ""
   
Loading
Loading
Loading
@@ -39,8 +39,8 @@
Loading
@@ -39,8 +39,8 @@
"@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-syntax-import-meta": "^7.2.0", "@babel/plugin-syntax-import-meta": "^7.2.0",
"@babel/preset-env": "^7.6.2", "@babel/preset-env": "^7.6.2",
"@gitlab/svgs": "^1.91.0", "@gitlab/svgs": "^1.94.0",
"@gitlab/ui": "^9.0.0", "@gitlab/ui": "^9.3.0",
"@gitlab/visual-review-tools": "1.5.1", "@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2", "@sentry/browser": "^5.10.2",
"@sourcegraph/code-host-integration": "0.0.21", "@sourcegraph/code-host-integration": "0.0.21",
Loading
Loading
# frozen_string_literal: true
require_relative '../../migration_helpers'
require_relative '../../code_reuse_helpers'
module RuboCop
module Cop
module Scalability
class BulkPerformWithContext < RuboCop::Cop::Cop
include RuboCop::MigrationHelpers
include RuboCop::CodeReuseHelpers
MSG = <<~MSG
Prefer using `Worker.bulk_perform_async_with_contexts` and
`Worker.bulk_perform_in_with_context` over the methods without a context
if your worker deals with specific projects or namespaces
The context is required to add metadata to our logs.
If there is already a parent context that will apply to the jobs
being scheduled, please disable this cop with a comment explaing which
context will be applied.
Read more about it https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#worker-context
MSG
def_node_matcher :schedules_in_batch_without_context?, <<~PATTERN
(send (...) {:bulk_perform_async :bulk_perform_in} _*)
PATTERN
def on_send(node)
return if in_migration?(node) || in_spec?(node)
return unless schedules_in_batch_without_context?(node)
return if name_of_receiver(node) == "BackgroundMigrationWorker"
add_offense(node, location: :expression)
end
private
def in_spec?(node)
file_path_for_node(node).end_with?("_spec.rb")
end
end
end
end
end
# frozen_string_literal: true
module RuboCop
module Cop
module Scalability
class CronWorkerContext < RuboCop::Cop::Cop
MSG = <<~MSG
Manually define an ApplicationContext for cronjob-workers. The context
is required to add metadata to our logs.
If there is no relevant metadata, please disable the cop with a comment
explaining this.
Read more about it https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#worker-context
MSG
def_node_matcher :includes_cronjob_queue?, <<~PATTERN
(send nil? :include (const nil? :CronjobQueue))
PATTERN
def_node_search :defines_contexts?, <<~PATTERN
(send nil? :with_context _)
PATTERN
def_node_search :schedules_with_batch_context?, <<~PATTERN
(send (...) {:bulk_perform_async_with_contexts :bulk_perform_in_with_contexts} (...))
PATTERN
def on_send(node)
return unless includes_cronjob_queue?(node)
return if defines_contexts?(node.parent)
return if schedules_with_batch_context?(node.parent)
add_offense(node.arguments.first, location: :expression)
end
end
end
end
end
Loading
@@ -44,6 +44,8 @@ require_relative 'cop/qa/element_with_pattern'
Loading
@@ -44,6 +44,8 @@ require_relative 'cop/qa/element_with_pattern'
require_relative 'cop/qa/ambiguous_page_object_name' require_relative 'cop/qa/ambiguous_page_object_name'
require_relative 'cop/sidekiq_options_queue' require_relative 'cop/sidekiq_options_queue'
require_relative 'cop/scalability/file_uploads' require_relative 'cop/scalability/file_uploads'
require_relative 'cop/scalability/bulk_perform_with_context'
require_relative 'cop/scalability/cron_worker_context'
require_relative 'cop/destroy_all' require_relative 'cop/destroy_all'
require_relative 'cop/ruby_interpolation_in_translation' require_relative 'cop/ruby_interpolation_in_translation'
require_relative 'code_reuse_helpers' require_relative 'code_reuse_helpers'
Loading
Loading
Loading
@@ -3,6 +3,18 @@ import Icon from '~/vue_shared/components/icon.vue';
Loading
@@ -3,6 +3,18 @@ import Icon from '~/vue_shared/components/icon.vue';
import DiffStats from '~/diffs/components/diff_stats.vue'; import DiffStats from '~/diffs/components/diff_stats.vue';
   
describe('diff_stats', () => { describe('diff_stats', () => {
it('does not render a group if diffFileLengths is empty', () => {
const wrapper = shallowMount(DiffStats, {
propsData: {
addedLines: 1,
removedLines: 2,
},
});
const groups = wrapper.findAll('.diff-stats-group');
expect(groups.length).toBe(2);
});
it('does not render a group if diffFileLengths is not a number', () => { it('does not render a group if diffFileLengths is not a number', () => {
const wrapper = shallowMount(DiffStats, { const wrapper = shallowMount(DiffStats, {
propsData: { propsData: {
Loading
Loading
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { GlLoadingIcon, GlLink, GlBadge, GlFormInput } from '@gitlab/ui'; import { GlLoadingIcon, GlLink, GlBadge, GlFormInput, GlAlert, GlSprintf } from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue'; import LoadingButton from '~/vue_shared/components/loading_button.vue';
import Stacktrace from '~/error_tracking/components/stacktrace.vue'; import Stacktrace from '~/error_tracking/components/stacktrace.vue';
import ErrorDetails from '~/error_tracking/components/error_details.vue'; import ErrorDetails from '~/error_tracking/components/error_details.vue';
Loading
@@ -28,7 +28,7 @@ describe('ErrorDetails', () => {
Loading
@@ -28,7 +28,7 @@ describe('ErrorDetails', () => {
   
function mountComponent() { function mountComponent() {
wrapper = shallowMount(ErrorDetails, { wrapper = shallowMount(ErrorDetails, {
stubs: { LoadingButton }, stubs: { LoadingButton, GlSprintf },
localVue, localVue,
store, store,
mocks, mocks,
Loading
@@ -62,7 +62,7 @@ describe('ErrorDetails', () => {
Loading
@@ -62,7 +62,7 @@ describe('ErrorDetails', () => {
startPollingDetails: () => {}, startPollingDetails: () => {},
startPollingStacktrace: () => {}, startPollingStacktrace: () => {},
updateIgnoreStatus: jest.fn(), updateIgnoreStatus: jest.fn(),
updateResolveStatus: jest.fn(), updateResolveStatus: jest.fn().mockResolvedValue({ closed_issue_iid: 1 }),
}; };
   
getters = { getters = {
Loading
@@ -313,6 +313,20 @@ describe('ErrorDetails', () => {
Loading
@@ -313,6 +313,20 @@ describe('ErrorDetails', () => {
expect.objectContaining({ status: errorStatus.UNRESOLVED }), expect.objectContaining({ status: errorStatus.UNRESOLVED }),
); );
}); });
it('should show alert with closed issueId', () => {
const findAlert = () => wrapper.find(GlAlert);
const closedIssueId = 123;
wrapper.setData({
isAlertVisible: true,
closedIssueId,
});
return wrapper.vm.$nextTick().then(() => {
expect(findAlert().exists()).toBe(true);
expect(findAlert().text()).toContain(`#${closedIssueId}`);
});
});
}); });
}); });
   
Loading
Loading
Loading
@@ -6,6 +6,7 @@ exports[`User Operation confirmation modal renders modal with form included 1`]
Loading
@@ -6,6 +6,7 @@ exports[`User Operation confirmation modal renders modal with form included 1`]
modalid="user-operation-modal" modalid="user-operation-modal"
ok-title="action" ok-title="action"
ok-variant="warning" ok-variant="warning"
size="md"
title="title" title="title"
titletag="h4" titletag="h4"
> >
Loading
Loading
Loading
@@ -61,6 +61,7 @@ exports[`self monitor component When the self monitor project has not been creat
Loading
@@ -61,6 +61,7 @@ exports[`self monitor component When the self monitor project has not been creat
modalid="delete-self-monitor-modal" modalid="delete-self-monitor-modal"
ok-title="Delete project" ok-title="Delete project"
ok-variant="danger" ok-variant="danger"
size="md"
title="Disable self monitoring?" title="Disable self monitoring?"
titletag="h4" titletag="h4"
> >
Loading
Loading
Loading
@@ -3,20 +3,34 @@
Loading
@@ -3,20 +3,34 @@
require 'spec_helper' require 'spec_helper'
   
describe Gitlab::Diff::Formatters::ImageFormatter do describe Gitlab::Diff::Formatters::ImageFormatter do
it_behaves_like "position formatter" do let(:base_attrs) do
let(:base_attrs) do {
{ base_sha: 123,
base_sha: 123, start_sha: 456,
start_sha: 456, head_sha: 789,
head_sha: 789, old_path: 'old_image.png',
old_path: 'old_image.png', new_path: 'new_image.png',
new_path: 'new_image.png', position_type: 'image'
position_type: 'image' }
} end
end
let(:attrs) do
base_attrs.merge(width: 100, height: 100, x: 1, y: 2)
end
it_behaves_like 'position formatter'
describe '#==' do
subject { described_class.new(attrs) }
it { is_expected.to eq(subject) }
[:width, :height, :x, :y].each do |attr|
let(:other_formatter) do
described_class.new(attrs.merge(attr => 9))
end
   
let(:attrs) do it { is_expected.not_to eq(other_formatter) }
base_attrs.merge(width: 100, height: 100, x: 1, y: 2)
end end
end end
end end
Loading
@@ -106,6 +106,14 @@ describe Project do
Loading
@@ -106,6 +106,14 @@ describe Project do
it { is_expected.to have_many(:sourced_pipelines) } it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_many(:source_pipelines) } it { is_expected.to have_many(:source_pipelines) }
   
it_behaves_like 'model with repository' do
let_it_be(:container) { create(:project, :repository, path: 'somewhere') }
let(:stubbed_container) { build_stubbed(:project) }
let(:expected_full_path) { "#{container.namespace.full_path}/somewhere" }
let(:expected_repository_klass) { Repository }
let(:expected_storage_klass) { Storage::Hashed }
end
it 'has an inverse relationship with merge requests' do it 'has an inverse relationship with merge requests' do
expect(described_class.reflect_on_association(:merge_requests).has_inverse?).to eq(:target_project) expect(described_class.reflect_on_association(:merge_requests).has_inverse?).to eq(:target_project)
end end
Loading
@@ -510,7 +518,6 @@ describe Project do
Loading
@@ -510,7 +518,6 @@ describe Project do
   
describe 'Respond to' do describe 'Respond to' do
it { is_expected.to respond_to(:url_to_repo) } it { is_expected.to respond_to(:url_to_repo) }
it { is_expected.to respond_to(:repo_exists?) }
it { is_expected.to respond_to(:execute_hooks) } it { is_expected.to respond_to(:execute_hooks) }
it { is_expected.to respond_to(:owner) } it { is_expected.to respond_to(:owner) }
it { is_expected.to respond_to(:path_with_namespace) } it { is_expected.to respond_to(:path_with_namespace) }
Loading
@@ -664,44 +671,6 @@ describe Project do
Loading
@@ -664,44 +671,6 @@ describe Project do
expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git') expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git')
end end
   
describe "#web_url" do
let(:project) { create(:project, path: "somewhere") }
context 'when given the only_path option' do
subject { project.web_url(only_path: only_path) }
context 'when only_path is false' do
let(:only_path) { false }
it 'returns the full web URL for this repo' do
expect(subject).to eq("#{Gitlab.config.gitlab.url}/#{project.namespace.full_path}/somewhere")
end
end
context 'when only_path is true' do
let(:only_path) { true }
it 'returns the relative web URL for this repo' do
expect(subject).to eq("/#{project.namespace.full_path}/somewhere")
end
end
context 'when only_path is nil' do
let(:only_path) { nil }
it 'returns the full web URL for this repo' do
expect(subject).to eq("#{Gitlab.config.gitlab.url}/#{project.namespace.full_path}/somewhere")
end
end
end
context 'when not given the only_path option' do
it 'returns the full web URL for this repo' do
expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.namespace.full_path}/somewhere")
end
end
end
describe "#readme_url" do describe "#readme_url" do
context 'with a non-existing repository' do context 'with a non-existing repository' do
let(:project) { create(:project) } let(:project) { create(:project) }
Loading
@@ -931,14 +900,6 @@ describe Project do
Loading
@@ -931,14 +900,6 @@ describe Project do
end end
end end
   
describe '#repository' do
let(:project) { create(:project, :repository) }
it 'returns valid repo' do
expect(project.repository).to be_kind_of(Repository)
end
end
describe '#default_issues_tracker?' do describe '#default_issues_tracker?' do
it "is true if used internal tracker" do it "is true if used internal tracker" do
project = build(:project) project = build(:project)
Loading
@@ -954,24 +915,6 @@ describe Project do
Loading
@@ -954,24 +915,6 @@ describe Project do
end end
end end
   
describe '#empty_repo?' do
context 'when the repo does not exist' do
let(:project) { build_stubbed(:project) }
it 'returns true' do
expect(project.empty_repo?).to be(true)
end
end
context 'when the repo exists' do
let(:project) { create(:project, :repository) }
let(:empty_project) { create(:project, :empty_repo) }
it { expect(empty_project.empty_repo?).to be(true) }
it { expect(project.empty_repo?).to be(false) }
end
end
describe '#external_issue_tracker' do describe '#external_issue_tracker' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:ext_project) { create(:redmine_project) } let(:ext_project) { create(:redmine_project) }
Loading
@@ -3406,59 +3349,6 @@ describe Project do
Loading
@@ -3406,59 +3349,6 @@ describe Project do
end end
end end
   
describe '#http_url_to_repo' do
let(:project) { create(:project) }
context 'when a custom HTTP clone URL root is not set' do
it 'returns the url to the repo without a username' do
expect(project.http_url_to_repo).to eq("#{project.web_url}.git")
expect(project.http_url_to_repo).not_to include('@')
end
end
context 'when a custom HTTP clone URL root is set' do
before do
stub_application_setting(custom_http_clone_url_root: custom_http_clone_url_root)
end
context 'when custom HTTP clone URL root has a relative URL root' do
context 'when custom HTTP clone URL root ends with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234/mygitlab/' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(project.http_url_to_repo).to eq("https://git.example.com:51234/mygitlab/#{project.full_path}.git")
end
end
context 'when custom HTTP clone URL root does not end with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234/mygitlab' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(project.http_url_to_repo).to eq("https://git.example.com:51234/mygitlab/#{project.full_path}.git")
end
end
end
context 'when custom HTTP clone URL root does not have a relative URL root' do
context 'when custom HTTP clone URL root ends with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234/' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(project.http_url_to_repo).to eq("https://git.example.com:51234/#{project.full_path}.git")
end
end
context 'when custom HTTP clone URL root does not end with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(project.http_url_to_repo).to eq("https://git.example.com:51234/#{project.full_path}.git")
end
end
end
end
end
describe '#lfs_http_url_to_repo' do describe '#lfs_http_url_to_repo' do
let(:project) { create(:project) } let(:project) { create(:project) }
   
Loading
@@ -5054,16 +4944,6 @@ describe Project do
Loading
@@ -5054,16 +4944,6 @@ describe Project do
end end
end end
   
context '#commits_by' do
let(:project) { create(:project, :repository) }
let(:commits) { project.repository.commits('HEAD', limit: 3).commits }
let(:commit_shas) { commits.map(&:id) }
it 'retrieves several commits from the repository by oid' do
expect(project.commits_by(oids: commit_shas)).to eq commits
end
end
context '#members_among' do context '#members_among' do
let(:users) { create_list(:user, 3) } let(:users) { create_list(:user, 3) }
   
Loading
Loading
Loading
@@ -4084,4 +4084,46 @@ describe User, :do_not_mock_admin_mode do
Loading
@@ -4084,4 +4084,46 @@ describe User, :do_not_mock_admin_mode do
end end
end end
end end
describe '#read_only_attribute?' do
context 'when LDAP server is enabled' do
before do
allow(Gitlab::Auth::LDAP::Config).to receive(:enabled?).and_return(true)
end
%i[name email location].each do |attribute|
it "is true for #{attribute}" do
expect(subject.read_only_attribute?(attribute)).to be_truthy
end
end
context 'and ldap_readonly_attributes feature is disabled' do
before do
stub_feature_flags(ldap_readonly_attributes: false)
end
%i[name email location].each do |attribute|
it "is false" do
expect(subject.read_only_attribute?(attribute)).to be_falsey
end
end
end
end
context 'when synced attributes metadata is present' do
it 'delegates to synced_attributes_metadata' do
subject.build_user_synced_attributes_metadata
expect(subject.build_user_synced_attributes_metadata)
.to receive(:read_only?).with(:email).and_return('return-value')
expect(subject.read_only_attribute?(:email)).to eq('return-value')
end
end
context 'when synced attributes metadata is present' do
it 'is false for any attribute' do
expect(subject.read_only_attribute?(:email)).to be_falsey
end
end
end
end end
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../support/helpers/expect_offense'
require_relative '../../../../rubocop/cop/scalability/bulk_perform_with_context'
describe RuboCop::Cop::Scalability::BulkPerformWithContext do
include CopHelper
include ExpectOffense
subject(:cop) { described_class.new }
it "adds an offense when calling bulk_perform_async" do
inspect_source(<<~CODE.strip_indent)
Worker.bulk_perform_async(args)
CODE
expect(cop.offenses.size).to eq(1)
end
it "adds an offense when calling bulk_perform_in" do
inspect_source(<<~CODE.strip_indent)
diffs.each_batch(of: BATCH_SIZE) do |relation, index|
ids = relation.pluck_primary_key.map { |id| [id] }
DeleteDiffFilesWorker.bulk_perform_in(index * 5.minutes, ids)
end
CODE
expect(cop.offenses.size).to eq(1)
end
it "does not add an offense for migrations" do
allow(cop).to receive(:in_migration?).and_return(true)
inspect_source(<<~CODE.strip_indent)
Worker.bulk_perform_in(args)
CODE
expect(cop.offenses.size).to eq(0)
end
it "does not add an offence for specs" do
allow(cop).to receive(:in_spec?).and_return(true)
inspect_source(<<~CODE.strip_indent)
Worker.bulk_perform_in(args)
CODE
expect(cop.offenses.size).to eq(0)
end
it "does not add an offense for scheduling BackgroundMigrations" do
inspect_source(<<~CODE.strip_indent)
BackgroundMigrationWorker.bulk_perform_in(args)
CODE
expect(cop.offenses.size).to eq(0)
end
end
# frozen_string_literal: true
require 'fast_spec_helper'
require 'rubocop'
require_relative '../../../support/helpers/expect_offense'
require_relative '../../../../rubocop/cop/scalability/cron_worker_context'
describe RuboCop::Cop::Scalability::CronWorkerContext do
include CopHelper
include ExpectOffense
subject(:cop) { described_class.new }
it 'adds an offense when including CronjobQueue' do
inspect_source(<<~CODE.strip_indent)
class SomeWorker
include CronjobQueue
end
CODE
expect(cop.offenses.size).to eq(1)
end
it 'does not add offenses for other workers' do
expect_no_offenses(<<~CODE.strip_indent)
class SomeWorker
end
CODE
end
it 'does not add an offense when the class defines a context' do
expect_no_offenses(<<~CODE.strip_indent)
class SomeWorker
include CronjobQueue
with_context user: 'bla'
end
CODE
end
it 'does not add an offense when the worker calls `with_context`' do
expect_no_offenses(<<~CODE.strip_indent)
class SomeWorker
include CronjobQueue
def perform
with_context(user: 'bla') do
# more work
end
end
end
CODE
end
it 'does not add an offense when the worker calls `bulk_perform_async_with_contexts`' do
expect_no_offenses(<<~CODE.strip_indent)
class SomeWorker
include CronjobQueue
def perform
SomeOtherWorker.bulk_perform_async_with_contexts(contexts_for_arguments)
end
end
CODE
end
it 'does not add an offense when the worker calls `bulk_perform_in_with_contexts`' do
expect_no_offenses(<<~CODE.strip_indent)
class SomeWorker
include CronjobQueue
def perform
SomeOtherWorker.bulk_perform_in_with_contexts(contexts_for_arguments)
end
end
CODE
end
end
Loading
@@ -55,6 +55,15 @@ describe Users::UpdateService do
Loading
@@ -55,6 +55,15 @@ describe Users::UpdateService do
expect(result[:message]).to eq("Emoji is not included in the list") expect(result[:message]).to eq("Emoji is not included in the list")
end end
   
it 'ignores read-only attributes' do
allow(user).to receive(:read_only_attribute?).with(:name).and_return(true)
expect do
update_user(user, name: 'changed' + user.name)
user.reload
end.not_to change { user.name }
end
def update_user(user, opts) def update_user(user, opts)
described_class.new(user, opts.merge(user: user)).execute described_class.new(user, opts.merge(user: user)).execute
end end
Loading
Loading
# frozen_string_literal: true
RSpec.shared_examples 'model with repository' do
describe '#commits_by' do
let(:commits) { container.repository.commits('HEAD', limit: 3).commits }
let(:commit_shas) { commits.map(&:id) }
it 'retrieves several commits from the repository by oid' do
expect(container.commits_by(oids: commit_shas)).to eq commits
end
end
describe "#web_url" do
context 'when given the only_path option' do
subject { container.web_url(only_path: only_path) }
context 'when only_path is false' do
let(:only_path) { false }
it 'returns the full web URL for this repo' do
expect(subject).to eq("#{Gitlab.config.gitlab.url}/#{expected_full_path}")
end
end
context 'when only_path is true' do
let(:only_path) { true }
it 'returns the relative web URL for this repo' do
expect(subject).to eq("/#{expected_full_path}")
end
end
context 'when only_path is nil' do
let(:only_path) { nil }
it 'returns the full web URL for this repo' do
expect(subject).to eq("#{Gitlab.config.gitlab.url}/#{expected_full_path}")
end
end
end
context 'when not given the only_path option' do
it 'returns the full web URL for this repo' do
expect(container.web_url).to eq("#{Gitlab.config.gitlab.url}/#{expected_full_path}")
end
end
end
describe '#ssh_url_to_repo' do
it 'returns container ssh address' do
expect(container.ssh_url_to_repo).to eq container.url_to_repo
end
end
describe '#http_url_to_repo' do
subject { container.http_url_to_repo }
context 'when a custom HTTP clone URL root is not set' do
it 'returns the url to the repo without a username' do
expect(subject).to eq("#{container.web_url}.git")
expect(subject).not_to include('@')
end
end
context 'when a custom HTTP clone URL root is set' do
before do
stub_application_setting(custom_http_clone_url_root: custom_http_clone_url_root)
end
context 'when custom HTTP clone URL root has a relative URL root' do
context 'when custom HTTP clone URL root ends with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234/mygitlab/' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(subject).to eq("#{custom_http_clone_url_root}#{expected_full_path}.git")
end
end
context 'when custom HTTP clone URL root does not end with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234/mygitlab' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(subject).to eq("#{custom_http_clone_url_root}/#{expected_full_path}.git")
end
end
end
context 'when custom HTTP clone URL root does not have a relative URL root' do
context 'when custom HTTP clone URL root ends with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234/' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(subject).to eq("#{custom_http_clone_url_root}#{expected_full_path}.git")
end
end
context 'when custom HTTP clone URL root does not end with a slash' do
let(:custom_http_clone_url_root) { 'https://git.example.com:51234' }
it 'returns the url to the repo, with the root replaced with the custom one' do
expect(subject).to eq("#{custom_http_clone_url_root}/#{expected_full_path}.git")
end
end
end
end
end
describe '#repository' do
it 'returns valid repo' do
expect(container.repository).to be_kind_of(expected_repository_klass)
end
end
describe '#storage' do
it 'returns valid storage' do
expect(container.storage).to be_kind_of(expected_storage_klass)
end
end
describe '#full_path' do
it 'returns valid full_path' do
expect(container.full_path).to eq(expected_full_path)
end
end
describe '#empty_repo?' do
context 'when the repo does not exist' do
it 'returns true' do
expect(stubbed_container.empty_repo?).to be(true)
end
end
context 'when the repo exists' do
it { expect(container.empty_repo?).to be(false) }
it 'returns true when repository is empty' do
allow(container.repository).to receive(:empty?).and_return(true)
expect(container.empty_repo?).to be(true)
end
end
end
describe '#valid_repo?' do
it { expect(stubbed_container.valid_repo?).to be(false)}
it { expect(container.valid_repo?).to be(true) }
end
describe '#repository_exists?' do
it { expect(stubbed_container.repository_exists?).to be(false)}
it { expect(container.repository_exists?).to be(true) }
end
describe '#repo_exists?' do
it { expect(stubbed_container.repo_exists?).to be(false)}
it { expect(container.repo_exists?).to be(true) }
end
describe '#root_ref' do
let(:root_ref) { container.repository.root_ref }
it { expect(container.root_ref?(root_ref)).to be(true) }
it { expect(container.root_ref?('HEAD')).to be(false) }
it { expect(container.root_ref?('foo')).to be(false) }
end
describe 'Respond to' do
it { is_expected.to respond_to(:base_dir) }
it { is_expected.to respond_to(:disk_path) }
end
end
Loading
@@ -10,7 +10,7 @@ describe CronjobQueue do
Loading
@@ -10,7 +10,7 @@ describe CronjobQueue do
end end
   
include ApplicationWorker include ApplicationWorker
include CronjobQueue include CronjobQueue # rubocop:disable Scalability/CronWorkerContext
end end
end end
   
Loading
Loading
Loading
@@ -736,15 +736,15 @@
Loading
@@ -736,15 +736,15 @@
dependencies: dependencies:
vue-eslint-parser "^6.0.4" vue-eslint-parser "^6.0.4"
   
"@gitlab/svgs@^1.91.0": "@gitlab/svgs@^1.94.0":
version "1.91.0" version "1.94.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.91.0.tgz#cf7b28e43779a929a438dcc0c51f39f92551e58e" resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.94.0.tgz#d6a39f982811f82d942692a91bf2678961752eba"
integrity sha512-Sz8aaaNnUUtlrk/FPf6FNceu4XsDLBh6g/c6nmzDVGF9kHrfiXfWL0tYAax8vhkrld5vewGHE0bRpq2ZILq0pw== integrity sha512-lB7HTVsNPBLUEgNUXLLC4V/XJsWg7aSO7RBp6cuuL3n6fUS9VGfELH9aBnuPJglTHddktcnElkZ3S54XI8kYHw==
"@gitlab/ui@^9.0.0": "@gitlab/ui@^9.3.0":
version "9.0.0" version "9.3.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.0.0.tgz#16d637f47ba0537100fd1c6d452b56174b50171b" resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-9.3.0.tgz#851b4246c2e661a5a343184f74e0448c597ce28c"
integrity sha512-OfP8UAticpqKkqbPBZ+7bbCBsd9Fxq3eL55Uq5nEwxJ8gGXm+nSc+HFnbzX/ryv0iz5+7nCI4DfIfgy9E4QAeQ== integrity sha512-DB9Q8XDLfn3Ui6EfYTVnmHVYPwbukocYTWL+uD6zN3leiamYQqaoYGmtcrXk9oSiAyuJYwaJlCzlblG1GPwnfw==
dependencies: dependencies:
"@babel/standalone" "^7.0.0" "@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0" "@gitlab/vue-toasted" "^1.3.0"
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment