diff options
30 files changed, 436 insertions, 246 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 4788359e6fa..5c9be5b1e9f 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -4,9 +4,8 @@ .if-not-canonical-namespace: &if-not-canonical-namespace if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org)?($|\/)/' -.exists-ee: &exists-ee - exists: - - ee/**/* +.if-not-ee: &if-not-ee + if: '$CI_PROJECT_NAME !~ /^gitlab(-ee)?$/' .if-not-foss: &if-not-foss if: '$CI_PROJECT_NAME != "gitlab-foss" && $CI_PROJECT_NAME != "gitlab-ce" && $CI_PROJECT_NAME != "gitlabhq"' @@ -312,14 +311,13 @@ ###################### .build-images:rules:build-qa-image: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-and-security-merge-request - <<: *exists-ee changes: *ci-build-images-patterns - <<: *if-dot-com-gitlab-org-and-security-merge-request - <<: *exists-ee changes: *code-qa-patterns - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee .build-images:rules:build-assets-image: rules: @@ -365,8 +363,9 @@ .dev-fixtures:rules:ee-only: rules: + - <<: *if-not-ee + when: never - <<: *if-default-refs - <<: *exists-ee changes: *code-backstage-patterns when: on_success @@ -392,8 +391,9 @@ .graphql:rules:graphql-verify: rules: + - <<: *if-not-ee + when: never - <<: *if-default-refs - <<: *exists-ee changes: *code-backstage-qa-patterns when: on_success @@ -414,8 +414,9 @@ .frontend:rules:compile-test-assets-as-if-foss: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request # Always run for MRs since `compile-test-assets as-if-foss` is either needed by `rspec foss-impact` or the `rspec * as-if-foss` jobs. - <<: *exists-ee changes: *code-backstage-qa-patterns .frontend:rules:default-frontend-jobs: @@ -425,37 +426,39 @@ .frontend:rules:default-frontend-jobs-ee: rules: + - <<: *if-not-ee + when: never - <<: *if-default-refs - <<: *exists-ee changes: *code-backstage-patterns .frontend:rules:default-frontend-jobs-as-if-foss: rules: + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns .frontend:rules:eslint-as-if-foss: rules: + - <<: *if-not-ee + when: never + - <<: *if-merge-request-title-as-if-foss + when: never - <<: *if-merge-request - <<: *exists-ee changes: *frontend-patterns .frontend:rules:ee-mr-and-default-branch-only: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request - <<: *exists-ee changes: *code-backstage-patterns when: always - <<: *if-default-branch-refs - <<: *exists-ee changes: *code-backstage-patterns .frontend:rules:qa-frontend-node: @@ -496,8 +499,9 @@ ############### .pages:rules: rules: + - <<: *if-not-ee + when: never - <<: *if-default-branch-schedule-2-hourly - <<: *exists-ee ############ # QA rules # @@ -510,34 +514,30 @@ .qa:rules:as-if-foss: rules: + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-qa-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns .qa:rules:package-and-qa: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-and-security-merge-request - <<: *exists-ee changes: *ci-qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-and-security-merge-request - <<: *exists-ee changes: *qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-and-security-merge-request - <<: *exists-ee changes: *code-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee allow_failure: true ############### @@ -649,13 +649,15 @@ .rails:rules:ee-only-migration: rules: - - <<: *exists-ee - changes: *db-patterns + - <<: *if-not-ee + when: never + - changes: *db-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:ee-only-migration:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -664,18 +666,19 @@ changes: *ci-patterns when: never - <<: *if-merge-request - <<: *exists-ee changes: *db-patterns .rails:rules:ee-only-unit: rules: - - <<: *exists-ee - changes: *backend-patterns + - <<: *if-not-ee + when: never + - changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:ee-only-unit:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -684,18 +687,19 @@ changes: *ci-patterns when: never - <<: *if-merge-request - <<: *exists-ee changes: *backend-patterns .rails:rules:ee-only-integration: rules: - - <<: *exists-ee - changes: *backend-patterns + - <<: *if-not-ee + when: never + - changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:ee-only-integration:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -704,18 +708,19 @@ changes: *ci-patterns when: never - <<: *if-merge-request - <<: *exists-ee changes: *backend-patterns .rails:rules:ee-only-system: rules: - - <<: *exists-ee - changes: *code-backstage-patterns + - <<: *if-not-ee + when: never + - changes: *code-backstage-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:ee-only-system:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request-title-run-all-rspec @@ -724,143 +729,129 @@ changes: *ci-patterns when: never - <<: *if-merge-request - <<: *exists-ee changes: *code-backstage-patterns .rails:rules:as-if-foss-migration: rules: + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-migration:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *db-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:as-if-foss-unit: rules: + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-unit:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *backend-patterns + - <<: *if-merge-request-title-run-all-rspec .rails:rules:as-if-foss-integration: rules: + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-integration:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *backend-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:as-if-foss-system: rules: + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns .rails:rules:as-if-foss-system:minimal: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-rspec-minimal-disabled when: never - <<: *if-merge-request changes: *ci-patterns when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:ee-and-foss-db-library-code: rules: - - <<: *exists-ee - changes: *db-library-patterns + - changes: *db-library-patterns - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:ee-mr-and-default-branch-only: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-default-branch-refs - <<: *exists-ee changes: *code-backstage-patterns .rails:rules:detect-tests: @@ -870,13 +861,13 @@ .rails:rules:rspec-foss-impact: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-title-as-if-foss when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-backstage-patterns .rails:rules:rspec fail-fast: @@ -885,11 +876,11 @@ when: never - <<: *if-rspec-fail-fast-skipped when: never + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-backstage-patterns .rails:rules:fail-pipeline-early: @@ -898,41 +889,40 @@ when: never - <<: *if-rspec-fail-fast-skipped when: never + - <<: *if-not-ee + when: never - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-patterns when: on_failure - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-backstage-patterns when: on_failure .rails:rules:deprecations: rules: + - <<: *if-not-ee + when: never - <<: *if-default-branch-schedule-nightly - <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:rspec-coverage: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request - <<: *exists-ee changes: *code-backstage-patterns when: always - <<: *if-default-branch-schedule-2-hourly - <<: *exists-ee - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee when: always .rails:rules:rspec-feature-flags: rules: + - <<: *if-not-ee + when: never - <<: *if-default-branch-schedule-2-hourly - <<: *exists-ee allow_failure: true - <<: *if-merge-request-title-run-all-rspec - <<: *exists-ee .rails:rules:default-branch-schedule-nightly--code-backstage: rules: @@ -942,10 +932,10 @@ .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only: rules: + - <<: *if-not-ee + when: never - <<: *if-default-branch-schedule-nightly - <<: *exists-ee - <<: *if-merge-request - <<: *exists-ee changes: [".gitlab/ci/rails.gitlab-ci.yml"] ######################### @@ -958,14 +948,13 @@ .static-analysis:rules:as-if-foss: rules: + - <<: *if-not-ee + when: never - <<: *if-merge-request-title-as-if-foss - <<: *exists-ee changes: *code-backstage-qa-patterns - <<: *if-security-merge-request - <<: *exists-ee changes: *code-backstage-qa-patterns - <<: *if-merge-request - <<: *exists-ee changes: *ci-patterns ####################### @@ -1071,116 +1060,108 @@ ################ .review:rules:review-build-cng: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *frontend-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee .review:rules:review-deploy: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *frontend-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee allow_failure: true .review:rules:review-performance: rules: - if: '$DAST_RUN == "true"' # Skip this job when DAST is run when: never + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *frontend-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-qa-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee allow_failure: true .review:rules:review-stop-failed-deployment: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-qa-patterns .review:rules:review-qa-smoke: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *ci-review-patterns - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *frontend-patterns allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-qa-patterns allow_failure: true .review:rules:review-qa-all: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *qa-patterns allow_failure: true .review:rules:review-cleanup: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-qa-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee allow_failure: true .review:rules:review-stop: rules: + - <<: *if-not-ee + when: never - <<: *if-dot-com-gitlab-org-merge-request - <<: *exists-ee changes: *code-qa-patterns when: manual allow_failure: true - <<: *if-dot-com-gitlab-org-schedule - <<: *exists-ee allow_failure: true .review:rules:danger: @@ -1223,8 +1204,9 @@ .setup:rules:verify-tests-yml: rules: + - <<: *if-not-ee + when: never - <<: *if-default-refs - <<: *exists-ee changes: *code-backstage-patterns when: on_success @@ -1239,12 +1221,12 @@ .test-metadata:rules:update-tests-metadata: rules: - - <<: *exists-ee - changes: + - <<: *if-not-ee + when: never + - changes: - ".gitlab/ci/test-metadata.gitlab-ci.yml" - "scripts/rspec_helpers.sh" - <<: *if-dot-com-ee-schedule - <<: *exists-ee ################### # workhorse rules # diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index cde5ad24fa5..3126c690514 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -38,6 +38,7 @@ @import 'framework/secondary_navigation_elements'; @import 'framework/selects'; @import 'framework/sidebar'; +@import 'framework/contextual_sidebar_header'; @import 'framework/contextual_sidebar'; @import 'framework/tables'; @import 'framework/notes'; diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss index 95b8298c59b..6299d4b236f 100644 --- a/app/assets/stylesheets/framework/contextual_sidebar.scss +++ b/app/assets/stylesheets/framework/contextual_sidebar.scss @@ -20,48 +20,6 @@ } } -.context-header { - position: relative; - margin-right: 2px; - width: $contextual-sidebar-width; - - > a, - > button { - transition: padding $sidebar-transition-duration; - font-weight: $gl-font-weight-bold; - display: flex; - width: 100%; - align-items: center; - padding: 10px 16px 10px 10px; - color: $gl-text-color; - background-color: transparent; - border: 0; - text-align: left; - - &:hover, - &:focus { - background-color: $link-hover-background; - color: $gl-text-color; - outline: 0; - } - } - - .avatar-container { - flex: 0 0 40px; - background-color: $white; - } - - .sidebar-context-title { - overflow: hidden; - text-overflow: ellipsis; - - &.text-secondary { - font-weight: normal; - font-size: 0.8em; - } - } -} - .settings-avatar { background-color: $white; @@ -72,14 +30,8 @@ } @mixin collapse-contextual-sidebar-content { - .context-header { - height: 60px; - width: $contextual-sidebar-collapsed-width; - a { - padding: 10px 4px; - } - } + @include context-header-collapsed; .sidebar-top-level-items > li { .sidebar-sub-level-items { @@ -135,7 +87,6 @@ } .badge.badge-pill:not(.fly-out-badge), - .sidebar-context-title, .nav-item-name { @include gl-sr-only; } diff --git a/app/assets/stylesheets/framework/contextual_sidebar_header.scss b/app/assets/stylesheets/framework/contextual_sidebar_header.scss new file mode 100644 index 00000000000..fdd03f4cdc8 --- /dev/null +++ b/app/assets/stylesheets/framework/contextual_sidebar_header.scss @@ -0,0 +1,57 @@ +.context-header { + position: relative; + margin-right: 2px; + width: $contextual-sidebar-width; + + > a, + > button { + transition: padding $sidebar-transition-duration; + font-weight: $gl-font-weight-bold; + display: flex; + width: 100%; + align-items: center; + padding: 10px 16px 10px 10px; + color: $gl-text-color; + background-color: transparent; + border: 0; + text-align: left; + + &:hover, + &:focus { + background-color: $link-hover-background; + color: $gl-text-color; + outline: 0; + } + } + + .avatar-container { + flex: 0 0 40px; + background-color: $white; + } + + .sidebar-context-title { + overflow: hidden; + text-overflow: ellipsis; + + &.text-secondary { + font-weight: normal; + font-size: 0.8em; + } + } +} + +@mixin context-header-collapsed { + .context-header { + height: 60px; + width: $contextual-sidebar-collapsed-width; + + a { + padding: 10px 4px; + } + } + + .sidebar-context-title { + @include gl-sr-only; + } +} + diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index c0de311d218..7507d5cb3b6 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -3,14 +3,16 @@ module GroupsHelper def group_overview_nav_link_paths %w[ - groups#show - groups#details groups#activity groups#subgroups ].tap do |paths| - break paths if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + extra_routes = if sidebar_refactor_disabled? + ['groups#show', 'groups#details'] + else + ['labels#index', 'group_members#index'] + end - paths.concat(['labels#index', 'group_members#index']) + paths.concat(extra_routes) end end diff --git a/app/helpers/sidebars_helper.rb b/app/helpers/sidebars_helper.rb index 0fc306a3f2e..39ad8ed8a0f 100644 --- a/app/helpers/sidebars_helper.rb +++ b/app/helpers/sidebars_helper.rb @@ -20,6 +20,14 @@ module SidebarsHelper Sidebars::Projects::Context.new(**context_data) end + def sidebar_refactor_enabled? + Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + end + + def sidebar_refactor_disabled? + !sidebar_refactor_enabled? + end + private def sidebar_project_tracking_attrs diff --git a/app/models/member.rb b/app/models/member.rb index 044b662e10f..00255f97f85 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -166,10 +166,10 @@ class Member < ApplicationRecord after_create :send_invite, if: :invite?, unless: :importing? after_create :send_request, if: :request?, unless: :importing? after_create :create_notification_setting, unless: [:pending?, :importing?] - after_create :post_create_hook, unless: [:pending?, :importing?] - after_update :post_update_hook, unless: [:pending?, :importing?] + after_create :post_create_hook, unless: [:pending?, :importing?], if: :hook_prerequisites_met? + after_update :post_update_hook, unless: [:pending?, :importing?], if: :hook_prerequisites_met? after_destroy :destroy_notification_setting - after_destroy :post_destroy_hook, unless: :pending? + after_destroy :post_destroy_hook, unless: :pending?, if: :hook_prerequisites_met? after_commit :refresh_member_authorized_projects default_value_for :notification_level, NotificationSetting.levels[:global] @@ -383,6 +383,12 @@ class Member < ApplicationRecord invite? || request? end + def hook_prerequisites_met? + # It is essential that an associated user record exists + # so that we can successfully fire any member related hooks/notifications. + user.present? + end + def accept_request return false unless request? diff --git a/app/views/layouts/nav/sidebar/_context_menu_body.html.haml b/app/views/layouts/nav/sidebar/_context_menu_body.html.haml new file mode 100644 index 00000000000..64b28cc892e --- /dev/null +++ b/app/views/layouts/nav/sidebar/_context_menu_body.html.haml @@ -0,0 +1,5 @@ += link_to group_path(@group), title: @group.name do + %span.avatar-container.rect-avatar.s40.group-avatar + = group_icon(@group, class: "avatar s40 avatar-tile") + %span.sidebar-context-title + = @group.name diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml index 234e849e14a..f31e1b718ff 100644 --- a/app/views/layouts/nav/sidebar/_group.html.haml +++ b/app/views/layouts/nav/sidebar/_group.html.haml @@ -4,33 +4,36 @@ %aside.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?), **sidebar_tracking_attributes_by_object(@group), 'aria-label': aside_title } .nav-sidebar-inner-scroll - .context-header - = link_to group_path(@group), title: @group.name do - %span.avatar-container.rect-avatar.s40.group-avatar - = group_icon(@group, class: "avatar s40 avatar-tile") - %span.sidebar-context-title - = @group.name + - if sidebar_refactor_disabled? + .context-header + = render 'layouts/nav/sidebar/context_menu_body' + %ul.sidebar-top-level-items.qa-group-sidebar + - if sidebar_refactor_enabled? + = nav_link(path: ['groups#show', 'groups#details'], html_options: { class: 'context-header' }) do + = render 'layouts/nav/sidebar/context_menu_body' + = render_if_exists 'layouts/nav/sidebar/group_trial_status_widget', group: @group - if group_sidebar_link?(:overview) - paths = group_overview_nav_link_paths = nav_link(path: paths, unless: -> { current_path?('groups/contribution_analytics#show') }, html_options: { class: 'home' }) do - = link_to group_path(@group) do + - information_link = sidebar_refactor_enabled? ? activity_group_path(@group) : group_path(@group) + = link_to information_link do .nav-icon-container - - sprite = Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml) ? 'group' : 'home' + - sprite = sidebar_refactor_enabled? ? 'group' : 'home' = sprite_icon(sprite) %span.nav-item-name = group_information_title(@group) %ul.sidebar-sub-level-items = nav_link(path: paths, html_options: { class: "fly-out-top-item" } ) do - = link_to group_path(@group) do + = link_to information_link do %strong.fly-out-top-item-name = group_information_title(@group) %li.divider.fly-out-top-item - - if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + - if sidebar_refactor_disabled? = nav_link(path: ['groups#show', 'groups#details', 'groups#subgroups'], html_options: { class: 'home' }) do = link_to details_group_path(@group), title: _('Group details') do %span @@ -42,13 +45,13 @@ %span = _('Activity') - - if group_sidebar_link?(:labels) && Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + - if group_sidebar_link?(:labels) && sidebar_refactor_enabled? = nav_link(path: 'labels#index') do = link_to group_labels_path(@group), title: _('Labels') do %span = _('Labels') - - if Feature.enabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + - if sidebar_refactor_enabled? - if group_sidebar_link?(:group_members) = nav_link(path: 'group_members#index') do = link_to group_group_members_path(@group), title: _('Members'), data: { qa_selector: 'group_members_item' } do @@ -85,7 +88,7 @@ %span = boards_link_text - - if group_sidebar_link?(:labels) && Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + - if group_sidebar_link?(:labels) && sidebar_refactor_disabled? = nav_link(path: 'labels#index') do = link_to group_labels_path(@group), title: _('Labels') do %span @@ -138,7 +141,7 @@ - if group_sidebar_link?(:wiki) = render 'layouts/nav/sidebar/wiki_link', wiki_url: @group.wiki.web_url - - if Feature.disabled?(:sidebar_refactor, current_user, default_enabled: :yaml) + - if sidebar_refactor_disabled? - if group_sidebar_link?(:group_members) = nav_link(path: 'group_members#index') do = link_to group_group_members_path(@group) do diff --git a/app/views/projects/pages/_access.html.haml b/app/views/projects/pages/_access.html.haml index 5b23234791b..67a2eeb7e7b 100644 --- a/app/views/projects/pages/_access.html.haml +++ b/app/views/projects/pages/_access.html.haml @@ -19,5 +19,3 @@ - link_start = '<a href="%{url}" target="_blank" class="gl-alert-link" rel="noopener noreferrer">'.html_safe % { url: help_page } - link_end = '</a>'.html_safe = html_escape_once(s_('GitLabPages|Access Control is enabled for this Pages website; only authorized users will be able to access it. To make your website publicly available, navigate to your project\'s %{strong_start}Settings > General > Visibility%{strong_end} and select %{strong_start}Everyone%{strong_end} in pages section. Read the %{link_start}documentation%{link_end} for more information.')).html_safe % { link_start: link_start, link_end: link_end, strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe } - .card-footer.gl-alert-info - = s_('GitLabPages|It may take up to 30 minutes before the site is available after the first deployment.') diff --git a/changelogs/unreleased/321670-remove-deprecated-instance-statistics-route.yml b/changelogs/unreleased/321670-remove-deprecated-instance-statistics-route.yml new file mode 100644 index 00000000000..aa0831296d3 --- /dev/null +++ b/changelogs/unreleased/321670-remove-deprecated-instance-statistics-route.yml @@ -0,0 +1,5 @@ +--- +title: Remove old redirect rule for the usage trends feature +merge_request: 60485 +author: +type: changed diff --git a/changelogs/unreleased/330722-nomethoderror-undefined-method-username-for-nil-nilclass.yml b/changelogs/unreleased/330722-nomethoderror-undefined-method-username-for-nil-nilclass.yml new file mode 100644 index 00000000000..9ed605b3f90 --- /dev/null +++ b/changelogs/unreleased/330722-nomethoderror-undefined-method-username-for-nil-nilclass.yml @@ -0,0 +1,5 @@ +--- +title: Execute member hooks only if an associated user is present +merge_request: 62175 +author: +type: fixed diff --git a/changelogs/unreleased/migrate-prometheus-application-status-to-integration-enabled.yml b/changelogs/unreleased/migrate-prometheus-application-status-to-integration-enabled.yml new file mode 100644 index 00000000000..233457c081b --- /dev/null +++ b/changelogs/unreleased/migrate-prometheus-application-status-to-integration-enabled.yml @@ -0,0 +1,5 @@ +--- +title: Backfill clusters_integration_prometheus.enabled +merge_request: 61502 +author: +type: changed diff --git a/config/routes/admin.rb b/config/routes/admin.rb index e929bb297d3..f3377c0fdce 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -104,7 +104,6 @@ namespace :admin do resources :projects, only: [:index] - get '/instance_statistics', to: redirect('admin/usage_trends') resources :usage_trends, only: :index resource :dev_ops_report, controller: 'dev_ops_report', only: :show resources :cohorts, only: :index diff --git a/db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb b/db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb new file mode 100644 index 00000000000..6cd9b1173b6 --- /dev/null +++ b/db/post_migrate/20210519104931_backfill_clusters_integration_prometheus_enabled.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +class BackfillClustersIntegrationPrometheusEnabled < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + disable_ddl_transaction! + + def up + ApplicationRecord.connection.execute(<<~SQL.squish) + WITH executed_at AS (VALUES (TIMEZONE('UTC', NOW()))) + INSERT INTO clusters_integration_prometheus( + cluster_id, + enabled, + encrypted_alert_manager_token, + encrypted_alert_manager_token_iv, + created_at, + updated_at + ) + SELECT + cluster_id, + true, + encrypted_alert_manager_token, + encrypted_alert_manager_token_iv, + (table executed_at), + (table executed_at) + FROM clusters_applications_prometheus + WHERE status IN ( + 3, /* installed */ + 11 /* externally installed */ + ) + ON CONFLICT(cluster_id) DO UPDATE SET + enabled = true, + encrypted_alert_manager_token = EXCLUDED.encrypted_alert_manager_token, + encrypted_alert_manager_token_iv = EXCLUDED.encrypted_alert_manager_token_iv, + updated_at = (table executed_at) + SQL + end + + def down + # Irreversible + end +end diff --git a/db/schema_migrations/20210519104931 b/db/schema_migrations/20210519104931 new file mode 100644 index 00000000000..82f84986924 --- /dev/null +++ b/db/schema_migrations/20210519104931 @@ -0,0 +1 @@ +c31cb40b6251704c699e7fa3e7392bb9eb73fefcd5b0268e2b8fc58df9e6075e
\ No newline at end of file diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md index 644e2d905ae..386102b4529 100644 --- a/doc/administration/integration/terminal.md +++ b/doc/administration/integration/terminal.md @@ -6,8 +6,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Web terminals **(FREE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7690) in GitLab 8.15. - With the introduction of the [Kubernetes integration](../../user/project/clusters/index.md), GitLab can store and use credentials for a Kubernetes cluster. GitLab uses these credentials to provide access to @@ -99,9 +97,9 @@ they receive a `Connection failed` message. ## Limiting WebSocket connection time -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/8413) in GitLab 8.17. +By default, terminal sessions do not expire. To limit the terminal session +lifetime in your GitLab instance: -Terminal sessions, by default, do not expire. -You can limit terminal session lifetime in your GitLab instance. To do so, -go to [**Admin Area > Settings > Web terminal**](../../user/admin_area/settings/index.md#general), -and set a `max session time`. +1. Go to the Admin Area (**{admin}**) and select + [**Settings > Web terminal**](../../user/admin_area/settings/index.md#general). +1. Set a `max session time`. diff --git a/doc/administration/packages/dependency_proxy.md b/doc/administration/packages/dependency_proxy.md index b454728cc8b..c4906ef6d8e 100644 --- a/doc/administration/packages/dependency_proxy.md +++ b/doc/administration/packages/dependency_proxy.md @@ -32,6 +32,23 @@ To enable the dependency proxy feature: 1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab") for the changes to take effect. 1. Enable the [Puma web server](https://docs.gitlab.com/omnibus/settings/puma.html). +**Helm chart installations** + +1. After the installation is complete, update the global `appConfig` to enable the feature: + + ```yaml + global: + appConfig: + dependencyProxy: + enabled: true + bucket: gitlab-dependency-proxy + connection: {} + secret: + key: + ``` + +For more information, see [Configure Charts using Globals](https://docs.gitlab.com/charts/charts/globals.html#configure-appconfig-settings). + **Installations from source** 1. After the installation is complete, configure the `dependency_proxy` diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index c6b79aee973..24f35bdab57 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -758,6 +758,7 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch | `if:` conditions | Description | Notes | |------------------|-------------|-------| | `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success|manual`), or **not** create a job for forks (by using `when: never`). | +| `if-not-ee` | Matches if the project isn't EE (i.e. project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success|manual`), or **not** create a job if the project is EE (by using `when: never`). | | `if-not-foss` | Matches if the project isn't FOSS (i.e. project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success|manual`), or **not** create a job if the project is FOSS (by using `when: never`). | | `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. | | `if-master-refs` | Matches if the current branch is `master` or `main`. | | @@ -787,16 +788,6 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch <!-- vale gitlab.Substitutions = YES --> -#### `exists:` conditions - -<!-- vale gitlab.Substitutions = NO --> - -| `exists:` conditions | Description | Notes | -|----------------------|-------------|-------| -| `exists-ee` | Matches if the project is EE (i.e. project contains `ee/` directory). | Use to create a job only in the EE project. | - -<!-- vale gitlab.Substitutions = YES --> - #### `changes:` patterns | `changes:` patterns | Description | diff --git a/doc/user/application_security/threat_monitoring/index.md b/doc/user/application_security/threat_monitoring/index.md index 825bc64d52b..443f82b70bb 100644 --- a/doc/user/application_security/threat_monitoring/index.md +++ b/doc/user/application_security/threat_monitoring/index.md @@ -165,7 +165,8 @@ button at the bottom of the editor. ### Configuring Network Policy Alerts -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9. +> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9. +> - The feature flag was removed and the Threat Monitoring Alerts Project was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 14.0. You can use policy alerts to track your policy's impact. Alerts are only available if you've [installed](../../clusters/agent/repository.md) @@ -186,25 +187,6 @@ There are two ways to create policy alerts: Once added, the UI updates and displays a warning about the dangers of too many alerts. -#### Enable or disable Policy Alerts **(ULTIMATE)** - -Policy Alerts is under development but ready for production use. -It is deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) -can opt to disable it. - -To enable it: - -```ruby -Feature.enable(:threat_monitoring_alerts) -``` - -To disable it: - -```ruby -Feature.disable(:threat_monitoring_alerts) -``` - ### Container Network Policy Alert list > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9. diff --git a/doc/user/project/pages/getting_started/pages_new_project_template.md b/doc/user/project/pages/getting_started/pages_new_project_template.md index 36371573fd9..e07b37a16d0 100644 --- a/doc/user/project/pages/getting_started/pages_new_project_template.md +++ b/doc/user/project/pages/getting_started/pages_new_project_template.md @@ -26,7 +26,6 @@ configured to generate a Pages site. and click **Run pipeline** to trigger GitLab CI/CD to build and deploy your site. -The site can take approximately 30 minutes to deploy. When the pipeline is finished, go to **Settings > Pages** to find the link to your Pages website. diff --git a/lib/gitlab/import_export/decompressed_archive_size_validator.rb b/lib/gitlab/import_export/decompressed_archive_size_validator.rb index 2baf2c61f7c..febfe00af0b 100644 --- a/lib/gitlab/import_export/decompressed_archive_size_validator.rb +++ b/lib/gitlab/import_export/decompressed_archive_size_validator.rb @@ -32,7 +32,16 @@ module Gitlab Timeout.timeout(TIMEOUT_LIMIT) do stdin, stdout, stderr, wait_thr = Open3.popen3(command, pgroup: true) stdin.close - pgrp = Process.getpgid(wait_thr[:pid]) + + # When validation is performed on a small archive (e.g. 100 bytes) + # `wait_thr` finishes before we can get process group id. Do not + # raise exception in this scenario. + pgrp = begin + Process.getpgid(wait_thr[:pid]) + rescue Errno::ESRCH + nil + end + status = wait_thr.value if status.success? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 147239f83b4..ec15cb103e8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -15233,9 +15233,6 @@ msgstr "" msgid "GitLabPages|GitLab Pages are disabled for this project. You can enable them on your project's %{strong_start}Settings > General > Visibility%{strong_end} page." msgstr "" -msgid "GitLabPages|It may take up to 30 minutes before the site is available after the first deployment." -msgstr "" - msgid "GitLabPages|Maximum size of pages (MB)" msgstr "" diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index b46d4dae87a..70a19445c89 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -13,6 +13,7 @@ RSpec.describe 'Group navbar' do let(:structure) do [ + group_context_nav_item, group_information_nav_item, { nav_item: _('Issues'), @@ -37,6 +38,13 @@ RSpec.describe 'Group navbar' do nil end + let(:group_context_nav_item) do + { + nav_item: "#{group.name[0, 1].upcase} #{group.name}", + nav_sub_items: [] + } + end + before do insert_package_nav(_('Kubernetes')) @@ -79,6 +87,10 @@ RSpec.describe 'Group navbar' do end context 'when feature flag :sidebar_refactor is disabled' do + let(:group_context_nav_item) do + nil + end + let(:group_information_nav_item) do { nav_item: _('Group overview'), diff --git a/spec/features/projects/pages/user_edits_settings_spec.rb b/spec/features/projects/pages/user_edits_settings_spec.rb index 412ba17cf20..71d4cce2784 100644 --- a/spec/features/projects/pages/user_edits_settings_spec.rb +++ b/spec/features/projects/pages/user_edits_settings_spec.rb @@ -39,12 +39,6 @@ RSpec.describe 'Pages edits pages settings', :js do end end - it 'renders first deployment warning' do - visit project_pages_path(project) - - expect(page).to have_content('It may take up to 30 minutes before the site is available after the first deployment.') - end - shared_examples 'does not render access control warning' do it 'does not render access control warning' do visit project_pages_path(project) diff --git a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb index 96c467e78d6..fe3b638d20f 100644 --- a/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb +++ b/spec/lib/gitlab/import_export/decompressed_archive_size_validator_spec.rb @@ -24,6 +24,14 @@ RSpec.describe Gitlab::ImportExport::DecompressedArchiveSizeValidator do it 'returns true' do expect(subject.valid?).to eq(true) end + + context 'when waiter thread no longer exists' do + it 'does not raise exception' do + allow(Process).to receive(:getpgid).and_raise(Errno::ESRCH) + + expect(subject.valid?).to eq(true) + end + end end context 'when file exceeds allowed decompressed size' do diff --git a/spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb b/spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb new file mode 100644 index 00000000000..5c0548da0fa --- /dev/null +++ b/spec/migrations/backfill_clusters_integration_prometheus_enabled_spec.rb @@ -0,0 +1,80 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! 'backfill_clusters_integration_prometheus_enabled' + +RSpec.describe BackfillClustersIntegrationPrometheusEnabled, :migration do + def create_cluster!(label = rand(2**64).to_s) + table(:clusters).create!( + name: "cluster: #{label}", + created_at: 1.day.ago, + updated_at: 1.day.ago + ) + end + + def create_clusters_applications_prometheus!(label, status:, cluster_id: nil) + table(:clusters_applications_prometheus).create!( + cluster_id: cluster_id || create_cluster!(label).id, + status: status, + version: "#{label}: version", + created_at: 1.day.ago, # artificially aged + updated_at: 1.day.ago, # artificially aged + encrypted_alert_manager_token: "#{label}: token", + encrypted_alert_manager_token_iv: "#{label}: iv" + ) + end + + def create_clusters_integration_prometheus! + table(:clusters_integration_prometheus).create!( + cluster_id: create_cluster!.id, + enabled: false, + created_at: 1.day.ago, + updated_at: 1.day.ago + ) + end + + RSpec::Matchers.define :be_enabled_and_match_application_values do |application| + match do |actual| + actual.enabled == true && + actual.encrypted_alert_manager_token == application.encrypted_alert_manager_token && + actual.encrypted_alert_manager_token_iv == application.encrypted_alert_manager_token_iv + end + end + + describe '#up' do + it 'backfills the enabled status and alert manager credentials from clusters_applications_prometheus' do + status_installed = 3 + status_externally_installed = 11 + status_installable = 0 + + existing_integration = create_clusters_integration_prometheus! + unaffected_existing_integration = create_clusters_integration_prometheus! + app_installed = create_clusters_applications_prometheus!('installed', status: status_installed) + app_installed_existing_integration = create_clusters_applications_prometheus!('installed, existing integration', status: status_installed, cluster_id: existing_integration.cluster_id) + app_externally_installed = create_clusters_applications_prometheus!('externally installed', status: status_externally_installed) + app_other_status = create_clusters_applications_prometheus!('other status', status: status_installable) + + migrate! + + integrations = table(:clusters_integration_prometheus).all.index_by(&:cluster_id) + + expect(unaffected_existing_integration.reload).to eq unaffected_existing_integration + + integration_installed = integrations[app_installed.cluster_id] + expect(integration_installed).to be_enabled_and_match_application_values(app_installed) + expect(integration_installed.updated_at).to be >= 1.minute.ago # recently updated + expect(integration_installed.updated_at).to eq(integration_installed.created_at) # recently created + + expect(existing_integration.reload).to be_enabled_and_match_application_values(app_installed_existing_integration) + expect(existing_integration.updated_at).to be >= 1.minute.ago # recently updated + expect(existing_integration.updated_at).not_to eq(existing_integration.created_at) # but not recently created + + integration_externally_installed = integrations[app_externally_installed.cluster_id] + expect(integration_externally_installed).to be_enabled_and_match_application_values(app_externally_installed) + expect(integration_externally_installed.updated_at).to be >= 1.minute.ago # recently updated + expect(integration_externally_installed.updated_at).to eq(integration_externally_installed.created_at) # recently created + + expect(integrations[app_other_status.cluster_id]).to be_nil + end + end +end diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 247be7654d8..72cd028b0b9 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -778,10 +778,27 @@ RSpec.describe Member do let(:invited_member) { create(:project_member, invite_email: "user@example.com", user: nil) } let(:requester) { create(:project_member, requested_at: Time.current.utc) } - it { expect(invited_member).to be_invite } + it { expect(invited_member).to be_pending } it { expect(requester).to be_pending } end + describe '#hook_prerequisites_met?' do + let(:member) { create(:project_member) } + + context 'when the member does not have an associated user' do + it 'returns false' do + member.update_column(:user_id, nil) + expect(member.reload.hook_prerequisites_met?).to eq(false) + end + end + + context 'when the member has an associated user' do + it 'returns true' do + expect(member.hook_prerequisites_met?).to eq(true) + end + end + end + describe "#accept_invite!" do let!(:member) { create(:project_member, invite_email: "user@example.com", user: nil) } let(:user) { create(:user) } diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index 4f8e88ae9da..32c79905236 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -200,8 +200,16 @@ RSpec.shared_context 'group navbar structure' do ] end + let(:group_context_nav_item) do + { + nav_item: "#{group.name[0, 1].upcase} #{group.name}", + nav_sub_items: [] + } + end + let(:structure) do [ + group_context_nav_item, group_information_nav_item, { nav_item: _('Issues'), diff --git a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb index d96052d4c03..50390964e1b 100644 --- a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb @@ -12,11 +12,19 @@ RSpec.describe 'layouts/nav/sidebar/_group' do it_behaves_like 'has nav sidebar' it_behaves_like 'sidebar includes snowplow attributes', 'render', 'groups_side_navigation', 'groups_side_navigation' - describe 'Group information' do + describe 'Group context menu' do it 'has a link to the group path' do render - expect(rendered).to have_link('Group information', href: group_path(group)) + expect(rendered).to have_link(group.name, href: group_path(group)) + end + end + + describe 'Group information' do + it 'has a link to the group activity path' do + render + + expect(rendered).to have_link('Group information', href: activity_group_path(group)) end it 'does not have a link to the details menu item' do |