Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5ca32d2dac
commit
3e9e2cd52e
24 changed files with 237 additions and 70 deletions
|
@ -1 +1 @@
|
|||
1.45.0
|
||||
1.46.0
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
<script>
|
||||
import { GlButton } from '@gitlab/ui';
|
||||
import { mapActions } from 'vuex';
|
||||
import { GlButton, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { mapActions, mapState } from 'vuex';
|
||||
import { __ } from '~/locale';
|
||||
import Tracking from '~/tracking';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlButton,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
computed: {
|
||||
...mapState({ isNewListShowing: ({ addColumnForm }) => addColumnForm.visible }),
|
||||
tooltip() {
|
||||
return this.isNewListShowing ? __('The list creation wizard is already open') : '';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['setAddColumnFormVisibility']),
|
||||
handleClick() {
|
||||
|
@ -19,7 +29,14 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gl-ml-3 gl-display-flex gl-align-items-center" data-testid="boards-create-list">
|
||||
<gl-button variant="confirm" @click="handleClick">{{ __('Create list') }} </gl-button>
|
||||
<div
|
||||
v-gl-tooltip="tooltip"
|
||||
:tabindex="isNewListShowing ? '0' : undefined"
|
||||
class="gl-ml-3 gl-display-flex gl-align-items-center"
|
||||
data-testid="boards-create-list"
|
||||
>
|
||||
<gl-button :disabled="isNewListShowing" variant="confirm" @click="handleClick"
|
||||
>{{ __('Create list') }}
|
||||
</gl-button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: linear_ee_group_ancestor_scopes
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70708
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341350
|
||||
milestone: '14.4'
|
||||
type: development
|
||||
group: group::access
|
||||
default_enabled: false
|
|
@ -485,7 +485,7 @@ config:
|
|||
|
||||
agent:
|
||||
monitor:
|
||||
eventTypes: ["drop"]
|
||||
eventTypes: ["drop"] # Note: possible values are documented at https://docs.cilium.io/en/stable/cmdref/cilium_monitor/
|
||||
```
|
||||
|
||||
The Cilium monitor log for traffic is logged out by the
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module BulkImports
|
||||
module Groups
|
||||
module Common
|
||||
module Pipelines
|
||||
class BoardsPipeline
|
||||
include NdjsonPipeline
|
|
@ -36,7 +36,7 @@ module BulkImports
|
|||
stage: 1
|
||||
},
|
||||
boards: {
|
||||
pipeline: BulkImports::Groups::Pipelines::BoardsPipeline,
|
||||
pipeline: BulkImports::Common::Pipelines::BoardsPipeline,
|
||||
stage: 2
|
||||
},
|
||||
finisher: {
|
||||
|
|
|
@ -23,9 +23,13 @@ module BulkImports
|
|||
pipeline: BulkImports::Projects::Pipelines::IssuesPipeline,
|
||||
stage: 3
|
||||
},
|
||||
boards: {
|
||||
pipeline: BulkImports::Common::Pipelines::BoardsPipeline,
|
||||
stage: 4
|
||||
},
|
||||
finisher: {
|
||||
pipeline: BulkImports::Common::Pipelines::EntityFinisher,
|
||||
stage: 4
|
||||
stage: 5
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -11,14 +11,15 @@
|
|||
module Gitlab
|
||||
class SidekiqEnq
|
||||
def enqueue_jobs(now = Time.now.to_f.to_s, sorted_sets = Sidekiq::Scheduled::SETS)
|
||||
start_time = ::Gitlab::Metrics::System.monotonic_time
|
||||
jobs = redundant_jobs = 0
|
||||
Sidekiq.logger.info(message: 'Enqueuing scheduled jobs', status: 'start')
|
||||
|
||||
# A job's "score" in Redis is the time at which it should be processed.
|
||||
# Just check Redis for the set of jobs with a timestamp before now.
|
||||
Sidekiq.redis do |conn|
|
||||
sorted_sets.each do |sorted_set|
|
||||
start_time = ::Gitlab::Metrics::System.monotonic_time
|
||||
jobs = redundant_jobs = 0
|
||||
|
||||
Sidekiq.logger.info(message: 'Enqueuing scheduled jobs', status: 'start', sorted_set: sorted_set)
|
||||
|
||||
# Get the next item in the queue if it's score (time to execute) is <= now.
|
||||
# We need to go through the list one at a time to reduce the risk of something
|
||||
# going wrong between the time jobs are popped from the scheduled queue and when
|
||||
|
@ -35,11 +36,16 @@ module Gitlab
|
|||
redundant_jobs += 1
|
||||
end
|
||||
end
|
||||
|
||||
end_time = ::Gitlab::Metrics::System.monotonic_time
|
||||
Sidekiq.logger.info(message: 'Enqueuing scheduled jobs',
|
||||
status: 'done',
|
||||
sorted_set: sorted_set,
|
||||
jobs_count: jobs,
|
||||
redundant_jobs_count: redundant_jobs,
|
||||
duration_s: end_time - start_time)
|
||||
end
|
||||
end
|
||||
|
||||
end_time = ::Gitlab::Metrics::System.monotonic_time
|
||||
Sidekiq.logger.info(message: 'Enqueuing scheduled jobs', status: 'done', jobs_count: jobs, redundant_jobs_count: redundant_jobs, duration_s: end_time - start_time)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34065,6 +34065,9 @@ msgstr ""
|
|||
msgid "The license was successfully uploaded and will be active from %{starts_at}. You can see the details below."
|
||||
msgstr ""
|
||||
|
||||
msgid "The list creation wizard is already open"
|
||||
msgstr ""
|
||||
|
||||
msgid "The maximum file size allowed is %{size}."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ settings:
|
|||
jest:
|
||||
jestConfigFile: 'jest.config.js'
|
||||
globals:
|
||||
getJSONFixture: false
|
||||
loadFixtures: false
|
||||
setFixtures: false
|
||||
rules:
|
||||
|
|
|
@ -20,6 +20,11 @@ Did you run bin/rake frontend:fixtures?`,
|
|||
return fs.readFileSync(absolutePath, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `import` to load a JSON fixture instead.
|
||||
* See https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html#use-fixtures,
|
||||
* https://gitlab.com/gitlab-org/gitlab/-/issues/339346.
|
||||
*/
|
||||
export const getJSONFixture = (relativePath) => JSON.parse(getFixture(relativePath));
|
||||
|
||||
export const resetHTMLFixture = () => {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import { GlButton } from '@gitlab/ui';
|
||||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
|
||||
import { createStore } from '~/boards/stores';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
describe('BoardAddNewColumnTrigger', () => {
|
||||
let wrapper;
|
||||
|
||||
const findBoardsCreateList = () => wrapper.findByTestId('boards-create-list');
|
||||
const findTooltipText = () => getBinding(findBoardsCreateList().element, 'gl-tooltip');
|
||||
|
||||
const mountComponent = () => {
|
||||
wrapper = mountExtended(BoardAddNewColumnTrigger, {
|
||||
directives: {
|
||||
GlTooltip: createMockDirective(),
|
||||
},
|
||||
store: createStore(),
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mountComponent();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('when button is active', () => {
|
||||
it('does not show the tooltip', () => {
|
||||
const tooltip = findTooltipText();
|
||||
|
||||
expect(tooltip.value).toBe('');
|
||||
});
|
||||
|
||||
it('renders an enabled button', () => {
|
||||
const button = wrapper.find(GlButton);
|
||||
|
||||
expect(button.props('disabled')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when button is disabled', () => {
|
||||
it('shows the tooltip', async () => {
|
||||
wrapper.find(GlButton).vm.$emit('click');
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
const tooltip = findTooltipText();
|
||||
|
||||
expect(tooltip.value).toBe('The list creation wizard is already open');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,11 +1,13 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import jsYaml from 'js-yaml';
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
import { getJSONFixture } from 'helpers/fixtures';
|
||||
|
||||
export const loadMarkdownApiResult = (testName) => {
|
||||
const fixturePathPrefix = `api/markdown/${testName}.json`;
|
||||
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
const fixture = getJSONFixture(fixturePathPrefix);
|
||||
return fixture.body || fixture.html;
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* eslint-disable import/no-deprecated */
|
||||
|
||||
import { getJSONFixture } from 'helpers/fixtures';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
import $ from 'jquery';
|
||||
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
|
||||
import '~/lib/utils/common_utils';
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
import { getJSONFixture } from 'helpers/fixtures';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
|
||||
jest.mock('~/lib/utils/url_utility', () => ({
|
||||
|
@ -66,6 +68,7 @@ describe('deprecatedJQueryDropdown', () => {
|
|||
loadFixtures('static/deprecated_jquery_dropdown.html');
|
||||
test.dropdownContainerElement = $('.dropdown.inline');
|
||||
test.$dropdownMenuElement = $('.dropdown-menu', test.dropdownContainerElement);
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
test.projectsData = getJSONFixture('static/projects.json');
|
||||
});
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line import/no-deprecated
|
||||
import { getJSONFixture, setHTMLFixture } from 'helpers/fixtures';
|
||||
import FilterableList from '~/filterable_list';
|
||||
|
||||
|
@ -14,6 +15,7 @@ describe('FilterableList', () => {
|
|||
</div>
|
||||
<div class="js-projects-list-holder"></div>
|
||||
`);
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
getJSONFixture('static/projects.json');
|
||||
form = document.querySelector('form#project-filter-form');
|
||||
filter = document.querySelector('.js-projects-list-filter');
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// eslint-disable-next-line import/no-deprecated
|
||||
import { getJSONFixture, setHTMLFixture } from 'helpers/fixtures';
|
||||
import ProjectsFilterableList from '~/projects/projects_filterable_list';
|
||||
|
||||
|
@ -14,6 +15,7 @@ describe('ProjectsFilterableList', () => {
|
|||
</div>
|
||||
<div class="js-projects-list-holder"></div>
|
||||
`);
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
getJSONFixture('static/projects.json');
|
||||
form = document.querySelector('form#project-filter-form');
|
||||
filter = document.querySelector('.js-projects-list-filter');
|
||||
|
|
|
@ -6,7 +6,7 @@ import { setGlobalDateToFakeDate } from 'helpers/fake_date';
|
|||
import setWindowLocation from 'helpers/set_window_location_helper';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import Translate from '~/vue_shared/translate';
|
||||
import { getJSONFixture, loadHTMLFixture, setHTMLFixture } from './__helpers__/fixtures';
|
||||
import { loadHTMLFixture, setHTMLFixture } from './__helpers__/fixtures';
|
||||
import { initializeTestTimeout } from './__helpers__/timeout';
|
||||
import customMatchers from './matchers';
|
||||
import { setupManualMocks } from './mocks/mocks_helper';
|
||||
|
@ -43,7 +43,6 @@ Vue.use(Translate);
|
|||
|
||||
// convenience wrapper for migration from Karma
|
||||
Object.assign(global, {
|
||||
getJSONFixture,
|
||||
loadFixtures: loadHTMLFixture,
|
||||
setFixtures: setHTMLFixture,
|
||||
});
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
import { getJSONFixture } from 'helpers/fixtures';
|
||||
import { trimText } from 'helpers/text_helper';
|
||||
import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
|
||||
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
|
||||
|
@ -11,6 +13,7 @@ describe('ProjectListItem component', () => {
|
|||
let vm;
|
||||
let options;
|
||||
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
const project = getJSONFixture('static/projects.json')[0];
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -2,6 +2,8 @@ import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
|
|||
import { mount, createLocalVue } from '@vue/test-utils';
|
||||
import { head } from 'lodash';
|
||||
import Vue from 'vue';
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
import { getJSONFixture } from 'helpers/fixtures';
|
||||
import { trimText } from 'helpers/text_helper';
|
||||
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
|
||||
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
|
||||
|
@ -11,6 +13,7 @@ const localVue = createLocalVue();
|
|||
describe('ProjectSelector component', () => {
|
||||
let wrapper;
|
||||
let vm;
|
||||
// eslint-disable-next-line import/no-deprecated
|
||||
const allProjects = getJSONFixture('static/projects.json');
|
||||
const searchResults = allProjects.slice(0, 5);
|
||||
let selected = [];
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BulkImports::Common::Pipelines::BoardsPipeline do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:project) { create(:project, group: group) }
|
||||
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
|
||||
|
||||
let(:board_data) do
|
||||
{
|
||||
"name" => "Test Board",
|
||||
"lists" => [
|
||||
{
|
||||
"list_type" => "backlog",
|
||||
"position" => 0
|
||||
},
|
||||
{
|
||||
"list_type" => "closed",
|
||||
"position" => 1
|
||||
},
|
||||
{
|
||||
"list_type" => "label",
|
||||
"position" => 2,
|
||||
"label" => {
|
||||
"title" => "test",
|
||||
"type" => "GroupLabel",
|
||||
"group_id" => group.id
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
let(:tracker) { create(:bulk_import_tracker, entity: entity) }
|
||||
let(:context) { BulkImports::Pipeline::Context.new(tracker) }
|
||||
|
||||
subject { described_class.new(context) }
|
||||
|
||||
before do
|
||||
allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
|
||||
allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: board_data))
|
||||
end
|
||||
group.add_owner(user)
|
||||
end
|
||||
|
||||
context 'when issue board belongs to a project' do
|
||||
let_it_be(:entity) do
|
||||
create(
|
||||
:bulk_import_entity,
|
||||
source_type: :project_entity,
|
||||
project: project,
|
||||
bulk_import: bulk_import,
|
||||
source_full_path: 'source/full/path',
|
||||
destination_name: 'My Destination Group',
|
||||
destination_namespace: group.full_path
|
||||
)
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
it 'imports issue boards into destination project' do
|
||||
expect { subject.run }.to change(::Board, :count).by(1)
|
||||
board = project.boards.find_by(name: board_data["name"])
|
||||
expect(board).to be
|
||||
expect(board.project.id).to eq(project.id)
|
||||
expect(board.lists.count).to eq(3)
|
||||
expect(board.lists.map(&:list_type).sort).to match_array(%w(backlog closed label))
|
||||
expect(board.lists.find_by(list_type: "label").label.title).to eq("test")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when issue board belongs to a group' do
|
||||
let_it_be(:entity) do
|
||||
create(
|
||||
:bulk_import_entity,
|
||||
group: group,
|
||||
bulk_import: bulk_import,
|
||||
source_full_path: 'source/full/path',
|
||||
destination_name: 'My Destination Group',
|
||||
destination_namespace: group.full_path
|
||||
)
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
it 'imports issue boards into destination group' do
|
||||
expect { subject.run }.to change(::Board, :count).by(1)
|
||||
board = group.boards.find_by(name: board_data["name"])
|
||||
expect(board).to be
|
||||
expect(board.group.id).to eq(group.id)
|
||||
expect(board.lists.count).to eq(3)
|
||||
expect(board.lists.map(&:list_type).sort).to match_array(%w(backlog closed label))
|
||||
expect(board.lists.find_by(list_type: "label").label.title).to eq("test")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,49 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe BulkImports::Groups::Pipelines::BoardsPipeline do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:bulk_import) { create(:bulk_import, user: user) }
|
||||
let_it_be(:filepath) { 'spec/fixtures/bulk_imports/gz/boards.ndjson.gz' }
|
||||
let_it_be(:entity) do
|
||||
create(
|
||||
:bulk_import_entity,
|
||||
group: group,
|
||||
bulk_import: bulk_import,
|
||||
source_full_path: 'source/full/path',
|
||||
destination_name: 'My Destination Group',
|
||||
destination_namespace: group.full_path
|
||||
)
|
||||
end
|
||||
|
||||
let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
|
||||
let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
|
||||
|
||||
let(:tmpdir) { Dir.mktmpdir }
|
||||
|
||||
before do
|
||||
FileUtils.copy_file(filepath, File.join(tmpdir, 'boards.ndjson.gz'))
|
||||
group.add_owner(user)
|
||||
end
|
||||
|
||||
subject { described_class.new(context) }
|
||||
|
||||
describe '#run' do
|
||||
it 'imports group boards into destination group and removes tmpdir' do
|
||||
allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
|
||||
allow_next_instance_of(BulkImports::FileDownloadService) do |service|
|
||||
allow(service).to receive(:execute)
|
||||
end
|
||||
|
||||
expect { subject.run }.to change(Board, :count).by(1)
|
||||
|
||||
lists = group.boards.find_by(name: 'first board').lists
|
||||
|
||||
expect(lists.count).to eq(3)
|
||||
expect(lists.first.label.title).to eq('TSL')
|
||||
expect(lists.second.label.title).to eq('Sosync')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -14,7 +14,7 @@ RSpec.describe BulkImports::Groups::Stage do
|
|||
[1, BulkImports::Common::Pipelines::LabelsPipeline],
|
||||
[1, BulkImports::Groups::Pipelines::MilestonesPipeline],
|
||||
[1, BulkImports::Groups::Pipelines::BadgesPipeline],
|
||||
[2, BulkImports::Groups::Pipelines::BoardsPipeline]
|
||||
[2, BulkImports::Common::Pipelines::BoardsPipeline]
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ RSpec.describe BulkImports::Projects::Stage do
|
|||
[1, BulkImports::Projects::Pipelines::RepositoryPipeline],
|
||||
[2, BulkImports::Common::Pipelines::LabelsPipeline],
|
||||
[3, BulkImports::Projects::Pipelines::IssuesPipeline],
|
||||
[4, BulkImports::Common::Pipelines::EntityFinisher]
|
||||
[4, BulkImports::Common::Pipelines::BoardsPipeline],
|
||||
[5, BulkImports::Common::Pipelines::EntityFinisher]
|
||||
]
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue