Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
04a893be75
commit
e2c471038a
25 changed files with 483 additions and 167 deletions
|
@ -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))
|
||||
|
|
|
@ -1 +1 @@
|
|||
d7c7ca994f16601bda8854ca9d20175dc8a11c74
|
||||
bb763fb573555a0f9714002c2755bdd396cab3dd
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
...(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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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')
|
19
danger/changes_size/Dangerfile
Normal file
19
danger/changes_size/Dangerfile
Normal 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
|
|
@ -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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 |
|
||||
|
|
71
lib/sidebars/projects/menus/packages_registries_menu.rb
Normal file
71
lib/sidebars/projects/menus/packages_registries_menu.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
78
spec/features/boards/user_visits_board_spec.rb
Normal file
78
spec/features/boards/user_visits_board_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -580,75 +580,50 @@ 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(package_menu_name, href: project_packages_path(project))
|
||||
expect(rendered).to have_link('Packages & Registries', href: project_packages_path(project))
|
||||
end
|
||||
|
||||
it 'packages list link is visible' do
|
||||
describe 'Packages Registry' do
|
||||
it 'shows link to package registry page' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_link(package_entry_name, href: project_packages_path(project))
|
||||
expect(rendered).to have_link('Package Registry', href: project_packages_path(project))
|
||||
end
|
||||
|
||||
it 'container registry link is visible' do
|
||||
context 'when packages config setting is not enabled' do
|
||||
let(:packages_enabled) { false }
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
context 'when container registry is disabled' do
|
||||
before do
|
||||
stub_container_registry_config(enabled: false)
|
||||
end
|
||||
context 'when container config setting is not enabled' do
|
||||
let(:registry_enabled) { false }
|
||||
|
||||
it 'packages top level and list link are visible' 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))
|
||||
end
|
||||
|
||||
it 'container registry link is not visible' do
|
||||
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))
|
||||
|
@ -656,6 +631,25 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'Infrastructure Registry' do
|
||||
it 'shows link to infrastructure registry page' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_link('Infrastructure Registry', href: project_infrastructure_registry_index_path(project))
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
render
|
||||
|
||||
expect(rendered).not_to have_link('Infrastructure Registry', href: project_infrastructure_registry_index_path(project))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'wiki entry tab' do
|
||||
let(:can_read_wiki) { true }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue