From e2c471038ab2b4f09487c1feb74520f74f834986 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Tue, 4 May 2021 09:09:59 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- Dangerfile | 8 +- GITALY_SERVER_VERSION | 2 +- Gemfile | 2 +- Gemfile.lock | 4 +- app/assets/javascripts/boards/constants.js | 8 ++ app/assets/javascripts/boards/index.js | 2 + app/assets/javascripts/boards/stores/actions.js | 34 +++-- app/assets/javascripts/boards/stores/mutations.js | 3 +- app/helpers/projects_helper.rb | 4 +- .../layouts/nav/sidebar/_project_menus.html.haml | 2 - .../nav/sidebar/_project_packages_link.html.haml | 27 ---- danger/changes_size/Dangerfile | 19 +++ danger/database/Dangerfile | 2 +- danger/feature_flag/Dangerfile | 2 +- doc/api/services.md | 4 +- .../projects/menus/packages_registries_menu.rb | 71 +++++++++++ lib/sidebars/projects/panel.rb | 1 + qa/qa/page/project/sub_menus/packages.rb | 20 +-- spec/features/boards/user_visits_board_spec.rb | 78 ++++++++++++ .../projects/settings/packages_settings_spec.rb | 26 ++-- spec/frontend/boards/stores/actions_spec.js | 81 ++++++++---- .../menus/packages_registries_menu_spec.rb | 139 +++++++++++++++++++++ spec/tooling/danger/project_helper_spec.rb | 2 +- .../layouts/nav/sidebar/_project.html.haml_spec.rb | 84 ++++++------- tooling/danger/project_helper.rb | 15 +++ 25 files changed, 478 insertions(+), 162 deletions(-) delete mode 100644 app/views/layouts/nav/sidebar/_project_packages_link.html.haml create mode 100644 danger/changes_size/Dangerfile create mode 100644 lib/sidebars/projects/menus/packages_registries_menu.rb create mode 100644 spec/features/boards/user_visits_board_spec.rb create mode 100644 spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb diff --git a/Dangerfile b/Dangerfile index 37a45674e16..699be613f2d 100644 --- a/Dangerfile +++ b/Dangerfile @@ -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)) diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index ada363b4fbc..83823ce4036 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -d7c7ca994f16601bda8854ca9d20175dc8a11c74 +bb763fb573555a0f9714002c2755bdd396cab3dd diff --git a/Gemfile b/Gemfile index 4aecc60600e..fcf5aae2585 100644 --- a/Gemfile +++ b/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 diff --git a/Gemfile.lock b/Gemfile.lock index 4d39fc99de6..1054af774c7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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) diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js index 4519992ca94..d88774d11c1 100644 --- a/app/assets/javascripts/boards/constants.js +++ b/app/assets/javascripts/boards/constants.js @@ -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, diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index b13b04430c0..84beaebfb4b 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -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, diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index 27dccd91b40..19285a1dc85 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -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, diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js index 561c21b78c1..4f89d7e9d1f 100644 --- a/app/assets/javascripts/boards/stores/mutations.js +++ b/app/assets/javascripts/boards/stores/mutations.js @@ -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; diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index da8ece06bcd..68bd6a30925 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -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 diff --git a/app/views/layouts/nav/sidebar/_project_menus.html.haml b/app/views/layouts/nav/sidebar/_project_menus.html.haml index 8d838617b64..f802488aa80 100644 --- a/app/views/layouts/nav/sidebar/_project_menus.html.haml +++ b/app/views/layouts/nav/sidebar/_project_menus.html.haml @@ -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) diff --git a/app/views/layouts/nav/sidebar/_project_packages_link.html.haml b/app/views/layouts/nav/sidebar/_project_packages_link.html.haml deleted file mode 100644 index aa25136dfc0..00000000000 --- a/app/views/layouts/nav/sidebar/_project_packages_link.html.haml +++ /dev/null @@ -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') diff --git a/danger/changes_size/Dangerfile b/danger/changes_size/Dangerfile new file mode 100644 index 00000000000..52e6cb65d04 --- /dev/null +++ b/danger/changes_size/Dangerfile @@ -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 diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile index cd56ea8dd22..af4d6ed513d 100644 --- a/danger/database/Dangerfile +++ b/danger/database/Dangerfile @@ -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') diff --git a/danger/feature_flag/Dangerfile b/danger/feature_flag/Dangerfile index 88ce6393b64..d14dd97380f 100644 --- a/danger/feature_flag/Dangerfile +++ b/danger/feature_flag/Dangerfile @@ -13,7 +13,7 @@ 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) diff --git a/doc/api/services.md b/doc/api/services.md index 27e057081bc..e658c51f7e6 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -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 | diff --git a/lib/sidebars/projects/menus/packages_registries_menu.rb b/lib/sidebars/projects/menus/packages_registries_menu.rb new file mode 100644 index 00000000000..51a1df7f1d3 --- /dev/null +++ b/lib/sidebars/projects/menus/packages_registries_menu.rb @@ -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 diff --git a/lib/sidebars/projects/panel.rb b/lib/sidebars/projects/panel.rb index 50a82a97adf..58f2e9e7fb4 100644 --- a/lib/sidebars/projects/panel.rb +++ b/lib/sidebars/projects/panel.rb @@ -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 diff --git a/qa/qa/page/project/sub_menus/packages.rb b/qa/qa/page/project/sub_menus/packages.rb index 46eae01e10d..88e2101a86d 100644 --- a/qa/qa/page/project/sub_menus/packages.rb +++ b/qa/qa/page/project/sub_menus/packages.rb @@ -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 diff --git a/spec/features/boards/user_visits_board_spec.rb b/spec/features/boards/user_visits_board_spec.rb new file mode 100644 index 00000000000..7fe32557d6a --- /dev/null +++ b/spec/features/boards/user_visits_board_spec.rb @@ -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 diff --git a/spec/features/projects/settings/packages_settings_spec.rb b/spec/features/projects/settings/packages_settings_spec.rb index 0b40cbee582..62f31fd027b 100644 --- a/spec/features/projects/settings/packages_settings_spec.rb +++ b/spec/features/projects/settings/packages_settings_spec.rb @@ -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 diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js index afc8f20b507..34e24fe0a1c 100644 --- a/spec/frontend/boards/stores/actions_spec.js +++ b/spec/frontend/boards/stores/actions_spec.js @@ -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, diff --git a/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb new file mode 100644 index 00000000000..fc0d7710a5e --- /dev/null +++ b/spec/lib/sidebars/projects/menus/packages_registries_menu_spec.rb @@ -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 diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb index 6bec176b39b..5d106f08402 100644 --- a/spec/tooling/danger/project_helper_spec.rb +++ b/spec/tooling/danger/project_helper_spec.rb @@ -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 diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index f83a515fb23..b86164a6639 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -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) + describe 'Packages and Registries' do + let(:registry_enabled) { true } + let(:packages_enabled) { true } - allow(controller).to receive(:controller_name) - .and_return('repositories') - allow(controller).to receive(:controller_path) - .and_return('projects/registry/repositories') + before do + stub_container_registry_config(enabled: registry_enabled) + stub_config(packages: { enabled: packages_enabled }) end - it 'highlights sidebar item and flyout' do + it 'top level navigation link is visible and points to package registry page' 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) + expect(rendered).to have_link('Packages & Registries', href: project_packages_path(project)) end - it 'highlights container registry tab' do - render + describe 'Packages Registry' do + it 'shows link to package registry page' do + render - expect(rendered).to have_css('.sidebar-sub-level-items > li:not(.fly-out-top-item).active', text: 'Container Registry') - end - end + expect(rendered).to have_link('Package Registry', href: project_packages_path(project)) + end - describe 'Packages' do - let_it_be(:user) { create(:user) } + context 'when packages config setting is not enabled' do + let(:packages_enabled) { false } - let_it_be(:package_menu_name) { 'Packages & Registries' } - let_it_be(:package_entry_name) { 'Package Registry' } + it 'does not show link to package registry page' do + render - before do - project.team.add_developer(user) - sign_in(user) - stub_container_registry_config(enabled: true) + expect(rendered).not_to have_link('Package Registry', href: project_packages_path(project)) + end + end end - context 'when packages is enabled' do - it 'packages link is visible' do + describe 'Container Registry' do + it 'shows link to container registry page' do render - expect(rendered).to have_link(package_menu_name, href: project_packages_path(project)) + expect(rendered).to have_link('Container Registry', href: project_container_registry_index_path(project)) end - it 'packages list link is visible' do - render - - expect(rendered).to have_link(package_entry_name, href: project_packages_path(project)) - end + context 'when container config setting is not enabled' do + let(:registry_enabled) { false } - it 'container registry link is visible' do - render + it 'does not show link to package registry page' do + render - expect(rendered).to have_link('Container Registry', href: project_container_registry_index_path(project)) + 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 diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb index b60a3aa1adc..7aac0de0b6b 100644 --- a/tooling/danger/project_helper.rb +++ b/tooling/danger/project_helper.rb @@ -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 -- cgit v1.2.1