Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-05-04 09:09:59 +00:00
parent 04a893be75
commit e2c471038a
25 changed files with 483 additions and 167 deletions

View File

@ -2,14 +2,10 @@
require 'gitlab-dangerfiles'
gitlab_dangerfiles = Gitlab::Dangerfiles::Engine.new(self)
gitlab_dangerfiles.import_plugins
return if helper.release_automation?
Gitlab::Dangerfiles.import_plugins(danger)
danger.import_plugin('danger/plugins/*.rb')
gitlab_dangerfiles.import_dangerfiles
return if helper.release_automation?
project_helper.rule_names.each do |rule|
danger.import_dangerfile(path: File.join('danger', rule))

View File

@ -1 +1 @@
d7c7ca994f16601bda8854ca9d20175dc8a11c74
bb763fb573555a0f9714002c2755bdd396cab3dd

View File

@ -403,7 +403,7 @@ group :development, :test do
end
group :development, :test, :danger do
gem 'gitlab-dangerfiles', '~> 2.0.0', require: false
gem 'gitlab-dangerfiles', '~> 1.1.1', require: false
end
group :development, :test, :coverage do

View File

@ -447,7 +447,7 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
gitlab-dangerfiles (2.0.0)
gitlab-dangerfiles (1.1.1)
danger-gitlab
gitlab-experiment (0.5.3)
activesupport (>= 3.0)
@ -1449,7 +1449,7 @@ DEPENDENCIES
gitaly (~> 13.11.0.pre.rc1)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 2.0.0)
gitlab-dangerfiles (~> 1.1.1)
gitlab-experiment (~> 0.5.3)
gitlab-fog-azure-rm (~> 1.0.1)
gitlab-fog-google (~> 1.13)

View File

@ -1,9 +1,11 @@
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import { __ } from '~/locale';
import updateEpicSubscriptionMutation from '~/sidebar/queries/update_epic_subscription.mutation.graphql';
import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql';
import boardBlockingIssuesQuery from './graphql/board_blocking_issues.query.graphql';
import destroyBoardListMutation from './graphql/board_list_destroy.mutation.graphql';
import updateBoardListMutation from './graphql/board_list_update.mutation.graphql';
import issueSetSubscriptionMutation from './graphql/issue_set_subscription.mutation.graphql';
import issueSetTitleMutation from './graphql/issue_set_title.mutation.graphql';
@ -62,6 +64,12 @@ export const NOT_FILTER = 'not[';
export const flashAnimationDuration = 2000;
export const listsQuery = {
[issuableTypes.issue]: {
query: boardListsQuery,
},
};
export const blockingIssuablesQueries = {
[issuableTypes.issue]: {
query: boardBlockingIssuesQuery,

View File

@ -37,6 +37,7 @@ import {
import { __ } from '~/locale';
import sidebarEventHub from '~/sidebar/event_hub';
import introspectionQueryResultData from '~/sidebar/fragmentTypes.json';
import { fullBoardId } from './boards_util';
import boardConfigToggle from './config_toggle';
import mountMultipleBoardsSwitcher from './mount_multiple_boards_switcher';
@ -135,6 +136,7 @@ export default () => {
created() {
this.setInitialBoardData({
boardId: $boardApp.dataset.boardId,
fullBoardId: fullBoardId($boardApp.dataset.boardId),
fullPath: $boardApp.dataset.fullPath,
boardType: this.parent,
disabled: this.disabled,

View File

@ -9,10 +9,11 @@ import {
subscriptionQueries,
SupportedFilters,
deleteListQueries,
listsQuery,
updateListQueries,
issuableTypes,
} from 'ee_else_ce/boards/constants';
import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
@ -21,7 +22,6 @@ import { s__ } from '~/locale';
import {
formatBoardLists,
formatListIssues,
fullBoardId,
formatListsPageInfo,
formatIssue,
formatIssueInput,
@ -86,24 +86,22 @@ export default {
}
},
fetchLists: ({ dispatch }) => {
dispatch('fetchIssueLists');
},
fetchIssueLists: ({ commit, state, dispatch }) => {
const { boardType, filterParams, fullPath, boardId } = state;
fetchLists: ({ commit, state, dispatch }) => {
const { boardType, filterParams, fullPath, fullBoardId, issuableType } = state;
const variables = {
fullPath,
boardId: fullBoardId(boardId),
boardId: fullBoardId,
filters: filterParams,
isGroup: boardType === BoardType.group,
isProject: boardType === BoardType.project,
...(issuableType === issuableTypes.issue && {
isGroup: boardType === BoardType.group,
isProject: boardType === BoardType.project,
}),
};
return gqlClient
.query({
query: boardListsQuery,
query: listsQuery[issuableType].query,
variables,
})
.then(({ data }) => {
@ -137,7 +135,7 @@ export default {
{ state, commit, dispatch, getters },
{ backlog, labelId, milestoneId, assigneeId, iterationId },
) => {
const { boardId } = state;
const { fullBoardId } = state;
const existingList = getters.getListByLabelId(labelId);
@ -150,7 +148,7 @@ export default {
.mutate({
mutation: createBoardListMutation,
variables: {
boardId: fullBoardId(boardId),
boardId: fullBoardId,
backlog,
labelId,
milestoneId,
@ -296,11 +294,11 @@ export default {
fetchItemsForList: ({ state, commit }, { listId, fetchNext = false }) => {
commit(types.REQUEST_ITEMS_FOR_LIST, { listId, fetchNext });
const { fullPath, boardId, boardType, filterParams } = state;
const { fullPath, fullBoardId, boardType, filterParams } = state;
const variables = {
fullPath,
boardId: fullBoardId(boardId),
boardId: fullBoardId,
id: listId,
filters: filterParams,
isGroup: boardType === BoardType.group,
@ -429,7 +427,7 @@ export default {
try {
const { itemId, fromListId, toListId, moveBeforeId, moveAfterId } = moveData;
const {
boardId,
fullBoardId,
boardItems: {
[itemId]: { iid, referencePath },
},
@ -440,7 +438,7 @@ export default {
variables: {
iid,
projectPath: referencePath.split(/[#]/)[0],
boardId: fullBoardId(boardId),
boardId: fullBoardId,
fromListId: getIdFromGraphQLId(fromListId),
toListId: getIdFromGraphQLId(toListId),
moveBeforeId,

View File

@ -40,8 +40,9 @@ export const addItemToList = ({ state, listId, itemId, moveBeforeId, moveAfterId
export default {
[mutationTypes.SET_INITIAL_BOARD_DATA](state, data) {
const { boardType, disabled, boardId, fullPath, boardConfig, issuableType } = data;
const { boardType, disabled, boardId, fullBoardId, fullPath, boardConfig, issuableType } = data;
state.boardId = boardId;
state.fullBoardId = fullBoardId;
state.fullPath = fullPath;
state.boardType = boardType;
state.disabled = disabled;

View File

@ -718,12 +718,12 @@ module ProjectsHelper
end
def settings_container_registry_expiration_policy_available?(project)
Feature.disabled?(:sidebar_refactor) &&
Feature.disabled?(:sidebar_refactor, current_user) &&
can_destroy_container_registry_image?(current_user, project)
end
def settings_packages_and_registries_enabled?(project)
Feature.enabled?(:sidebar_refactor) &&
Feature.enabled?(:sidebar_refactor, current_user) &&
can_destroy_container_registry_image?(current_user, project)
end

View File

@ -1,5 +1,3 @@
= render_if_exists 'layouts/nav/sidebar/project_packages_link'
- if project_nav_tab? :analytics
= render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user)

View File

@ -1,27 +0,0 @@
- packages_link = project_nav_tab?(:packages) ? project_packages_path(@project) : project_container_registry_index_path(@project)
- if project_nav_tab?(:packages) || project_nav_tab?(:container_registry)
= nav_link controller: [:packages, :repositories, :infrastructure_registry] do
= link_to packages_link, data: { qa_selector: 'packages_link' } do
.nav-icon-container
= sprite_icon('package')
%span.nav-item-name
= _('Packages & Registries')
%ul.sidebar-sub-level-items
= nav_link(controller: [:packages, :repositories, :infrastructure_registry], html_options: { class: "fly-out-top-item" } ) do
= link_to packages_link do
%strong.fly-out-top-item-name
= _('Packages & Registries')
%li.divider.fly-out-top-item
- if project_nav_tab? :packages
= nav_link controller: :packages do
= link_to project_packages_path(@project), title: _('Package Registry') do
%span= _('Package Registry')
- if project_nav_tab? :container_registry
= nav_link controller: :repositories do
= link_to project_container_registry_index_path(@project), class: 'shortcuts-container-registry', title: _('Container Registry') do
%span= _('Container Registry')
- if project_nav_tab? :infrastructure_registry
= nav_link controller: :infrastructure_registry do
= link_to project_infrastructure_registry_index_path(@project), title: _('Infrastructure Registry') do
%span= _('Infrastructure Registry')

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
# FIXME: git.info_for_file raises the following error
# /usr/local/bundle/gems/git-1.4.0/lib/git/lib.rb:956:in `command': (Danger::DSLError)
# [!] Invalid `Dangerfile` file:
# [!] Invalid `Dangerfile` file: git '--git-dir=/builds/gitlab-org/gitlab/.git' '--work-tree=/builds/gitlab-org/gitlab' cat-file '-t' '' 2>&1:fatal: Not a valid object name
# This seems to be the same as https://github.com/danger/danger/issues/535.
# locale_files_updated = git.modified_files.select { |path| path.start_with?('locale') }
# locale_files_updated.each do |locale_file_updated|
# git_stats = git.info_for_file(locale_file_updated)
# message "Git stats for #{locale_file_updated}: #{git_stats[:insertions]} insertions, #{git_stats[:deletions]} insertions"
# end
if git.lines_of_code > 2_000
warn "This merge request is definitely too big (#{git.lines_of_code} lines changed), please split it into multiple merge requests."
elsif git.lines_of_code > 500
warn "This merge request is quite big (#{git.lines_of_code} lines changed), please consider splitting it into multiple merge requests."
end

View File

@ -55,7 +55,7 @@ if gitlab.mr_labels.include?('database') || db_paths_to_review.any?
markdown(DB_MESSAGE)
markdown(DB_FILES_MESSAGE + helper.markdown_list(db_paths_to_review)) if db_paths_to_review.any?
unless helper.has_database_scoped_labels?
unless helper.has_database_scoped_labels?(gitlab.mr_labels)
gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
gitlab.mr_json['iid'],
add_labels: 'database::review pending')

View File

@ -13,7 +13,7 @@ group: "%<group>s"
SUGGEST_COMMENT
def check_feature_flag_yaml(feature_flag)
mr_group_label = helper.group_label
mr_group_label = helper.group_label(gitlab.mr_labels)
if feature_flag.group.nil?
message_for_feature_flag_missing_group!(feature_flag: feature_flag, mr_group_label: mr_group_label)

View File

@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Services API **(FREE)**
NOTE:
This API requires an access token with Maintainer or Owner permissions
This API requires an access token with Maintainer or Owner permissions.
## List all active services
@ -1253,7 +1253,7 @@ Parameters:
| `confidential_issue_channel` | string | false | The name of the channel to receive confidential issues events notifications |
| `merge_request_channel` | string | false | The name of the channel to receive merge request events notifications |
| `note_channel` | string | false | The name of the channel to receive note events notifications |
| `confidential_note_channel` | boolean | The name of the channel to receive confidential note events notifications |
| `confidential_note_channel` | string | false | The name of the channel to receive confidential note events notifications |
| `tag_push_channel` | string | false | The name of the channel to receive tag push events notifications |
| `pipeline_channel` | string | false | The name of the channel to receive pipeline events notifications |
| `wiki_page_channel` | string | false | The name of the channel to receive wiki page events notifications |

View File

@ -0,0 +1,71 @@
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class PackagesRegistriesMenu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
add_item(packages_registry_menu_item)
add_item(container_registry_menu_item)
add_item(infrastructure_registry_menu_item)
true
end
override :link
def link
items.first.link
end
override :title
def title
_('Packages & Registries')
end
override :sprite_icon
def sprite_icon
'package'
end
private
def packages_registry_menu_item
return unless ::Gitlab.config.packages.enabled
return unless can?(context.current_user, :read_package, context.project)
::Sidebars::MenuItem.new(
title: _('Package Registry'),
link: project_packages_path(context.project),
active_routes: { controller: :packages },
item_id: :packages_registry,
container_html_options: { class: 'shortcuts-container-registry' }
)
end
def container_registry_menu_item
return unless ::Gitlab.config.registry.enabled
return unless can?(context.current_user, :read_container_image, context.project)
::Sidebars::MenuItem.new(
title: _('Container Registry'),
link: project_container_registry_index_path(context.project),
active_routes: { controller: :repositories },
item_id: :container_registry
)
end
def infrastructure_registry_menu_item
return if Feature.disabled?(:infrastructure_registry_page, context.current_user)
::Sidebars::MenuItem.new(
title: _('Infrastructure Registry'),
link: project_infrastructure_registry_index_path(context.project),
active_routes: { controller: :infrastructure_registry },
item_id: :infrastructure_registry
)
end
end
end
end
end

View File

@ -17,6 +17,7 @@ module Sidebars
add_menu(Sidebars::Projects::Menus::CiCdMenu.new(context))
add_menu(Sidebars::Projects::Menus::SecurityComplianceMenu.new(context))
add_menu(Sidebars::Projects::Menus::OperationsMenu.new(context))
add_menu(Sidebars::Projects::Menus::PackagesRegistriesMenu.new(context))
end
override :render_raw_menus_partial

View File

@ -7,19 +7,11 @@ module QA
module Packages
extend QA::Page::PageConcern
def self.included(base)
super
base.class_eval do
view 'app/views/layouts/nav/sidebar/_project_packages_link.html.haml' do
element :packages_link
end
end
end
def click_packages_link
within_sidebar do
click_element :packages_link
hover_registry do
within_submenu do
click_element(:sidebar_menu_item_link, menu_item: 'Package Registry')
end
end
end
@ -35,8 +27,8 @@ module QA
def hover_registry
within_sidebar do
scroll_to_element(:packages_link)
find_element(:packages_link).hover
scroll_to_element(:sidebar_menu_link, menu_item: 'Packages & Registries')
find_element(:sidebar_menu_link, menu_item: 'Packages & Registries').hover
yield
end

View File

@ -0,0 +1,78 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User visits issue boards', :js do
using RSpec::Parameterized::TableSyntax
let_it_be(:group) { create_default(:group, :public) }
let_it_be(:project) { create_default(:project, :public, group: group) }
# TODO use 'let' when rspec-parameterized supports it.
# https://gitlab.com/gitlab-org/gitlab/-/issues/329746
label_name1 = 'foobar'
label_name2 = 'in dev'
assignee_username = 'root'
issue_with_label1 = "issue with label1"
issue_with_label2 = "issue with label2"
issue_with_assignee = "issue with assignee"
issue_with_milestone = "issue with milestone"
issue_with_all_filters = "issue with all filters"
let_it_be(:label1) { create(:group_label, group: group, name: label_name1) }
let_it_be(:label2) { create(:group_label, group: group, name: label_name2) }
let_it_be(:assignee) { create_default(:group_member, :maintainer, user: create(:user, username: assignee_username), group: group ).user }
let_it_be(:milestone) { create_default(:milestone, project: project, start_date: Date.today - 1, due_date: 7.days.from_now) }
before_all do
create_default(:issue, project: project, title: issue_with_label1, labels: [label1])
create_default(:issue, project: project, title: issue_with_label2, labels: [label2])
create_default(:issue, project: project, title: issue_with_assignee, assignees: [assignee])
create_default(:issue, project: project, title: issue_with_milestone, milestone: milestone)
create_default(:issue, project: project, title: issue_with_all_filters, labels: [label1, label2], assignees: [assignee], milestone: milestone)
end
shared_examples "visiting board path with search params" do
where(:params, :expected_issues) do
{ "label_name" => [label_name1] } | [issue_with_label1, issue_with_all_filters]
{ "label_name" => [label_name2] } | [issue_with_label2, issue_with_all_filters]
{ "label_name" => [label_name1, label_name2] } | [issue_with_all_filters]
{ "assignee_username" => assignee_username } | [issue_with_assignee, issue_with_all_filters]
{ "milestone_title" => '#started' } | [issue_with_milestone, issue_with_all_filters]
{ "label_name" => [label_name1, label_name2], "assignee_username" => assignee_username } | [issue_with_all_filters]
end
with_them do
before do
visit board_path
wait_for_requests
end
it 'displays all issues satisfiying filter params and correctly sets url params' do
expect(page).to have_current_path(board_path)
page.assert_selector('[data-testid="board_card"]', count: expected_issues.length)
expected_issues.each { |issue_title| expect(page).to have_link issue_title }
end
end
end
context "project boards" do
let_it_be(:board) { create_default(:board, project: project) }
let_it_be(:backlog_list) { create_default(:backlog_list, board: board) }
let(:board_path) { project_boards_path(project, params) }
include_examples "visiting board path with search params"
end
context "group boards" do
let_it_be(:board) { create_default(:board, group: group) }
let_it_be(:backlog_list) { create_default(:backlog_list, board: board) }
let(:board_path) { group_boards_path(group, params) }
include_examples 'visiting board path with search params'
end
end

View File

@ -3,36 +3,32 @@
require 'spec_helper'
RSpec.describe 'Projects > Settings > Packages', :js do
let(:project) { create(:project) }
let(:user) { create(:user) }
let_it_be(:project) { create(:project) }
let(:user) { project.owner }
before do
sign_in(user)
project.add_maintainer(user)
stub_config(packages: { enabled: packages_enabled })
visit edit_project_path(project)
end
context 'Packages enabled in config' do
before do
allow(Gitlab.config.packages).to receive(:enabled).and_return(true)
end
let(:packages_enabled) { true }
it 'displays the packages toggle button' do
visit edit_project_path(project)
expect(page).to have_content('Packages')
expect(page).to have_button('Packages', class: 'gl-toggle')
expect(page).to have_selector('input[name="project[packages_enabled]"] + button', visible: true)
end
end
context 'Packages disabled in config' do
before do
allow(Gitlab.config.packages).to receive(:enabled).and_return(false)
end
let(:packages_enabled) { false }
it 'does not show up in UI' do
visit edit_project_path(project)
expect(page).not_to have_content('Packages')
expect(page).not_to have_button('Packages', class: 'gl-toggle')
end
end
end

View File

@ -1,15 +1,21 @@
import * as Sentry from '@sentry/browser';
import {
inactiveId,
ISSUABLE,
ListType,
issuableTypes,
BoardType,
listsQuery,
} from 'ee_else_ce/boards/constants';
import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
import testAction from 'helpers/vuex_action_helper';
import {
fullBoardId,
formatListIssues,
formatBoardLists,
formatIssueInput,
formatIssue,
getMoveData,
} from '~/boards/boards_util';
import { inactiveId, ISSUABLE, ListType, issuableTypes } from '~/boards/constants';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
import actions, { gqlClient } from '~/boards/stores/actions';
@ -132,20 +138,12 @@ describe('setActiveId', () => {
});
describe('fetchLists', () => {
it('should dispatch fetchIssueLists action', () => {
testAction({
action: actions.fetchLists,
expectedActions: [{ type: 'fetchIssueLists' }],
});
});
});
describe('fetchIssueLists', () => {
const state = {
let state = {
fullPath: 'gitlab-org',
boardId: '1',
fullBoardId: 'gid://gitlab/Board/1',
filterParams: {},
boardType: 'group',
issuableType: 'issue',
};
let queryResponse = {
@ -167,7 +165,7 @@ describe('fetchIssueLists', () => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
actions.fetchIssueLists,
actions.fetchLists,
{},
state,
[
@ -185,7 +183,7 @@ describe('fetchIssueLists', () => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject());
testAction(
actions.fetchIssueLists,
actions.fetchLists,
{},
state,
[
@ -214,7 +212,7 @@ describe('fetchIssueLists', () => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
actions.fetchIssueLists,
actions.fetchLists,
{},
state,
[
@ -227,6 +225,43 @@ describe('fetchIssueLists', () => {
done,
);
});
it.each`
issuableType | boardType | fullBoardId | isGroup | isProject
${issuableTypes.issue} | ${BoardType.group} | ${'gid://gitlab/Board/1'} | ${true} | ${false}
${issuableTypes.issue} | ${BoardType.project} | ${'gid://gitlab/Board/1'} | ${false} | ${true}
`(
'calls $issuableType query with correct variables',
async ({ issuableType, boardType, fullBoardId, isGroup, isProject }) => {
const commit = jest.fn();
const dispatch = jest.fn();
state = {
fullPath: 'gitlab-org',
fullBoardId,
filterParams: {},
boardType,
issuableType,
};
const variables = {
query: listsQuery[issuableType].query,
variables: {
fullPath: 'gitlab-org',
boardId: fullBoardId,
filters: {},
isGroup,
isProject,
},
};
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
await actions.fetchLists({ commit, state, dispatch });
expect(gqlClient.query).toHaveBeenCalledWith(variables);
},
);
});
describe('createList', () => {
@ -248,7 +283,7 @@ describe('createIssueList', () => {
beforeEach(() => {
state = {
fullPath: 'gitlab-org',
boardId: '1',
fullBoardId: 'gid://gitlab/Board/1',
boardType: 'group',
disabled: false,
boardLists: [{ type: 'closed' }],
@ -378,7 +413,7 @@ describe('moveList', () => {
const state = {
fullPath: 'gitlab-org',
boardId: '1',
fullBoardId: 'gid://gitlab/Board/1',
boardType: 'group',
disabled: false,
boardLists: initialBoardListsState,
@ -421,7 +456,7 @@ describe('moveList', () => {
const state = {
fullPath: 'gitlab-org',
boardId: '1',
fullBoardId: 'gid://gitlab/Board/1',
boardType: 'group',
disabled: false,
boardLists: initialBoardListsState,
@ -455,7 +490,7 @@ describe('updateList', () => {
const state = {
fullPath: 'gitlab-org',
boardId: '1',
fullBoardId: 'gid://gitlab/Board/1',
boardType: 'group',
disabled: false,
boardLists: [{ type: 'closed' }],
@ -573,7 +608,7 @@ describe('fetchItemsForList', () => {
const state = {
fullPath: 'gitlab-org',
boardId: '1',
fullBoardId: 'gid://gitlab/Board/1',
filterParams: {},
boardType: 'group',
};
@ -960,7 +995,7 @@ describe('updateIssueOrder', () => {
const state = {
boardItems: issues,
boardId: 'gid://gitlab/Board/1',
fullBoardId: 'gid://gitlab/Board/1',
};
const moveData = {
@ -974,7 +1009,7 @@ describe('updateIssueOrder', () => {
mutation: issueMoveListMutation,
variables: {
projectPath: getProjectPath(mockIssue.referencePath),
boardId: fullBoardId(state.boardId),
boardId: state.fullBoardId,
iid: mockIssue.iid,
fromListId: 1,
toListId: 2,

View File

@ -0,0 +1,139 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::PackagesRegistriesMenu do
let(:project) { build(:project) }
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
describe '#render?' do
context 'when menu does not have any menu item to show' do
it 'returns false' do
allow(subject).to receive(:has_items?).and_return(false)
expect(subject.render?).to eq false
end
end
context 'when menu has menu items to show' do
it 'returns true' do
expect(subject.render?).to eq true
end
end
end
describe '#link' do
let(:registry_enabled) { true }
let(:packages_enabled) { true }
before do
stub_container_registry_config(enabled: registry_enabled)
stub_config(packages: { enabled: packages_enabled })
end
context 'when Packages Registry is visible' do
it 'menu link points to Packages Registry page' do
expect(subject.link).to eq described_class.new(context).items.find { |i| i.item_id == :packages_registry }.link
end
end
context 'when Packages Registry is not visible' do
let(:packages_enabled) { false }
it 'menu link points to Container Registry page' do
expect(subject.link).to eq described_class.new(context).items.find { |i| i.item_id == :container_registry }.link
end
context 'when Container Registry is not visible' do
let(:registry_enabled) { false }
it 'menu link points to Infrastructure Registry page' do
expect(subject.link).to eq described_class.new(context).items.find { |i| i.item_id == :infrastructure_registry }.link
end
end
end
end
describe 'Packages Registry' do
subject { described_class.new(context).items.find { |i| i.item_id == :packages_registry }}
context 'when user can read packages' do
context 'when config package setting is disabled' do
it 'the menu item is not added to list of menu items' do
stub_config(packages: { enabled: false })
is_expected.to be_nil
end
end
context 'when config package setting is enabled' do
it 'the menu item is added to list of menu items' do
stub_config(packages: { enabled: true })
is_expected.not_to be_nil
end
end
end
context 'when user cannot read packages' do
let(:user) { nil }
it 'the menu item is not added to list of menu items' do
is_expected.to be_nil
end
end
end
describe 'Container Registry' do
subject { described_class.new(context).items.find { |i| i.item_id == :container_registry }}
context 'when user can read container images' do
context 'when config registry setting is disabled' do
it 'the menu item is not added to list of menu items' do
stub_container_registry_config(enabled: false)
is_expected.to be_nil
end
end
context 'when config registry setting is enabled' do
it 'the menu item is added to list of menu items' do
stub_container_registry_config(enabled: true)
is_expected.not_to be_nil
end
end
end
context 'when user cannot read container images' do
let(:user) { nil }
it 'the menu item is not added to list of menu items' do
is_expected.to be_nil
end
end
end
describe 'Infrastructure Registry' do
subject { described_class.new(context).items.find { |i| i.item_id == :infrastructure_registry }}
context 'when feature flag :infrastructure_registry_page is enabled' do
it 'the menu item is added to list of menu items' do
stub_feature_flags(infrastructure_registry_page: true)
is_expected.not_to be_nil
end
end
context 'when feature flag :infrastructure_registry_page is disabled' do
it 'the menu item is not added to list of menu items' do
stub_feature_flags(infrastructure_registry_page: false)
is_expected.to be_nil
end
end
end
end

View File

@ -220,7 +220,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
describe '.local_warning_message' do
it 'returns an informational message with rules that can run' do
expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css')
expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, changes_size, commit_messages, database, datateam, documentation, duplicate_yarn_dependencies, eslint, karma, pajamas, pipeline, prettier, product_intelligence, utility_css')
end
end

View File

@ -580,78 +580,72 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end
end
describe 'packages tab' do
before do
stub_container_registry_config(enabled: true)
allow(controller).to receive(:controller_name)
.and_return('repositories')
allow(controller).to receive(:controller_path)
.and_return('projects/registry/repositories')
end
it 'highlights sidebar item and flyout' do
render
expect(rendered).to have_css('.sidebar-top-level-items > li.active', count: 1)
expect(rendered).to have_css('.sidebar-sub-level-items > li.fly-out-top-item.active', count: 1)
end
it 'highlights container registry tab' do
render
expect(rendered).to have_css('.sidebar-sub-level-items > li:not(.fly-out-top-item).active', text: 'Container Registry')
end
end
describe 'Packages' do
let_it_be(:user) { create(:user) }
let_it_be(:package_menu_name) { 'Packages & Registries' }
let_it_be(:package_entry_name) { 'Package Registry' }
describe 'Packages and Registries' do
let(:registry_enabled) { true }
let(:packages_enabled) { true }
before do
project.team.add_developer(user)
sign_in(user)
stub_container_registry_config(enabled: true)
stub_container_registry_config(enabled: registry_enabled)
stub_config(packages: { enabled: packages_enabled })
end
context 'when packages is enabled' do
it 'packages link is visible' do
it 'top level navigation link is visible and points to package registry page' do
render
expect(rendered).to have_link('Packages & Registries', href: project_packages_path(project))
end
describe 'Packages Registry' do
it 'shows link to package registry page' do
render
expect(rendered).to have_link(package_menu_name, href: project_packages_path(project))
expect(rendered).to have_link('Package Registry', href: project_packages_path(project))
end
it 'packages list link is visible' do
render
context 'when packages config setting is not enabled' do
let(:packages_enabled) { false }
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
it 'does not show link to package registry page' do
render
expect(rendered).not_to have_link('Package Registry', href: project_packages_path(project))
end
end
end
it 'container registry link is visible' do
describe 'Container Registry' do
it 'shows link to container registry page' do
render
expect(rendered).to have_link('Container Registry', href: project_container_registry_index_path(project))
end
context 'when container config setting is not enabled' do
let(:registry_enabled) { false }
it 'does not show link to package registry page' do
render
expect(rendered).not_to have_link('Container Registry', href: project_container_registry_index_path(project))
end
end
end
context 'when container registry is disabled' do
before do
stub_container_registry_config(enabled: false)
end
it 'packages top level and list link are visible' do
describe 'Infrastructure Registry' do
it 'shows link to infrastructure registry page' do
render
expect(rendered).to have_link(package_menu_name, href: project_packages_path(project))
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
expect(rendered).to have_link('Infrastructure Registry', href: project_infrastructure_registry_index_path(project))
end
it 'container registry link is not visible' do
render
context 'when feature flag :infrastructure_registry_page is disabled' do
it 'does not show link to package registry page' do
stub_feature_flags(infrastructure_registry_page: false)
expect(rendered).not_to have_link('Container Registry', href: project_container_registry_index_path(project))
render
expect(rendered).not_to have_link('Infrastructure Registry', href: project_infrastructure_registry_index_path(project))
end
end
end
end

View File

@ -5,6 +5,7 @@ module Tooling
module ProjectHelper
LOCAL_RULES ||= %w[
changelog
changes_size
commit_messages
database
datateam
@ -175,12 +176,26 @@ module Tooling
ee? ? 'gitlab' : 'gitlab-foss'
end
def missing_database_labels(current_mr_labels)
labels = if has_database_scoped_labels?(current_mr_labels)
['database']
else
['database', 'database::review pending']
end
labels - current_mr_labels
end
private
def ee?
# Support former project name for `dev` and support local Danger run
%w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('../../../ee', __dir__))
end
def has_database_scoped_labels?(current_mr_labels)
current_mr_labels.any? { |label| label.start_with?('database::') }
end
end
end
end