Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-07-14 00:09:32 +00:00
parent 75f2fd2ba8
commit 804348d39b
61 changed files with 739 additions and 813 deletions

View File

@ -2531,8 +2531,9 @@
- "scripts/rspec_helpers.sh"
- <<: *if-merge-request
changes:
- "gems/gitlab-rspec"
- "gems/rspec_flaky"
- "gems/gitlab-rspec/**/*"
- "gems/rspec_flaky/**/*"
- "scripts/flaky_examples/prune-old-flaky-examples"
###################
# workhorse rules #

View File

@ -45,7 +45,7 @@ update-tests-metadata:
- rspec-ee system pg14
- rspec-ee background_migration pg14
script:
- run_timed_command "retry gem install fog-aws mime-types activesupport rspec rspec_profiling postgres-copy --no-document"
- run_timed_command "retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document"
- source ./scripts/rspec_helpers.sh
- test -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo -e "\e[31m" 'Consider add ~"pipeline:run-all-rspec" to run full rspec jobs' "\e[0m"
- update_tests_metadata

View File

@ -1,6 +1,7 @@
---
# Cop supports --autocorrect.
Gitlab/StrongMemoizeAttr:
Details: grace period
Exclude:
- 'app/components/pajamas/avatar_component.rb'
- 'app/controllers/application_controller.rb'
@ -27,7 +28,6 @@ Gitlab/StrongMemoizeAttr:
- 'app/controllers/projects/incidents_controller.rb'
- 'app/controllers/projects/merge_requests/drafts_controller.rb'
- 'app/controllers/projects/merge_requests_controller.rb'
- 'app/controllers/projects/metrics_dashboard_controller.rb'
- 'app/controllers/projects/milestones_controller.rb'
- 'app/controllers/projects/pipelines/application_controller.rb'
- 'app/controllers/projects/pipelines_controller.rb'
@ -52,7 +52,6 @@ Gitlab/StrongMemoizeAttr:
- 'app/finders/merge_requests_finder/params.rb'
- 'app/finders/projects/members/effective_access_level_finder.rb'
- 'app/finders/releases/evidence_pipeline_finder.rb'
- 'app/finders/releases_finder.rb'
- 'app/finders/snippets_finder.rb'
- 'app/finders/todos_finder.rb'
- 'app/graphql/resolvers/issue_status_counts_resolver.rb'
@ -125,7 +124,6 @@ Gitlab/StrongMemoizeAttr:
- 'app/models/namespaces/traversal/linear.rb'
- 'app/models/namespaces/traversal/recursive.rb'
- 'app/models/note.rb'
- 'app/models/pages/lookup_path.rb'
- 'app/models/project.rb'
- 'app/models/release.rb'
- 'app/models/resource_event.rb'
@ -134,7 +132,6 @@ Gitlab/StrongMemoizeAttr:
- 'app/models/snippet_input_action_collection.rb'
- 'app/models/state_note.rb'
- 'app/models/tree.rb'
- 'app/models/uploads/fog.rb'
- 'app/models/user.rb'
- 'app/models/wiki_page.rb'
- 'app/models/work_item.rb'
@ -249,7 +246,6 @@ Gitlab/StrongMemoizeAttr:
- 'app/workers/merge_request_cleanup_refs_worker.rb'
- 'app/workers/packages/cleanup/execute_policy_worker.rb'
- 'app/workers/packages/debian/generate_distribution_worker.rb'
- 'app/workers/packages/debian/process_changes_worker.rb'
- 'app/workers/packages/maven/metadata/sync_worker.rb'
- 'app/workers/projects/inactive_projects_deletion_cron_worker.rb'
- 'ee/app/controllers/admin/audit_logs_controller.rb'
@ -283,10 +279,10 @@ Gitlab/StrongMemoizeAttr:
- 'ee/app/helpers/ee/preferences_helper.rb'
- 'ee/app/helpers/ee/registrations_helper.rb'
- 'ee/app/helpers/ee/timeboxes_helper.rb'
- 'ee/app/helpers/trials_helper.rb'
- 'ee/app/helpers/welcome_helper.rb'
- 'ee/app/helpers/license_monitoring_helper.rb'
- 'ee/app/helpers/subscriptions_helper.rb'
- 'ee/app/helpers/trials_helper.rb'
- 'ee/app/helpers/welcome_helper.rb'
- 'ee/app/models/approval_merge_request_rule.rb'
- 'ee/app/models/approval_state.rb'
- 'ee/app/models/approval_wrapped_any_approver_rule.rb'
@ -316,7 +312,6 @@ Gitlab/StrongMemoizeAttr:
- 'ee/app/models/ee/namespace.rb'
- 'ee/app/models/ee/project.rb'
- 'ee/app/models/ee/snippet.rb'
- 'ee/app/models/ee/user.rb'
- 'ee/app/models/ee/work_item.rb'
- 'ee/app/models/gitlab/seat_link_data.rb'
- 'ee/app/models/gitlab_subscription.rb'
@ -328,6 +323,7 @@ Gitlab/StrongMemoizeAttr:
- 'ee/app/models/vulnerabilities/finding.rb'
- 'ee/app/presenters/approval_rule_presenter.rb'
- 'ee/app/presenters/ci/minutes/usage_presenter.rb'
- 'ee/app/presenters/merge_request_approver_presenter.rb'
- 'ee/app/serializers/dashboard_operations_project_entity.rb'
- 'ee/app/serializers/ee/member_user_entity.rb'
- 'ee/app/services/app_sec/dast/pipelines/find_latest_service.rb'
@ -337,7 +333,6 @@ Gitlab/StrongMemoizeAttr:
- 'ee/app/services/ci/compare_license_scanning_reports_collapsed_service.rb'
- 'ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb'
- 'ee/app/services/ci/subscribe_bridge_service.rb'
- 'ee/app/services/ci/sync_reports_to_approval_rules_service.rb'
- 'ee/app/services/deployments/approval_service.rb'
- 'ee/app/services/ee/allowed_email_domains/update_service.rb'
- 'ee/app/services/ee/auto_merge_service.rb'
@ -388,13 +383,11 @@ Gitlab/StrongMemoizeAttr:
- 'ee/app/services/status_page/publish_service.rb'
- 'ee/app/services/status_page/trigger_publish_service.rb'
- 'ee/app/services/timebox_report_service.rb'
- 'ee/app/services/vulnerabilities/create_service.rb'
- 'ee/app/services/vulnerability_feedback/create_service.rb'
- 'ee/app/services/vulnerability_feedback/destroy_service.rb'
- 'ee/app/workers/auth/saml_group_sync_worker.rb'
- 'ee/app/workers/geo/repository_cleanup_worker.rb'
- 'ee/app/workers/geo/scheduler/scheduler_worker.rb'
- 'ee/app/workers/group_saml_group_sync_worker.rb'
- 'ee/app/workers/status_page/publish_worker.rb'
- 'ee/lib/api/analytics/project_deployment_frequency.rb'
- 'ee/lib/api/epic_links.rb'
@ -416,7 +409,6 @@ Gitlab/StrongMemoizeAttr:
- 'ee/lib/ee/gitlab/checks/diff_check.rb'
- 'ee/lib/ee/gitlab/ci/matching/runner_matcher.rb'
- 'ee/lib/ee/gitlab/ci/pipeline/chain/validate/external.rb'
- 'ee/lib/ee/gitlab/ci/pipeline/quota/activity.rb'
- 'ee/lib/ee/gitlab/ci/pipeline/quota/size.rb'
- 'ee/lib/ee/gitlab/etag_caching/router/rails.rb'
- 'ee/lib/ee/gitlab/git_access.rb'
@ -426,7 +418,6 @@ Gitlab/StrongMemoizeAttr:
- 'ee/lib/ee/gitlab/security/scan_configuration.rb'
- 'ee/lib/ee/gitlab/web_hooks/rate_limiter.rb'
- 'ee/lib/ee/sidebars/groups/menus/issues_menu.rb'
- 'ee/lib/ee/sidebars/groups/menus/settings_menu.rb'
- 'ee/lib/elastic/multi_version_util.rb'
- 'ee/lib/gitlab/auth/group_saml/auth_hash.rb'
- 'ee/lib/gitlab/auth/group_saml/membership_updater.rb'
@ -480,7 +471,6 @@ Gitlab/StrongMemoizeAttr:
- 'lib/atlassian/jira_connect/jwt/symmetric.rb'
- 'lib/banzai/filter/base_sanitization_filter.rb'
- 'lib/banzai/filter/custom_emoji_filter.rb'
- 'lib/banzai/filter/inline_metrics_redactor_filter.rb'
- 'lib/banzai/filter/issuable_reference_expansion_filter.rb'
- 'lib/banzai/filter/references/reference_cache.rb'
- 'lib/banzai/filter/repository_link_filter.rb'
@ -570,7 +560,6 @@ Gitlab/StrongMemoizeAttr:
- 'lib/gitlab/config/entry/composable_array.rb'
- 'lib/gitlab/config/loader/yaml.rb'
- 'lib/gitlab/conflict/file.rb'
- 'lib/gitlab/database/background_migration/health_status/indicators/write_ahead_log.rb'
- 'lib/gitlab/database/bulk_update.rb'
- 'lib/gitlab/database/load_balancing/srv_resolver.rb'
- 'lib/gitlab/database/metrics.rb'
@ -613,7 +602,6 @@ Gitlab/StrongMemoizeAttr:
- 'lib/gitlab/import_export/importer.rb'
- 'lib/gitlab/import_export/lfs_restorer.rb'
- 'lib/gitlab/import_export/project/sample/date_calculator.rb'
- 'lib/gitlab/import_export/project/tree_restorer.rb'
- 'lib/gitlab/inactive_projects_deletion_warning_tracker.rb'
- 'lib/gitlab/instrumentation/redis_base.rb'
- 'lib/gitlab/instrumentation/redis_payload.rb'

View File

@ -173,18 +173,11 @@ export default {
item.text.toLowerCase().includes(lowerCasedSearchTerm),
);
},
isKasUserAccessAvailable() {
return this.glFeatures?.kasUserAccessProject;
},
isKasKubernetesNamespaceAvailable() {
return this.glFeatures?.kubernetesNamespaceForEnvironment;
},
showNamespaceSelector() {
return Boolean(
this.isKasUserAccessAvailable &&
this.isKasKubernetesNamespaceAvailable &&
this.selectedAgentId,
);
return Boolean(this.isKasKubernetesNamespaceAvailable && this.selectedAgentId);
},
namespaceDropdownToggleText() {
return this.selectedNamespace || this.$options.i18n.namespaceHelpText;

View File

@ -165,15 +165,9 @@ export default {
rolloutStatus() {
return this.environment?.rolloutStatus;
},
isKubernetesOverviewAvailable() {
return this.glFeatures?.kasUserAccessProject;
},
isKubernetesNamespaceAvailable() {
return this.glFeatures?.kubernetesNamespaceForEnvironment;
},
showKubernetesOverview() {
return Boolean(this.isKubernetesOverviewAvailable && this.clusterAgent);
},
},
methods: {
toggleEnvironmentCollapse() {
@ -184,7 +178,7 @@ export default {
}
},
getClusterAgent() {
if (!this.isKubernetesOverviewAvailable || this.clusterAgent) return;
if (this.clusterAgent) return;
this.$apollo.addSmartQuery('environmentClusterAgent', {
variables() {
@ -377,7 +371,7 @@ export default {
</template>
</gl-sprintf>
</div>
<div v-if="showKubernetesOverview" :class="$options.kubernetesOverviewClasses">
<div v-if="clusterAgent" :class="$options.kubernetesOverviewClasses">
<kubernetes-overview :cluster-agent="clusterAgent" :namespace="kubernetesNamespace" />
</div>
<div v-if="rolloutStatus" :class="$options.deployBoardClasses">

View File

@ -2,6 +2,7 @@
import { GlButton, GlEmptyState, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import { createAlert, VARIANT_INFO } from '~/alert';
import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
import { fetchPolicies } from '~/lib/graphql';
import { historyReplaceState } from '~/lib/utils/common_utils';
import { s__ } from '~/locale';
import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages_and_registries/shared/constants';
@ -38,11 +39,13 @@ export default {
sort: '',
filters: {},
mutationLoading: false,
pageParams: {},
};
},
apollo: {
packagesResource: {
query: getPackagesQuery,
fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
variables() {
return this.queryVariables;
},
@ -72,6 +75,7 @@ export default {
packageName: this.filters?.packageName,
packageType: this.filters?.packageType,
first: GRAPHQL_PAGE_SIZE,
...this.pageParams,
};
},
graphqlResource() {
@ -120,37 +124,22 @@ export default {
}
},
handleSearchUpdate({ sort, filters }) {
this.pageParams = {};
this.sort = sort;
this.filters = { ...filters };
},
updateQuery(_, { fetchMoreResult }) {
return fetchMoreResult;
},
fetchNextPage() {
const variables = {
...this.queryVariables,
this.pageParams = {
first: GRAPHQL_PAGE_SIZE,
last: null,
after: this.pageInfo?.endCursor,
};
this.$apollo.queries.packagesResource.fetchMore({
variables,
updateQuery: this.updateQuery,
});
},
fetchPreviousPage() {
const variables = {
...this.queryVariables,
this.pageParams = {
first: null,
last: GRAPHQL_PAGE_SIZE,
before: this.pageInfo?.startCursor,
};
this.$apollo.queries.packagesResource.fetchMore({
variables,
updateQuery: this.updateQuery,
});
},
},
i18n: {

View File

@ -2,6 +2,7 @@ import Vue from 'vue';
import Vuex from 'vuex';
import VueApollo from 'vue-apollo';
import VueRouter from 'vue-router';
import { provideWebIdeLink } from 'ee_else_ce/pages/projects/shared/web_ide_link/provide_web_ide_link';
import TableOfContents from '~/blob/components/table_contents.vue';
import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue';
import { BlobViewer, initAuxiliaryViewer } from '~/blob/viewer/index';
@ -70,6 +71,7 @@ if (viewBlobEl) {
resourceId,
userId,
explainCodeAvailable,
...dataset
} = viewBlobEl.dataset;
// eslint-disable-next-line no-new
@ -85,6 +87,7 @@ if (viewBlobEl) {
resourceId,
userId,
explainCodeAvailable: parseBoolean(explainCodeAvailable),
...provideWebIdeLink(dataset),
},
render(createElement) {
return createElement(BlobContentViewer, {

View File

@ -1,8 +1,9 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { provideWebIdeLink } from 'ee_else_ce/pages/projects/shared/web_ide_link/provide_web_ide_link';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { joinPaths, webIDEUrl } from '~/lib/utils/url_utility';
import WebIdeButton from '~/vue_shared/components/web_ide_link.vue';
import WebIdeButton from 'ee_else_ce/vue_shared/components/web_ide_link.vue';
import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
@ -26,6 +27,7 @@ export default ({ el, router }) => {
apolloProvider,
provide: {
projectPath,
...provideWebIdeLink(options),
},
render(h) {
return h(WebIdeButton, {
@ -37,6 +39,7 @@ export default ({ el, router }) => {
: webIDEUrl(
joinPaths('/', projectPath, 'edit', ref, '-', this.$route?.params.path || '', '/'),
),
projectPath,
...options,
},
});

View File

@ -0,0 +1,9 @@
/**
* Inspects an object and extracts properties
* that are relevant to the web_ide_link.vue
* component.
*
* @returns An object with properties that are
* relevant to the web_ide_link.vue component. See EE version.
*/
export const provideWebIdeLink = () => ({});

View File

@ -7,10 +7,11 @@ import { SIMPLE_BLOB_VIEWER, RICH_BLOB_VIEWER } from '~/blob/components/constant
import { createAlert } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import { isLoggedIn, handleLocationHash } from '~/lib/utils/common_utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import { redirectTo, getLocationHash } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
import WebIdeLink from 'ee_else_ce/vue_shared/components/web_ide_link.vue';
import CodeIntelligence from '~/code_navigation/components/app.vue';
import LineHighlighter from '~/blob/line_highlighter';
import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
@ -226,6 +227,9 @@ export default {
isUsingLfs() {
return this.blobInfo.storedExternally && this.blobInfo.externalStorage === LFS_STORAGE;
},
projectIdAsNumber() {
return getIdFromGraphQLId(this.project?.id);
},
},
watch: {
// Watch the URL 'plain' query value to know if the viewer needs changing.
@ -356,6 +360,8 @@ export default {
:gitpod-url="blobInfo.gitpodBlobUrl"
:show-gitpod-button="gitpodEnabled"
:gitpod-enabled="currentUser && currentUser.gitpodEnabled"
:project-path="projectPath"
:project-id="projectIdAsNumber"
:user-preferences-gitpod-path="currentUser && currentUser.preferencesGitpodPath"
:user-profile-enable-gitpod-path="currentUser && currentUser.profileEnableGitpodPath"
is-blob

View File

@ -45,8 +45,12 @@ export default {
:category="category"
:toggle-text="toggleText"
data-qa-selector="action_dropdown"
fluid-width
block
@shown="$emit('shown')"
@hidden="$emit('hidden')"
>
<gl-disclosure-dropdown-group>
<gl-disclosure-dropdown-group class="edit-dropdown-group-width">
<gl-disclosure-dropdown-item
v-for="action in actions"
:key="action.key"
@ -65,5 +69,6 @@ export default {
</template>
</gl-disclosure-dropdown-item>
</gl-disclosure-dropdown-group>
<slot></slot>
</gl-disclosure-dropdown>
</template>

View File

@ -23,6 +23,7 @@ export const i18n = {
};
export default {
name: 'CEWebIdeLink',
components: {
ActionsButton,
GlModal,
@ -319,7 +320,11 @@ export default {
:toggle-text="$options.i18n.toggleText"
:variant="isBlob ? 'confirm' : 'default'"
:category="isBlob ? 'primary' : 'secondary'"
/>
@hidden="$emit('hidden')"
@shown="$emit('shown')"
>
<slot></slot>
</actions-button>
<gl-modal
v-if="computedShowGitpodButton && !gitpodEnabled"
v-model="showEnableGitpodModal"

View File

@ -205,17 +205,6 @@
margin-top: $gl-padding;
}
.web-ide-promo-popover {
box-shadow: 0 0 18px -1.9px rgba(119, 89, 194, 0.16),
0 0 12.9px -1.7px rgba(119, 89, 194, 0.16), 0 0 9.2px -1.4px rgba(119, 89, 194, 0.16),
0 0 6.4px -1.1px rgba(119, 89, 194, 0.16), 0 0 4.5px -0.8px rgba(119, 89, 194, 0.16),
0 0 3px -0.6px rgba(119, 89, 194, 0.16), 0 0 1.8px -0.3px rgba(119, 89, 194, 0.16),
0 0 0.6px rgba(119, 89, 194, 0.16);
z-index: 999;
}
.web-ide-promo-popover-illustration {
width: calc(100% + 24px);
margin: -28px -12px 0;
.edit-dropdown-group-width {
width: 320px;
}

View File

@ -13,7 +13,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
end
before_action only: [:index, :edit, :new] do
push_frontend_feature_flag(:kas_user_access_project, @project)
push_frontend_feature_flag(:kubernetes_namespace_for_environment)
end

View File

@ -172,18 +172,6 @@ module ProjectsHelper
project.fork_source if project.fork_source && can?(current_user, :read_project, project.fork_source)
end
def project_search_tabs?(tab)
return false unless @project.present?
abilities = Array(search_tab_ability_map[tab])
if @project.respond_to?(:each) # support multi-project select
@project.any? { |project| abilities.any? { |ability| can?(current_user, ability, project) } }
else
abilities.any? { |ability| can?(current_user, ability, @project) }
end
end
def can_change_visibility_level?(project, current_user)
can?(current_user, :change_visibility_level, project)
end
@ -614,41 +602,6 @@ module ProjectsHelper
s_(str).html_safe % { provider: provider, link_start: link_start, link_end: '</a>'.html_safe }
end
def tab_ability_map
{
cycle_analytics: :read_cycle_analytics,
environments: :read_environment,
metrics_dashboards: :metrics_dashboard,
milestones: :read_milestone,
snippets: :read_snippet,
settings: :admin_project,
builds: :read_build,
clusters: :read_cluster,
serverless: :read_cluster,
terraform: :read_terraform_state,
error_tracking: :read_sentry_issue,
alert_management: :read_alert_management_alert,
incidents: :read_issue,
labels: :read_label,
issues: :read_issue,
project_members: :read_project_member,
wiki: :read_wiki,
feature_flags: :read_feature_flag,
analytics: :read_analytics
}
end
def search_tab_ability_map
@search_tab_ability_map ||= tab_ability_map.merge(
blobs: :read_code,
commits: :read_code,
merge_requests: :read_merge_request,
notes: [:read_merge_request, :read_code, :read_issue, :read_snippet],
users: :read_project_member,
wiki_blobs: :read_wiki
)
end
def project_lfs_status(project)
if project.lfs_enabled?
content_tag(:span, class: 'lfs-enabled') do

View File

@ -464,65 +464,15 @@ module SearchHelper
result
end
def show_code_search_tab?
return true if project_search_tabs?(:blobs)
@project.nil? && search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_code_tab)
end
def show_wiki_search_tab?
return true if project_search_tabs?(:wiki_blobs)
@project.nil? && search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_wiki_tab)
end
def show_commits_search_tab?
return true if project_search_tabs?(:commits)
@project.nil? && search_service.show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_commits_tab)
end
def show_issues_search_tab?
return true if project_search_tabs?(:issues)
@project.nil? && feature_flag_tab_enabled?(:global_search_issues_tab)
end
def show_merge_requests_search_tab?
return true if project_search_tabs?(:merge_requests)
@project.nil? && feature_flag_tab_enabled?(:global_search_merge_requests_tab)
end
def show_comments_search_tab?
return true if project_search_tabs?(:notes)
@project.nil? && search_service.show_elasticsearch_tabs?
end
def show_snippets_search_tab?
search_service.show_snippets? && @project.nil? && feature_flag_tab_enabled?(:global_search_snippet_titles_tab)
end
# search page scope navigation
def search_navigation
def nav_options
{
projects: { sort: 1, label: _("Projects"), data: { qa_selector: 'projects_tab' }, condition: @project.nil? },
blobs: { sort: 2, label: _("Code"), data: { qa_selector: 'code_tab' }, condition: show_code_search_tab? },
# sort: 3 is reserved for EE items
issues: { sort: 4, label: _("Issues"), condition: show_issues_search_tab? },
merge_requests: { sort: 5, label: _("Merge requests"), condition: show_merge_requests_search_tab? },
wiki_blobs: { sort: 6, label: _("Wiki"), condition: show_wiki_search_tab? },
commits: { sort: 7, label: _("Commits"), condition: show_commits_search_tab? },
notes: { sort: 8, label: _("Comments"), condition: show_comments_search_tab? },
milestones: { sort: 9, label: _("Milestones"), condition: project_search_tabs?(:milestones) || @project.nil? },
users: { sort: 10, label: _("Users"), condition: show_user_search_tab? },
snippet_titles: { sort: 11, label: _("Snippets"), search: { snippets: true, group_id: nil, project_id: nil }, condition: show_snippets_search_tab? }
show_snippets: search_service.show_snippets?
}
end
def search_navigation_json
sorted_navigation = search_navigation.sort_by { |_, h| h[:sort] }
search_navigation = Search::Navigation.new(user: current_user, project: @project, group: @group, options: nav_options)
sorted_navigation = search_navigation.tabs.sort_by { |_, h| h[:sort] }
sorted_navigation.each_with_object({}) do |(key, value), hash|
hash[key] = search_filter_link_json(key, value[:label], value[:data], value[:search]) if value[:condition]
@ -604,14 +554,6 @@ module SearchHelper
simple_search_highlight_and_truncate(issuable.description, search_term, highlighter: '<span class="gl-text-gray-900 gl-font-weight-bold">\1</span>')
end
def show_user_search_tab?
return project_search_tabs?(:users) if @project
return false unless can?(current_user, :read_users_list)
return true if @group
Feature.enabled?(:global_search_users_tab, current_user, type: :ops)
end
def issuable_state_to_badge_class(issuable)
# Closed is considered "danger" for MR so we need to handle separately
if issuable.is_a?(::MergeRequest)
@ -640,10 +582,6 @@ module SearchHelper
end
end
def feature_flag_tab_enabled?(flag)
@group.present? || Feature.enabled?(flag, current_user, type: :ops)
end
def sanitized_search_params
sanitized_params = params.dup

View File

@ -66,7 +66,6 @@ module Clusters
def ci_access_authorized_for?(user)
return false unless user
return false unless ::Feature.enabled?(:expose_authorized_cluster_agents, project)
all_ci_access_authorized_projects_for(user).exists? ||
all_ci_access_authorized_namespaces_for(user).exists?
@ -74,7 +73,6 @@ module Clusters
def user_access_authorized_for?(user)
return false unless user
return false unless ::Feature.enabled?(:expose_authorized_cluster_agents, project)
Clusters::Agents::Authorizations::UserAccess::Finder
.new(user, agent: self, preload: false, limit: 1).execute.any?

View File

@ -4,7 +4,6 @@ module Search
class ProjectService
include Search::Filter
include Gitlab::Utils::StrongMemoize
include ProjectsHelper
ALLOWED_SCOPES = %w(blobs issues merge_requests wiki_blobs commits notes milestones users).freeze
@ -18,13 +17,13 @@ module Search
def execute
Gitlab::ProjectSearchResults.new(current_user,
params[:search],
project: project,
repository_ref: params[:repository_ref],
order_by: params[:order_by],
sort: params[:sort],
filters: filters
)
params[:search],
project: project,
repository_ref: params[:repository_ref],
order_by: params[:order_by],
sort: params[:sort],
filters: filters
)
end
def allowed_scopes
@ -33,10 +32,12 @@ module Search
def scope
strong_memoize(:scope) do
next params[:scope] if allowed_scopes.include?(params[:scope]) && project_search_tabs?(params[:scope].to_sym)
search_navigation = Search::Navigation.new(user: current_user, project: project)
scope = params[:scope]
next scope if allowed_scopes.include?(scope) && search_navigation.tab_enabled_for_project?(scope.to_sym)
allowed_scopes.find do |scope|
project_search_tabs?(scope.to_sym)
allowed_scopes.find do |s|
search_navigation.tab_enabled_for_project?(s.to_sym)
end
end
end

View File

@ -102,16 +102,6 @@ class SearchService
end
end
def show_elasticsearch_tabs?
# overridden in EE
false
end
def show_epics?
# overridden in EE
false
end
def global_search_enabled_for_scope?
return false if show_snippets? && Feature.disabled?(:global_search_snippet_titles_tab, current_user, type: :ops)

View File

@ -1,7 +1,4 @@
- gitlab_com = Gitlab.com?
- return unless Feature.enabled?(:slack_app_self_managed) || gitlab_com
- expanded = integration_expanded?('slack_app_')
%section.settings.as-slack.no-animate#js-slack-settings{ class: ('expanded' if expanded) }

View File

@ -1,8 +0,0 @@
---
name: expose_authorized_cluster_agents
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117128
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/407841
milestone: '16.0'
type: development
group: group::environments
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: kas_user_access
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104504'
rollout_issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391201'
milestone: '15.10'
type: development
group: group::environments
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: kas_user_access_project
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104504'
rollout_issue_url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391211'
milestone: '15.10'
type: development
group: group::environments
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: slack_app_self_managed
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124823
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/416448
milestone: '16.2'
type: development
group: group::import and integrate
default_enabled: false

View File

@ -807,6 +807,9 @@ Gitlab.ee do
Settings.cron_jobs['vulnerability_historical_statistics_deletion_worker'] ||= {}
Settings.cron_jobs['vulnerability_historical_statistics_deletion_worker']['cron'] ||= '15 3 * * *'
Settings.cron_jobs['vulnerability_historical_statistics_deletion_worker']['job_class'] = 'Vulnerabilities::HistoricalStatistics::DeletionWorker'
Settings.cron_jobs['vulnerability_orphaned_remediations_cleanup_worker'] ||= {}
Settings.cron_jobs['vulnerability_orphaned_remediations_cleanup_worker']['job_class'] = 'Vulnerabilities::OrphanedRemediationsCleanupWorker'
Settings.cron_jobs['vulnerability_orphaned_remediations_cleanup_worker']['cron'] ||= '15 3 3 * *'
Settings.cron_jobs['security_create_orchestration_policy_worker'] ||= {}
Settings.cron_jobs['security_create_orchestration_policy_worker']['cron'] ||= '*/10 * * * *'
Settings.cron_jobs['security_create_orchestration_policy_worker']['job_class'] = 'Security::CreateOrchestrationPolicyWorker'

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class ChangePmAdvisoriesUrlsConstraint < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
CONSTRAINT_NAME = "chk_rails_e73af9de76"
def up
remove_check_constraint :pm_advisories, CONSTRAINT_NAME
add_check_constraint :pm_advisories, "CARDINALITY(urls) <= 20", CONSTRAINT_NAME
end
def down
remove_check_constraint :pm_advisories, CONSTRAINT_NAME
add_check_constraint :pm_advisories, "CARDINALITY(urls) <= 10", CONSTRAINT_NAME
end
end

View File

@ -0,0 +1 @@
8fcab29ea25760d876c2b985cf9e4f2a62e25450322a92fe769533b0882b5402

View File

@ -20285,7 +20285,7 @@ CREATE TABLE pm_advisories (
CONSTRAINT check_bed97fa77a CHECK ((char_length(cvss_v3) <= 128)),
CONSTRAINT check_e4bfd3ffbf CHECK ((char_length(title) <= 256)),
CONSTRAINT check_fee880f7aa CHECK ((char_length(description) <= 8192)),
CONSTRAINT chk_rails_e73af9de76 CHECK ((cardinality(urls) <= 10))
CONSTRAINT chk_rails_e73af9de76 CHECK ((cardinality(urls) <= 20))
);
CREATE SEQUENCE pm_advisories_id_seq

View File

@ -142,10 +142,9 @@ For details, see [how to use the GitLab-KAS chart](https://docs.gitlab.com/chart
## Kubernetes API proxy cookie
> Introduced in GitLab 15.10 [with feature flags](../feature_flags.md) named `kas_user_access` and `kas_user_access_project`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flags](../feature_flags.md) named `kas_user_access` and `kas_user_access_project`.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/104504) in GitLab 15.10 [with feature flags](../feature_flags.md) named `kas_user_access` and `kas_user_access_project`. Disabled by default.
> - Feature flags `kas_user_access` and `kas_user_access_project` [enabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123479) in GitLab 16.1.
> - Feature flags `kas_user_access` and `kas_user_access_project` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125835) in GitLab 16.2.
KAS proxies Kubernetes API requests to the GitLab agent with either:

View File

@ -415,7 +415,7 @@ authentication mode (`patroni['tls_client_mode']`), must each have the same valu
1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`CONSUL_PASSWORD_HASH`](#consul-information), and [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information) before executing the next step.
1. One each node, edit the `/etc/gitlab/gitlab.rb` configuration file and replace values noted in the `# START user configuration` section as below:
1. On each node, edit the `/etc/gitlab/gitlab.rb` configuration file and replace values noted in the `# START user configuration` section as below:
```ruby
# Disable all components except PgBouncer and Consul agent
@ -864,7 +864,7 @@ patroni['remove_data_directory_on_rewind_failure'] = false
patroni['remove_data_directory_on_diverged_timelines'] = false
```
[The upstream documentation is always more up to date](https://patroni.readthedocs.io/en/latest/SETTINGS.html#postgresql), but the table below should provide a minimal overview of functionality.
[The upstream documentation is always more up to date](https://patroni.readthedocs.io/en/latest/patroni_configuration.html), but the table below should provide a minimal overview of functionality.
|Setting|Overview|
|-|-|

View File

@ -7,8 +7,9 @@ type: reference
# Dashboard for Kubernetes (Beta) **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../policy/experiment-beta-support.md#beta).
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../administration/feature_flags.md) named `environment_settings_to_graphql`, `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../policy/experiment-beta-support.md#beta).
> - Feature flag `environment_settings_to_graphql` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124177) in GitLab 16.2.
> - Feature flags `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125835) in GitLab 16.2.
Use the Dashboard for Kubernetes to understand the status of your clusters with an intuitive visual interface.
The dashboard works with every connected Kubernetes cluster, whether you deployed them

View File

@ -316,6 +316,13 @@ Example migration:
Changing column defaults is difficult because of how Rails handles values
that are equal to the default.
NOTE:
Rails ignores sending the default values to PostgreSQL when writing records. It leaves this task to
the database. When migrations change the default values of the columns, the running application is unaware
of this change due to the schema cache. The application is then under the risk of accidentally writing
wrong data to the database, especially when deploying the new version of the code
long after we run database migrations.
If running code ever explicitly writes the old default value of a column, you must follow a multi-step
process to prevent Rails replacing the old default with the new default in INSERT queries that explicitly
specify the old default.

View File

@ -16,6 +16,8 @@ delivery from customer launch.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an example of feature flags in action, see [Feature Flags configuration, instrumentation and use](https://www.youtube.com/watch?v=ViA6suScxkE).
You can also explore feature flags with a [click-through demo](https://go.gitlab.com/YKuzLt).
NOTE:
To contribute to the development of the GitLab product, view
[this feature flag content](../development/feature_flags/index.md) instead.

View File

@ -6,10 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab for Slack app administration **(FREE SELF)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358872) for self-managed instances in GitLab 16.2 [with a flag](../../../administration/feature_flags.md) named `slack_app_self_managed`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `slack_app_self_managed`. On GitLab.com, this feature is available.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358872) for self-managed instances in GitLab 16.2.
NOTE:
This page contains information about administering the GitLab for Slack app for self-managed instances. For user documentation, see [GitLab for Slack app](../../../user/project/integrations/gitlab_slack_application.md).

View File

@ -6,8 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Grant users Kubernetes access (Beta) **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../../administration/feature_flags.md) named `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../../policy/experiment-beta-support.md#beta).
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/390769) in GitLab 16.1, with [flags](../../../administration/feature_flags.md) named `environment_settings_to_graphql`, `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents`. This feature is in [Beta](../../../policy/experiment-beta-support.md#beta).
> - Feature flag `environment_settings_to_graphql` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124177) in GitLab 16.2.
> - Feature flags `kas_user_access`, `kas_user_access_project`, and `expose_authorized_cluster_agents` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125835) in GitLab 16.2.
As an administrator of Kubernetes clusters in an organization, you can grant Kubernetes access to members
of a specific project or group.

View File

@ -6,10 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab for Slack app **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358872) for self-managed instances in GitLab 16.2 [with a flag](../../../administration/feature_flags.md) named `slack_app_self_managed`. Disabled by default.
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `slack_app_self_managed`. On GitLab.com, this feature is available.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/358872) for self-managed instances in GitLab 16.2.
NOTE:
This page contains information about configuring the GitLab for Slack app on GitLab.com. For administrator documentation, see [GitLab for Slack app administration](../../admin_area/settings/slack_app.md).
@ -20,9 +17,10 @@ you run in Slack is run by your linked GitLab user.
## Install the GitLab for Slack app
Prerequisite:
Prerequisites:
- You must have the [appropriate permissions to add apps to your Slack workspace](https://slack.com/help/articles/202035138-Add-apps-to-your-Slack-workspace).
- On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature](../../admin_area/settings/slack_app.md). On GitLab.com, this feature is available.
In GitLab 15.0 and later, the GitLab for Slack app uses
[granular permissions](https://medium.com/slack-developer-blog/more-precision-less-restrictions-a3550006f9c3).
@ -34,7 +32,7 @@ To install the GitLab for Slack app from project integration settings:
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
1. Select **Settings > Integrations**.
1. Select **GitLab for Slack app**. On self-managed GitLab, an administrator must first [enable the integration](../../admin_area/settings/slack_app.md).
1. Select **GitLab for Slack app**.
1. Select **Install GitLab for Slack app**.
1. On the Slack confirmation page, select **Allow**.
@ -109,7 +107,7 @@ By default, slash commands expect a project full path. To create a shorter proje
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**) to find your project.
1. Select **Settings > Integrations**.
1. Select **GitLab for Slack app**. On self-managed GitLab, an administrator must first [enable the integration](../../admin_area/settings/slack_app.md).
1. Select **GitLab for Slack app**.
1. The current **Project Alias**, if any, is displayed. To edit this value,
select **Edit**.
1. Enter your desired alias, and select **Save changes**.

View File

@ -22,7 +22,7 @@ To open the command palette:
1. On the left sidebar, at the top, select **Search GitLab** (**{search}**).
1. Type one of the special characters:
- <kbd>></kbd> - Use to create a new object or to find a menu item.
- <kbd>@</kbd> - Search for user.
- <kbd>:</kbd> - Search for project.
- <kbd>></kbd> - Create a new object or find a menu item.
- <kbd>@</kbd> - Search for a user.
- <kbd>:</kbd> - Search for a project.
- <kbd>/</kbd> - Search for project files in the default repository branch.

View File

@ -185,7 +185,7 @@ module API
# Load agent
agent = ::Clusters::Agent.find(params[:agent_id])
unauthorized!('Feature disabled for agent') unless ::Gitlab::Kas::UserAccess.enabled_for?(agent)
unauthorized!('Feature disabled for agent') unless ::Gitlab::Kas::UserAccess.enabled?
service_response = ::Clusters::Agents::AuthorizeProxyUserService.new(user, agent).execute
render_api_error!(service_response[:message], service_response[:reason]) unless service_response.success?

View File

@ -59,6 +59,8 @@ module API
end
def search(additional_params = {})
return Kaminari.paginate_array([]) if @project.present? && !project_scope_allowed?
search_service = search_service(additional_params)
if search_service.global_search? && !search_service.global_search_enabled_for_scope?
forbidden!('Global Search is disabled for this scope')
@ -95,6 +97,10 @@ module API
)
end
def project_scope_allowed?
::Search::Navigation.new(user: current_user, project: @project).tab_enabled_for_project?(params[:scope].to_sym)
end
def snippets?
%w(snippet_titles).include?(params[:scope]).to_s
end
@ -108,9 +114,7 @@ module API
end
def verify_search_scope!(resource:)
# In EE we have additional validation requirements for searches.
# Defining this method here as a noop allows us to easily extend it in
# EE, without having to modify this file directly.
# no-op
end
def search_type(additional_params = {})

View File

@ -9,11 +9,7 @@ module Gitlab
class UserAccess
class << self
def enabled?
::Gitlab::Kas.enabled? && ::Feature.enabled?(:kas_user_access)
end
def enabled_for?(agent)
enabled? && ::Feature.enabled?(:kas_user_access_project, agent.project)
::Gitlab::Kas.enabled?
end
def encrypt_public_session_id(data)

158
lib/search/navigation.rb Normal file
View File

@ -0,0 +1,158 @@
# frozen_string_literal: true
module Search
class Navigation
include Gitlab::Allowable
def initialize(user:, project: nil, group: nil, options: {})
@user = user
@project = project
@group = group
@options = options
end
def tab_enabled_for_project?(tab)
return false unless project.present?
abilities = Array(search_tab_ability_map[tab])
Array.wrap(project).any? { |p| abilities.any? { |ability| can?(user, ability, p) } }
end
def tabs
{
projects: {
sort: 1,
label: _("Projects"),
data: { qa_selector: 'projects_tab' },
condition: project.nil?
},
blobs: {
sort: 2,
label: _("Code"),
data: { qa_selector: 'code_tab' },
condition: show_code_search_tab?
},
# sort: 3 is reserved for EE items
issues: {
sort: 4,
label: _("Issues"),
condition: show_issues_search_tab?
},
merge_requests: {
sort: 5,
label: _("Merge requests"),
condition: show_merge_requests_search_tab?
},
wiki_blobs: {
sort: 6,
label: _("Wiki"),
condition: show_wiki_search_tab?
},
commits: {
sort: 7,
label: _("Commits"),
condition: show_commits_search_tab?
},
notes: {
sort: 8,
label: _("Comments"),
condition: show_comments_search_tab?
},
milestones: {
sort: 9, label: _("Milestones"),
condition: show_milestones_search_tab?
},
users: {
sort: 10,
label: _("Users"),
condition: show_user_search_tab?
},
snippet_titles: {
sort: 11,
label: _("Snippets"),
search: { snippets: true, group_id: nil, project_id: nil },
condition: show_snippets_search_tab?
}
}
end
private
attr_reader :user, :project, :group, :options
def show_elasticsearch_tabs?
!!options[:show_elasticsearch_tabs]
end
def search_tab_ability_map
{
milestones: :read_milestone,
snippets: :read_snippet,
issues: :read_issue,
blobs: :read_code,
commits: :read_code,
merge_requests: :read_merge_request,
notes: [:read_merge_request, :read_code, :read_issue, :read_snippet],
users: :read_project_member,
wiki_blobs: :read_wiki
}
end
def show_user_search_tab?
return true if tab_enabled_for_project?(:users)
return false unless can?(user, :read_users_list)
project.nil? && feature_flag_tab_enabled?(:global_search_users_tab)
end
def show_code_search_tab?
return true if tab_enabled_for_project?(:blobs)
project.nil? && show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_code_tab)
end
def show_wiki_search_tab?
return true if tab_enabled_for_project?(:wiki_blobs)
project.nil? && show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_wiki_tab)
end
def show_commits_search_tab?
return true if tab_enabled_for_project?(:commits)
project.nil? && show_elasticsearch_tabs? && feature_flag_tab_enabled?(:global_search_commits_tab)
end
def show_issues_search_tab?
return true if tab_enabled_for_project?(:issues)
project.nil? && feature_flag_tab_enabled?(:global_search_issues_tab)
end
def show_merge_requests_search_tab?
return true if tab_enabled_for_project?(:merge_requests)
project.nil? && feature_flag_tab_enabled?(:global_search_merge_requests_tab)
end
def show_comments_search_tab?
return true if tab_enabled_for_project?(:notes)
project.nil? && show_elasticsearch_tabs?
end
def show_snippets_search_tab?
!!options[:show_snippets] && project.nil? && feature_flag_tab_enabled?(:global_search_snippet_titles_tab)
end
def show_milestones_search_tab?
project.nil? || tab_enabled_for_project?(:milestones)
end
def feature_flag_tab_enabled?(flag)
group.present? || Feature.enabled?(flag, user, type: :ops)
end
end
end
Search::Navigation.prepend_mod

View File

@ -59,7 +59,7 @@
"@gitlab/svgs": "3.55.0",
"@gitlab/ui": "64.20.0",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20230620122149",
"@gitlab/web-ide": "0.0.1-dev-20230713160749",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
"@popperjs/core": "^2.11.2",
"@rails/actioncable": "7.0.6",

View File

@ -34,11 +34,13 @@ module RuboCop
class StrongMemoizeAttr < RuboCop::Cop::Base
extend RuboCop::Cop::AutoCorrector
MSG = 'Use `strong_memoize_attr`, instead of using `strong_memoize` directly.'
STRONG_MEMOIZE_MSG = 'Use `strong_memoize_attr`, instead of using `strong_memoize` directly.'
STRONG_MEMOIZE_WITH_MSG =
'Use `strong_memoize_attr`, instead of using `strong_memoize_with` without parameters.'
def_node_matcher :strong_memoize?, <<~PATTERN
(block
$(send nil? :strong_memoize
$(send nil? {:strong_memoize | :strong_memoize_with}
(sym _)
)
(args)
@ -58,7 +60,14 @@ module RuboCop
corrector = autocorrect_pure_definitions(node.parent, body) if node.parent.def_type?
add_offense(send_node, &corrector)
message = case send_node.method_name
when :strong_memoize
STRONG_MEMOIZE_MSG
when :strong_memoize_with
STRONG_MEMOIZE_WITH_MSG
end
add_offense(send_node, message: message, &corrector)
end
private

View File

@ -4,6 +4,8 @@
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'rspec_flaky', path: 'gems/rspec_flaky'
end

View File

@ -42,14 +42,6 @@ RSpec.describe KasCookie, feature_category: :deployment_management do
expect(kas_cookie).to eq('foobar')
expect(::Gitlab::Kas::UserAccess).to have_received(:cookie_data)
end
context 'when feature flag is disabled' do
before do
stub_feature_flags(kas_user_access: false)
end
it { is_expected.to be_blank }
end
end
end
@ -88,60 +80,42 @@ RSpec.describe KasCookie, feature_category: :deployment_management do
request.env['action_dispatch.content_security_policy'].directives['connect-src']
end
context "when feature flag is disabled" do
context 'when KAS is on same domain as rails' do
let_it_be(:kas_tunnel_url) { 'ws://gitlab.example.com/-/k8s-proxy/' }
before do
stub_feature_flags(kas_user_access: false)
end
it 'does not add KAS url to connect-src directives' do
it 'does not add KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).not_to include(::Gitlab::Kas.tunnel_url)
end
end
context 'when feature flag is enabled' do
before do
stub_feature_flags(kas_user_access: true)
context 'when KAS is on subdomain' do
let_it_be(:kas_tunnel_url) { 'ws://kas.gitlab.example.com/k8s-proxy/' }
it 'adds KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).to include(::Gitlab::Kas.tunnel_url)
end
context 'when KAS is on same domain as rails' do
let_it_be(:kas_tunnel_url) { 'ws://gitlab.example.com/-/k8s-proxy/' }
context 'when content_security_policy is disabled' do
let(:content_security_policy_enabled) { false }
it 'does not add KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).not_to include(::Gitlab::Kas.tunnel_url)
end
end
end
context 'when KAS is on subdomain' do
let_it_be(:kas_tunnel_url) { 'ws://kas.gitlab.example.com/k8s-proxy/' }
context 'when KAS tunnel url is configured without trailing slash' do
let_it_be(:kas_tunnel_url) { 'ws://kas.gitlab.example.com/k8s-proxy' }
it 'adds KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).to include(::Gitlab::Kas.tunnel_url)
end
context 'when content_security_policy is disabled' do
let(:content_security_policy_enabled) { false }
it 'does not add KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).not_to include(::Gitlab::Kas.tunnel_url)
end
end
it 'adds KAS url to CSP connect-src directive with trailing slash' do
expect(kas_csp_connect_src).to include("#{::Gitlab::Kas.tunnel_url}/")
end
context 'when KAS tunnel url is configured without trailing slash' do
let_it_be(:kas_tunnel_url) { 'ws://kas.gitlab.example.com/k8s-proxy' }
context 'when content_security_policy is disabled' do
let(:content_security_policy_enabled) { false }
it 'adds KAS url to CSP connect-src directive with trailing slash' do
expect(kas_csp_connect_src).to include("#{::Gitlab::Kas.tunnel_url}/")
end
context 'when content_security_policy is disabled' do
let(:content_security_policy_enabled) { false }
it 'does not add KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).not_to include("#{::Gitlab::Kas.tunnel_url}/")
end
it 'does not add KAS url to CSP connect-src directive' do
expect(kas_csp_connect_src).not_to include("#{::Gitlab::Kas.tunnel_url}/")
end
end
end

View File

@ -383,20 +383,6 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
end
end
context 'when the `slack_app_self_managed` flag is disabled' do
before do
stub_feature_flags(slack_app_self_managed: false)
visit general_admin_application_settings_path
end
it 'does not display any sections' do
expect(page).not_to have_selector('.as-slack')
expect(page).not_to have_content(configure_heading)
expect(page).not_to have_content(create_heading)
expect(page).not_to have_content(update_heading)
end
end
it 'changes the settings' do
page.within('.as-slack') do
check 'Enable GitLab for Slack app'

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe 'Search Snippets', :js, feature_category: :source_code_management do
RSpec.describe 'Search Snippets', :js, feature_category: :global_search do
it 'user searches for snippets by title' do
public_snippet = create(:personal_snippet, :public, title: 'Beginning and Middle')
private_snippet = create(:personal_snippet, :private, title: 'Middle and End')

View File

@ -44,7 +44,6 @@ describe('~/environments/components/form.vue', () => {
const createWrapperWithApollo = ({
propsData = {},
kasUserAccessProject = false,
kubernetesNamespaceForEnvironment = false,
queryResult = null,
} = {}) => {
@ -74,7 +73,6 @@ describe('~/environments/components/form.vue', () => {
provide: {
...PROVIDE,
glFeatures: {
kasUserAccessProject,
kubernetesNamespaceForEnvironment,
},
},
@ -303,15 +301,9 @@ describe('~/environments/components/form.vue', () => {
expect(findNamespaceSelector().exists()).toBe(false);
});
it("doesn't render namespace selector if `kasUserAccessProject` feature flag is disabled", () => {
wrapper = createWrapperWithApollo();
expect(findNamespaceSelector().exists()).toBe(false);
});
describe('when `kasUserAccessProject` and `kubernetesNamespaceForEnvironment` feature flags are enabled', () => {
describe('when `kubernetesNamespaceForEnvironment` feature flag is enabled', () => {
beforeEach(() => {
wrapper = createWrapperWithApollo({
kasUserAccessProject: true,
kubernetesNamespaceForEnvironment: true,
});
});
@ -410,7 +402,6 @@ describe('~/environments/components/form.vue', () => {
beforeEach(async () => {
wrapper = createWrapperWithApollo({
kasUserAccessProject: true,
kubernetesNamespaceForEnvironment: true,
queryResult: jest.fn().mockRejectedValueOnce(error),
});
@ -439,7 +430,6 @@ describe('~/environments/components/form.vue', () => {
beforeEach(() => {
wrapper = createWrapperWithApollo({
propsData: { environment: environmentWithAgent },
kasUserAccessProject: true,
kubernetesNamespaceForEnvironment: true,
});
});
@ -473,7 +463,6 @@ describe('~/environments/components/form.vue', () => {
beforeEach(() => {
wrapper = createWrapperWithApollo({
propsData: { environment: environmentWithAgentAndNamespace },
kasUserAccessProject: true,
kubernetesNamespaceForEnvironment: true,
});
});

View File

@ -537,11 +537,6 @@ describe('~/environments/components/new_environment_item.vue', () => {
it('should request agent data when the environment is visible if the feature flag is enabled', async () => {
wrapper = createWrapper({
propsData: { environment: resolvedEnvironment },
provideData: {
glFeatures: {
kasUserAccessProject: true,
},
},
apolloProvider: createApolloProvider(agent),
});
@ -553,12 +548,11 @@ describe('~/environments/components/new_environment_item.vue', () => {
});
});
it('should request agent data with kubernetes namespace when `kasUserAccessProject` and `kubernetesNamespaceForEnvironment` feature flags are enabled', async () => {
it('should request agent data with kubernetes namespace when `kubernetesNamespaceForEnvironment` feature flag is enabled', async () => {
wrapper = createWrapper({
propsData: { environment: resolvedEnvironment },
provideData: {
glFeatures: {
kasUserAccessProject: true,
kubernetesNamespaceForEnvironment: true,
},
},
@ -573,14 +567,9 @@ describe('~/environments/components/new_environment_item.vue', () => {
});
});
it('should render if the feature flag is enabled and the environment has an agent associated', async () => {
it('should render if the environment has an agent associated', async () => {
wrapper = createWrapper({
propsData: { environment: resolvedEnvironment },
provideData: {
glFeatures: {
kasUserAccessProject: true,
},
},
apolloProvider: createApolloProvider(agent),
});
@ -592,12 +581,11 @@ describe('~/environments/components/new_environment_item.vue', () => {
});
});
it('should render with the namespace if `kasUserAccessProject` and `kubernetesNamespaceForEnvironment` feature flags are enabled and the environment has an agent associated', async () => {
it('should render with the namespace if `kubernetesNamespaceForEnvironment` feature flag is enabled and the environment has an agent associated', async () => {
wrapper = createWrapper({
propsData: { environment: resolvedEnvironment },
provideData: {
glFeatures: {
kasUserAccessProject: true,
kubernetesNamespaceForEnvironment: true,
},
},
@ -613,26 +601,9 @@ describe('~/environments/components/new_environment_item.vue', () => {
});
});
it('should not render if the feature flag is not enabled', async () => {
wrapper = createWrapper({
propsData: { environment: resolvedEnvironment },
apolloProvider: createApolloProvider(agent),
});
await expandCollapsedSection();
expect(queryResponseHandler).not.toHaveBeenCalled();
expect(findKubernetesOverview().exists()).toBe(false);
});
it('should not render if the environment has no agent object', async () => {
wrapper = createWrapper({
propsData: { environment: resolvedEnvironment },
provideData: {
glFeatures: {
kasUserAccessProject: true,
},
},
apolloProvider: createApolloProvider(),
});

View File

@ -219,7 +219,11 @@ describe('PackagesListApp', () => {
await waitForPromises();
expect(resolver).toHaveBeenCalledWith(
expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
expect.objectContaining({
first: null,
before: pagination().startCursor,
last: GRAPHQL_PAGE_SIZE,
}),
);
});
});

View File

@ -11,7 +11,7 @@ import BlobContent from '~/blob/components/blob_content.vue';
import BlobHeader from '~/blob/components/blob_header.vue';
import BlobButtonGroup from '~/repository/components/blob_button_group.vue';
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
import WebIdeLink from 'ee_else_ce/vue_shared/components/web_ide_link.vue';
import ForkSuggestion from '~/repository/components/fork_suggestion.vue';
import { loadViewer } from '~/repository/components/blob_viewers';
import DownloadViewer from '~/repository/components/blob_viewers/download_viewer.vue';

View File

@ -31,12 +31,13 @@ const TEST_ACTION_2 = {
describe('vue_shared/components/actions_button', () => {
let wrapper;
function createComponent(props) {
function createComponent({ props = {}, slots = {} } = {}) {
wrapper = shallowMountExtended(ActionsButton, {
propsData: { actions: [TEST_ACTION, TEST_ACTION_2], toggleText: 'Edit', ...props },
stubs: {
GlDisclosureDropdownItem,
},
slots,
});
}
const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
@ -47,11 +48,29 @@ describe('vue_shared/components/actions_button', () => {
expect(findDropdown().props().toggleText).toBe('Edit');
});
it('dropdown has a fluid width', () => {
createComponent();
expect(findDropdown().props().fluidWidth).toBe(true);
});
it('provides a default slot', () => {
const slotContent = 'default text';
createComponent({
slots: {
default: slotContent,
},
});
expect(findDropdown().text()).toContain(slotContent);
});
it('allows customizing variant and category', () => {
const variant = 'confirm';
const category = 'secondary';
createComponent({ variant, category });
createComponent({ props: { variant, category } });
expect(findDropdown().props()).toMatchObject({ category, variant });
});
@ -88,4 +107,13 @@ describe('vue_shared/components/actions_button', () => {
});
});
});
it.each(['shown', 'hidden'])(
'bubbles up %s event from the disclosure dropdown component',
(event) => {
createComponent();
findDropdown().vm.$emit(event);
expect(wrapper.emitted(event)).toHaveLength(1);
},
);
});

View File

@ -85,7 +85,7 @@ describe('vue_shared/components/web_ide_link', () => {
let wrapper;
function createComponent(props, { mountFn = shallowMountExtended, glFeatures = {} } = {}) {
function createComponent(props, { mountFn = shallowMountExtended, slots = {} } = {}) {
const fakeApollo = createMockApollo([
[getWritableForksQuery, jest.fn().mockResolvedValue(getWritableForksResponse)],
]);
@ -98,9 +98,7 @@ describe('vue_shared/components/web_ide_link', () => {
forkPath,
...props,
},
provide: {
glFeatures,
},
slots,
stubs: {
GlModal: stubComponent(GlModal, {
template: `
@ -215,6 +213,27 @@ describe('vue_shared/components/web_ide_link', () => {
expect(findActionsButton().props('actions')).toEqual(expectedActions);
});
it('bubbles up shown and hidden events triggered by actions button component', () => {
createComponent();
expect(wrapper.emitted('shown')).toBe(undefined);
expect(wrapper.emitted('hidden')).toBe(undefined);
findActionsButton().vm.$emit('shown');
findActionsButton().vm.$emit('hidden');
expect(wrapper.emitted('shown')).toHaveLength(1);
expect(wrapper.emitted('hidden')).toHaveLength(1);
});
it('exposes a default slot', () => {
const slotContent = 'default slot content';
createComponent({}, { slots: { default: slotContent } });
expect(wrapper.text()).toContain(slotContent);
});
describe('when pipeline editor action is available', () => {
beforeEach(() => {
createComponent({

View File

@ -722,78 +722,6 @@ RSpec.describe SearchHelper, feature_category: :global_search do
end
end
describe '#show_user_search_tab?' do
subject { show_user_search_tab? }
let(:current_user) { build(:user) }
before do
allow(self).to receive(:current_user).and_return(current_user)
end
context 'when project search' do
before do
@project = :some_project
expect(self).to receive(:project_search_tabs?)
.with(:users)
.and_return(:value)
end
it 'delegates to project_search_tabs?' do
expect(subject).to eq(:value)
end
end
context 'when group search' do
before do
@group = :some_group
end
context 'when current_user can read_users_list' do
before do
allow(self).to receive(:can?).with(current_user, :read_users_list).and_return(true)
end
it { is_expected.to eq(true) }
end
context 'when current_user cannot read_users_list' do
before do
allow(self).to receive(:can?).with(current_user, :read_users_list).and_return(false)
end
it { is_expected.to eq(false) }
end
end
context 'when global search' do
context 'when current_user can read_users_list' do
before do
allow(self).to receive(:can?).with(current_user, :read_users_list).and_return(true)
end
it { is_expected.to eq(true) }
context 'when global_search_user_tab feature flag is disabled' do
before do
stub_feature_flags(global_search_users_tab: false)
end
it { is_expected.to eq(false) }
end
end
context 'when current_user cannot read_users_list' do
before do
allow(self).to receive(:can?).with(current_user, :read_users_list).and_return(false)
end
it { is_expected.to eq(false) }
end
end
end
describe '#repository_ref' do
using RSpec::Parameterized::TableSyntax
@ -1113,248 +1041,24 @@ RSpec.describe SearchHelper, feature_category: :global_search do
end
end
describe '.search_navigation' do
using RSpec::Parameterized::TableSyntax
let(:user) { build(:user) }
let_it_be(:project) { build(:project) }
before do
allow(self).to receive(:current_user).and_return(user)
allow(self).to receive(:can?).and_return(true)
allow(self).to receive(:project_search_tabs?).and_return(false)
allow(self).to receive(:feature_flag_tab_enabled?).and_return(false)
end
context 'projects' do
where(:global_project, :condition) do
nil | true
ref(:project) | false
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
expect(search_navigation[:projects][:condition]).to eq(condition)
end
end
end
context 'code' do
where(:feature_flag_tab_enabled, :show_elasticsearch_tabs, :global_project, :project_search_tabs, :condition) do
false | false | nil | false | false
true | true | nil | true | true
true | false | nil | false | false
false | true | nil | false | false
false | false | ref(:project) | true | true
true | false | ref(:project) | false | false
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_code_tab).and_return(feature_flag_tab_enabled)
allow(self).to receive(:project_search_tabs?).with(:blobs).and_return(project_search_tabs)
expect(search_navigation[:blobs][:condition]).to eq(condition)
end
end
end
context 'issues' do
where(:project_search_tabs, :global_search_issues_tab, :global_project, :condition) do
false | false | nil | false
false | true | nil | true
false | true | ref(:project) | false
false | false | ref(:project) | false
true | false | nil | true
true | true | nil | true
true | false | ref(:project) | true
true | true | ref(:project) | true
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_issues_tab).and_return(global_search_issues_tab)
allow(self).to receive(:project_search_tabs?).with(:issues).and_return(project_search_tabs)
expect(search_navigation[:issues][:condition]).to eq(condition)
end
end
end
context 'merge requests' do
where(:project_search_tabs, :feature_flag_tab_enabled, :global_project, :condition) do
false | false | nil | false
true | false | nil | true
false | false | ref(:project) | false
true | false | ref(:project) | true
false | true | nil | true
true | true | nil | true
false | true | ref(:project) | false
true | true | ref(:project) | true
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_merge_requests_tab).and_return(feature_flag_tab_enabled)
allow(self).to receive(:project_search_tabs?).with(:merge_requests).and_return(project_search_tabs)
expect(search_navigation[:merge_requests][:condition]).to eq(condition)
end
end
end
context 'wiki' do
where(:global_search_wiki_tab, :show_elasticsearch_tabs, :global_project, :project_search_tabs, :condition) do
false | false | nil | true | true
false | false | nil | false | false
false | false | ref(:project) | false | false
false | true | nil | false | false
false | true | ref(:project) | false | false
true | false | nil | false | false
true | true | ref(:project) | false | false
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_wiki_tab).and_return(global_search_wiki_tab)
allow(self).to receive(:project_search_tabs?).with(:wiki_blobs).and_return(project_search_tabs)
expect(search_navigation[:wiki_blobs][:condition]).to eq(condition)
end
end
end
context 'commits' do
where(:global_search_commits_tab, :show_elasticsearch_tabs, :global_project, :project_search_tabs, :condition) do
false | false | nil | true | true
false | false | ref(:project) | true | true
false | false | nil | false | false
false | true | ref(:project) | false | false
false | true | nil | false | false
true | false | nil | false | false
true | false | ref(:project) | false | false
true | true | ref(:project) | false | false
true | true | nil | false | true
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_commits_tab).and_return(global_search_commits_tab)
allow(self).to receive(:project_search_tabs?).with(:commits).and_return(project_search_tabs)
expect(search_navigation[:commits][:condition]).to eq(condition)
end
end
end
context 'comments' do
where(:project_search_tabs, :show_elasticsearch_tabs, :global_project, :condition) do
true | true | nil | true
true | true | ref(:project) | true
false | false | nil | false
false | false | ref(:project) | false
false | true | nil | true
false | true | ref(:project) | false
true | false | nil | true
true | false | ref(:project) | true
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(show_elasticsearch_tabs)
allow(self).to receive(:project_search_tabs?).with(:notes).and_return(project_search_tabs)
expect(search_navigation[:notes][:condition]).to eq(condition)
end
end
end
context 'milestones' do
where(:global_project, :project_search_tabs, :condition) do
ref(:project) | true | true
nil | false | true
ref(:project) | false | false
nil | true | true
end
with_them do
it 'data item condition is set correctly' do
@project = global_project
allow(self).to receive(:project_search_tabs?).with(:milestones).and_return(project_search_tabs)
expect(search_navigation[:milestones][:condition]).to eq(condition)
end
end
end
context 'users' do
where(:show_user_search_tab, :condition) do
true | true
false | false
end
with_them do
it 'data item condition is set correctly' do
allow(self).to receive(:show_user_search_tab?).and_return(show_user_search_tab)
expect(search_navigation[:users][:condition]).to eq(condition)
end
end
end
context 'snippet_titles' do
where(:global_project, :global_show_snippets, :global_feature_flag_enabled, :condition) do
ref(:project) | true | false | false
nil | false | false | false
ref(:project) | false | false | false
nil | true | false | false
ref(:project) | true | true | false
nil | false | true | false
ref(:project) | false | true | false
nil | true | true | true
end
with_them do
it 'data item condition is set correctly' do
allow(search_service).to receive(:show_snippets?).and_return(global_show_snippets)
allow(self).to receive(:feature_flag_tab_enabled?).with(:global_search_snippet_titles_tab)
.and_return(global_feature_flag_enabled)
@project = global_project
expect(search_navigation[:snippet_titles][:condition]).to eq(condition)
end
end
end
end
describe '.search_navigation_json' do
using RSpec::Parameterized::TableSyntax
context 'with data' do
context 'with some tab conditions set to false' do
example_data_1 = {
projects: { label: _("Projects"), condition: true },
blobs: { label: _("Code"), condition: false }
blobs: { label: _("Code"), condition: false }
}
example_data_2 = {
projects: { label: _("Projects"), condition: false },
blobs: { label: _("Code"), condition: false }
blobs: { label: _("Code"), condition: false }
}
example_data_3 = {
projects: { label: _("Projects"), condition: true },
blobs: { label: _("Code"), condition: true },
epics: { label: _("Epics"), condition: true }
blobs: { label: _("Code"), condition: true },
epics: { label: _("Epics"), condition: true }
}
where(:data, :matcher) do
@ -1365,28 +1069,31 @@ RSpec.describe SearchHelper, feature_category: :global_search do
with_them do
it 'renders data correctly' do
allow(self).to receive(:search_navigation).with(no_args).and_return(data)
allow(self).to receive(:current_user).and_return(build(:user))
allow_next_instance_of(Search::Navigation) do |search_nav|
allow(search_nav).to receive(:tabs).and_return(data)
end
expect(search_navigation_json).to instance_exec(&matcher)
end
end
end
end
describe '.search_navigation_json with .search_navigation' do
before do
allow(self).to receive(:current_user).and_return(build(:user))
allow(self).to receive(:can?).and_return(true)
allow(self).to receive(:project_search_tabs?).and_return(true)
allow(self).to receive(:feature_flag_tab_enabled?).and_return(true)
allow(self).to receive(:feature_flag_tab_enabled?).and_return(true)
allow(search_service).to receive(:show_elasticsearch_tabs?).and_return(true)
allow(search_service).to receive(:show_snippets?).and_return(true)
@project = nil
end
context 'when all options enabled' do
before do
allow(self).to receive(:current_user).and_return(build(:user))
allow(search_service).to receive(:show_snippets?).and_return(true)
allow_next_instance_of(Search::Navigation) do |search_nav|
allow(search_nav).to receive(:tab_enabled_for_project?).and_return(true)
allow(search_nav).to receive(:feature_flag_tab_enabled?).and_return(true)
end
it 'test search navigation item order for CE all options enabled' do
expect(Gitlab::Json.parse(search_navigation_json).keys).to eq(%w[projects blobs issues merge_requests wiki_blobs commits notes milestones users snippet_titles])
@project = nil
end
it 'returns items in order' do
expect(Gitlab::Json.parse(search_navigation_json).keys).to eq(%w[projects blobs issues merge_requests wiki_blobs commits notes milestones users snippet_titles])
end
end
end
@ -1431,30 +1138,6 @@ RSpec.describe SearchHelper, feature_category: :global_search do
end
end
describe 'show_elasticsearch_tabs' do
subject { search_service.show_elasticsearch_tabs? }
let(:user) { build(:user) }
before do
allow(self).to receive(:current_user).and_return(user)
end
it { is_expected.to eq(false) }
end
describe 'show_epics' do
subject { search_service.show_epics? }
let(:user) { build(:user) }
before do
allow(self).to receive(:current_user).and_return(user)
end
it { is_expected.to eq(false) }
end
describe '#wiki_blob_link' do
let_it_be(:project) { create :project, :wiki_repo }
let(:wiki_blob) do

View File

@ -11,42 +11,6 @@ RSpec.describe Gitlab::Kas::UserAccess, feature_category: :deployment_management
end
it { is_expected.to be true }
context 'when flag kas_user_access is disabled' do
before do
stub_feature_flags(kas_user_access: false)
end
it { is_expected.to be false }
end
end
describe '.enabled_for?' do
subject { described_class.enabled_for?(agent) }
let(:agent) { build(:cluster_agent) }
before do
allow(::Gitlab::Kas).to receive(:enabled?).and_return true
end
it { is_expected.to be true }
context 'when flag kas_user_access is disabled' do
before do
stub_feature_flags(kas_user_access: false)
end
it { is_expected.to be false }
end
context 'when flag kas_user_access_project is disabled' do
before do
stub_feature_flags(kas_user_access_project: false)
end
it { is_expected.to be false }
end
end
describe '.{encrypt,decrypt}_public_session_id' do

View File

@ -0,0 +1,280 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Search::Navigation, feature_category: :global_search do
let(:user) { instance_double(User) }
let(:project_double) { instance_double(Project) }
let(:options) { {} }
let(:search_navigation) { described_class.new(user: user, project: project, options: options) }
describe '#tab_enabled_for_project?' do
let(:project) { project_double }
let(:tab) { :blobs }
subject(:tab_enabled_for_project) { search_navigation.tab_enabled_for_project?(tab) }
context 'when user has ability for tab' do
before do
allow(search_navigation).to receive(:can?).with(user, :read_code, project_double).and_return(true)
end
it { is_expected.to eq(true) }
end
context 'when user does not have ability for tab' do
before do
allow(search_navigation).to receive(:can?).with(user, :read_code, project_double).and_return(false)
end
it { is_expected.to eq(false) }
end
context 'when an array of projects is provided' do
let(:project) { Array.wrap(project_double) }
before do
allow(search_navigation).to receive(:can?).with(user, :read_code, project_double).and_return(true)
end
it { is_expected.to eq(true) }
end
context 'when project is not present' do
let_it_be(:project) { nil }
it { is_expected.to eq(false) }
end
end
describe '#tabs' do
using RSpec::Parameterized::TableSyntax
before do
allow(search_navigation).to receive(:can?).and_return(true)
allow(search_navigation).to receive(:tab_enabled_for_project?).and_return(false)
allow(search_navigation).to receive(:feature_flag_tab_enabled?).and_return(false)
end
subject(:tabs) { search_navigation.tabs }
context 'for projects tab' do
where(:project, :condition) do
nil | true
ref(:project_double) | false
end
with_them do
it 'data item condition is set correctly' do
expect(tabs[:projects][:condition]).to eq(condition)
end
end
end
context 'for code tab' do
where(:feature_flag_enabled, :show_elasticsearch_tabs, :project, :tab_enabled, :condition) do
false | false | nil | false | false
true | true | nil | true | true
true | false | nil | false | false
false | true | nil | false | false
false | false | ref(:project_double) | true | true
true | false | ref(:project_double) | false | false
end
with_them do
let(:options) { { show_elasticsearch_tabs: show_elasticsearch_tabs } }
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_code_tab).and_return(feature_flag_enabled)
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:blobs).and_return(tab_enabled)
expect(tabs[:blobs][:condition]).to eq(condition)
end
end
end
context 'for issues tab' do
where(:tab_enabled, :feature_flag_enabled, :project, :condition) do
false | false | nil | false
false | true | nil | true
false | true | ref(:project_double) | false
false | false | ref(:project_double) | false
true | false | nil | true
true | true | nil | true
true | false | ref(:project_double) | true
true | true | ref(:project_double) | true
end
with_them do
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_issues_tab).and_return(feature_flag_enabled)
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:issues).and_return(tab_enabled)
expect(tabs[:issues][:condition]).to eq(condition)
end
end
end
context 'for merge requests tab' do
where(:tab_enabled, :feature_flag_enabled, :project, :condition) do
false | false | nil | false
true | false | nil | true
false | false | ref(:project_double) | false
true | false | ref(:project_double) | true
false | true | nil | true
true | true | nil | true
false | true | ref(:project_double) | false
true | true | ref(:project_double) | true
end
with_them do
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_merge_requests_tab).and_return(feature_flag_enabled)
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:merge_requests).and_return(tab_enabled)
expect(tabs[:merge_requests][:condition]).to eq(condition)
end
end
end
context 'for wiki tab' do
where(:feature_flag_enabled, :show_elasticsearch_tabs, :project, :tab_enabled, :condition) do
false | false | nil | true | true
false | false | nil | false | false
false | false | ref(:project_double) | false | false
false | true | nil | false | false
false | true | ref(:project_double) | false | false
true | false | nil | false | false
true | true | ref(:project_double) | false | false
end
with_them do
let(:options) { { show_elasticsearch_tabs: show_elasticsearch_tabs } }
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_wiki_tab).and_return(feature_flag_enabled)
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:wiki_blobs).and_return(tab_enabled)
expect(tabs[:wiki_blobs][:condition]).to eq(condition)
end
end
end
context 'for commits tab' do
where(:feature_flag_enabled, :show_elasticsearch_tabs, :project, :tab_enabled, :condition) do
false | false | nil | true | true
false | false | ref(:project_double) | true | true
false | false | nil | false | false
false | true | ref(:project_double) | false | false
false | true | nil | false | false
true | false | nil | false | false
true | false | ref(:project_double) | false | false
true | true | ref(:project_double) | false | false
true | true | nil | false | true
end
with_them do
let(:options) { { show_elasticsearch_tabs: show_elasticsearch_tabs } }
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_commits_tab).and_return(feature_flag_enabled)
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:commits).and_return(tab_enabled)
expect(tabs[:commits][:condition]).to eq(condition)
end
end
end
context 'for comments tab' do
where(:tab_enabled, :show_elasticsearch_tabs, :project, :condition) do
true | true | nil | true
true | true | ref(:project_double) | true
false | false | nil | false
false | false | ref(:project_double) | false
false | true | nil | true
false | true | ref(:project_double) | false
true | false | nil | true
true | false | ref(:project_double) | true
end
with_them do
let(:options) { { show_elasticsearch_tabs: show_elasticsearch_tabs } }
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:notes).and_return(tab_enabled)
expect(tabs[:notes][:condition]).to eq(condition)
end
end
end
context 'for milestones tab' do
where(:project, :tab_enabled, :condition) do
ref(:project_double) | true | true
nil | false | true
ref(:project_double) | false | false
nil | true | true
end
with_them do
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:milestones).and_return(tab_enabled)
expect(tabs[:milestones][:condition]).to eq(condition)
end
end
end
context 'for users tab' do
where(:feature_flag_enabled, :can_read_users_list, :project, :tab_enabled, :condition) do
false | false | ref(:project_double) | true | true
false | false | nil | false | false
false | true | nil | false | false
false | true | ref(:project_double) | false | false
true | true | nil | false | true
true | true | ref(:project_double) | false | false
end
with_them do
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:tab_enabled_for_project?).with(:users).and_return(tab_enabled)
allow(search_navigation).to receive(:can?)
.with(user, :read_users_list, project_double).and_return(can_read_users_list)
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_users_tab).and_return(feature_flag_enabled)
expect(tabs[:users][:condition]).to eq(condition)
end
end
end
context 'for snippet_titles tab' do
where(:project, :show_snippets, :feature_flag_enabled, :condition) do
ref(:project_double) | true | false | false
nil | false | false | false
ref(:project_double) | false | false | false
nil | true | false | false
ref(:project_double) | true | true | false
nil | false | true | false
ref(:project_double) | false | true | false
nil | true | true | true
end
with_them do
let(:options) { { show_snippets: show_snippets } }
it 'data item condition is set correctly' do
allow(search_navigation).to receive(:feature_flag_tab_enabled?)
.with(:global_search_snippet_titles_tab).and_return(feature_flag_enabled)
expect(tabs[:snippet_titles][:condition]).to eq(condition)
end
end
end
end
end

View File

@ -198,14 +198,6 @@ RSpec.describe Clusters::Agent, feature_category: :deployment_management do
it { is_expected.to eq(allowed) }
end
context 'when expose_authorized_cluster_agents feature flag is disabled' do
before do
stub_feature_flags(expose_authorized_cluster_agents: false)
end
it { is_expected.to eq(false) }
end
end
context 'with group-level authorization' do
@ -226,14 +218,6 @@ RSpec.describe Clusters::Agent, feature_category: :deployment_management do
it { is_expected.to eq(allowed) }
end
context 'when expose_authorized_cluster_agents feature flag is disabled' do
before do
stub_feature_flags(expose_authorized_cluster_agents: false)
end
it { is_expected.to eq(false) }
end
end
end
@ -269,14 +253,6 @@ RSpec.describe Clusters::Agent, feature_category: :deployment_management do
it { is_expected.to eq(allowed) }
end
context 'when expose_authorized_cluster_agents feature flag is disabled' do
before do
stub_feature_flags(expose_authorized_cluster_agents: false)
end
it { is_expected.to eq(false) }
end
end
context 'with group-level authorization' do
@ -297,14 +273,6 @@ RSpec.describe Clusters::Agent, feature_category: :deployment_management do
it { is_expected.to eq(allowed) }
end
context 'when expose_authorized_cluster_agents feature flag is disabled' do
before do
stub_feature_flags(expose_authorized_cluster_agents: false)
end
it { is_expected.to eq(false) }
end
end
end

View File

@ -547,18 +547,6 @@ RSpec.describe API::Internal::Kubernetes, feature_category: :deployment_manageme
expect(response).to have_gitlab_http_status(:forbidden)
end
it 'returns 401 when global flag is disabled' do
stub_feature_flags(kas_user_access: false)
deployment_project.add_member(user, :developer)
token = new_token
public_id = stub_user_session(user, token)
access_key = Gitlab::Kas::UserAccess.encrypt_public_session_id(public_id)
send_request(params: { agent_id: agent.id, access_type: 'session_cookie', access_key: access_key, csrf_token: mask_token(token) })
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'returns 401 when user id is not found in session' do
deployment_project.add_member(user, :developer)
token = new_token

View File

@ -688,6 +688,16 @@ RSpec.describe API::Search, :clean_gitlab_redis_rate_limiting, feature_category:
end
end
context 'when user does not have permissions for scope' do
it 'returns an empty array' do
project.project_feature.update!(issues_access_level: Gitlab::VisibilityLevel::PRIVATE)
get api(endpoint, user), params: { scope: 'issues', search: 'awesome' }
expect(json_response).to be_empty
end
end
context 'when project does not exist' do
it 'returns 404 error' do
get api('/projects/0/search', user), params: { scope: 'issues', search: 'awesome' }

View File

@ -100,4 +100,42 @@ RSpec.describe RuboCop::Cop::Gitlab::StrongMemoizeAttr do
RUBY
end
end
context 'when strong_memoize_with() is called without parameters' do
it 'registers an offense and autocorrects' do
expect_offense(<<~RUBY)
class Foo
def memoized_method
strong_memoize_with(:memoized_method) do
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `strong_memoize_attr`, instead of using `strong_memoize_with` without parameters.
'This is a memoized method'
end
end
end
RUBY
expect_correction(<<~RUBY)
class Foo
def memoized_method
'This is a memoized method'
end
strong_memoize_attr :memoized_method
end
RUBY
end
end
context 'when strong_memoize_with() is called with parameters' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY)
class Foo
def memoized_method(param)
strong_memoize_with(:memoized_method, param) do
param.to_s
end
end
end
RUBY
end
end
end

View File

@ -1151,10 +1151,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.7.3.tgz#9ea641146436da388ffbad25d7f2abe0df52c235"
integrity sha512-NMV++7Ew1FSBDN1xiZaauU9tfeSfgDHcOLpn+8bGpP+O5orUPm2Eu66R5eC5gkjBPaXosNAxNWtriee+aFk4+g==
"@gitlab/web-ide@0.0.1-dev-20230620122149":
version "0.0.1-dev-20230620122149"
resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20230620122149.tgz#2e5c2c41a3df91227440c1a319001bd59eac8aac"
integrity sha512-uJFT0aUiOvPynN8/zp0VB2CVxiiKmzzTiZIJseKY8V1b2kKvW554lRVbNwES34Fo/ZXoCU65ZCmIitbbPgsZYQ==
"@gitlab/web-ide@0.0.1-dev-20230713160749":
version "0.0.1-dev-20230713160749"
resolved "https://registry.yarnpkg.com/@gitlab/web-ide/-/web-ide-0.0.1-dev-20230713160749.tgz#427aed5e9fa6be1d1f58dde282500759df204b6c"
integrity sha512-QySxWa5dzuZw1XGtkFDuTX9CF/kvBMGoiM9PySH2cvx6mGvC9dphis06eeliNKkNZG3arjwNSC6/8JRkg96B5A==
"@graphql-eslint/eslint-plugin@3.20.0":
version "3.20.0"