Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
cba5b2d7ea
commit
41c37d81e7
|
|
@ -48,6 +48,7 @@ db:rollback single-db:
|
|||
# https://docs.gitlab.com/ee/development/database/dbmigrate_multi_version_upgrade_job.html
|
||||
db:migrate:multi-version-upgrade:
|
||||
extends:
|
||||
- .single-db
|
||||
- .db-job-base
|
||||
- .rails:rules:db:migrate:multi-version-upgrade
|
||||
script:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
a70abfad8ef4d4d1cb4b5d6667b8df8ccd772f3d
|
||||
a2ca345cd681ef39094623d8f4b6ed65996de57d
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {
|
|||
GlFormCombobox,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlFormSelect,
|
||||
GlCollapsibleListbox,
|
||||
GlFormTextarea,
|
||||
GlIcon,
|
||||
GlLink,
|
||||
|
|
@ -120,7 +120,7 @@ export default {
|
|||
GlFormCombobox,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlFormSelect,
|
||||
GlCollapsibleListbox,
|
||||
GlFormTextarea,
|
||||
GlIcon,
|
||||
GlLink,
|
||||
|
|
@ -467,10 +467,11 @@ export default {
|
|||
'-gl-mb-1': hideEnvironmentScope,
|
||||
}"
|
||||
>
|
||||
<gl-form-select
|
||||
id="ci-variable-type"
|
||||
<gl-collapsible-listbox
|
||||
v-model="variable.variableType"
|
||||
:options="$options.variableOptions"
|
||||
:items="$options.variableOptions"
|
||||
block
|
||||
fluid-width
|
||||
/>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
OPERATOR_OR,
|
||||
OPERATOR_AFTER,
|
||||
OPERATOR_BEFORE,
|
||||
TOKEN_TYPE_APPROVED_BY,
|
||||
TOKEN_TYPE_ASSIGNEE,
|
||||
TOKEN_TYPE_REVIEWER,
|
||||
TOKEN_TYPE_AUTHOR,
|
||||
|
|
@ -149,6 +150,19 @@ export const filtersMap = {
|
|||
},
|
||||
},
|
||||
},
|
||||
[TOKEN_TYPE_APPROVED_BY]: {
|
||||
[API_PARAM]: {
|
||||
[NORMAL_FILTER]: 'approvedBy',
|
||||
},
|
||||
[URL_PARAM]: {
|
||||
[OPERATOR_IS]: {
|
||||
[NORMAL_FILTER]: 'approved_by_usernames[]',
|
||||
},
|
||||
[OPERATOR_NOT]: {
|
||||
[NORMAL_FILTER]: 'not[approved_by_usernames][]',
|
||||
},
|
||||
},
|
||||
},
|
||||
[TOKEN_TYPE_AUTHOR]: {
|
||||
[API_PARAM]: {
|
||||
[NORMAL_FILTER]: 'authorUsername',
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import { DEFAULT_PAGE_SIZE, mergeRequestListTabs } from '~/vue_shared/issuable/l
|
|||
import {
|
||||
OPERATORS_IS,
|
||||
OPERATORS_IS_NOT,
|
||||
TOKEN_TITLE_APPROVED_BY,
|
||||
TOKEN_TYPE_APPROVED_BY,
|
||||
TOKEN_TITLE_AUTHOR,
|
||||
TOKEN_TYPE_AUTHOR,
|
||||
TOKEN_TITLE_DRAFT,
|
||||
|
|
@ -192,6 +194,19 @@ export default {
|
|||
searchTokens() {
|
||||
const preloadedUsers = [];
|
||||
const tokens = [
|
||||
{
|
||||
type: TOKEN_TYPE_APPROVED_BY,
|
||||
title: TOKEN_TITLE_APPROVED_BY,
|
||||
icon: 'approval',
|
||||
token: UserToken,
|
||||
dataType: 'user',
|
||||
operators: OPERATORS_IS_NOT,
|
||||
fullPath: this.fullPath,
|
||||
isProject: true,
|
||||
recentSuggestionsStorageKey: `${this.fullPath}-merge_requests-recent-tokens-approved_by`,
|
||||
preloadedUsers,
|
||||
multiSelect: false,
|
||||
},
|
||||
{
|
||||
type: TOKEN_TYPE_ASSIGNEE,
|
||||
title: TOKEN_TITLE_ASSIGNEE,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ query getMergeRequests(
|
|||
$fullPath: ID!
|
||||
$sort: MergeRequestSort
|
||||
$state: MergeRequestState
|
||||
$approvedBy: [String!]
|
||||
$assigneeUsernames: String
|
||||
$assigneeWildcardId: AssigneeWildcardId
|
||||
$reviewerUsername: String
|
||||
|
|
@ -31,6 +32,7 @@ query getMergeRequests(
|
|||
mergeRequests(
|
||||
sort: $sort
|
||||
state: $state
|
||||
approvedBy: $approvedBy
|
||||
assigneeUsername: $assigneeUsernames
|
||||
assigneeWildcardId: $assigneeWildcardId
|
||||
reviewerUsername: $reviewerUsername
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
|
||||
import { queryToObject } from '~/lib/utils/url_utility';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import syntaxHighlight from '~/syntax_highlight';
|
||||
import { initSidebar } from './sidebar';
|
||||
import { initSearchSort } from './sort';
|
||||
|
|
@ -13,8 +14,16 @@ const sidebarInitState = () => {
|
|||
const el = document.getElementById('js-search-sidebar');
|
||||
if (!el) return {};
|
||||
|
||||
const { navigationJson, searchType, searchLevel, groupInitialJson, projectInitialJson, ref } =
|
||||
el.dataset;
|
||||
const {
|
||||
navigationJson,
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable,
|
||||
zoektAvailable,
|
||||
groupInitialJson,
|
||||
projectInitialJson,
|
||||
ref,
|
||||
} = el.dataset;
|
||||
|
||||
const navigationJsonParsed = JSON.parse(navigationJson);
|
||||
const groupInitialJsonParsed = JSON.parse(groupInitialJson);
|
||||
|
|
@ -24,6 +33,8 @@ const sidebarInitState = () => {
|
|||
navigationJsonParsed,
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable: parseBoolean(advancedSearchAvailable),
|
||||
zoektAvailable: parseBoolean(zoektAvailable),
|
||||
groupInitialJsonParsed,
|
||||
projectInitialJsonParsed,
|
||||
ref,
|
||||
|
|
@ -48,6 +59,8 @@ export const initSearchApp = () => {
|
|||
navigationJsonParsed: navigation,
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable,
|
||||
zoektAvailable,
|
||||
groupInitialJsonParsed: groupInitialJson,
|
||||
projectInitialJsonParsed: projectInitialJson,
|
||||
ref,
|
||||
|
|
@ -60,6 +73,8 @@ export const initSearchApp = () => {
|
|||
navigation,
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable,
|
||||
zoektAvailable,
|
||||
groupInitialJson,
|
||||
projectInitialJson,
|
||||
defaultBranchName,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ const createState = ({
|
|||
navigation,
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable,
|
||||
zoektAvailable,
|
||||
groupInitialJson,
|
||||
projectInitialJson,
|
||||
defaultBranchName,
|
||||
|
|
@ -31,6 +33,8 @@ const createState = ({
|
|||
searchLabelString: '',
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable,
|
||||
zoektAvailable,
|
||||
groupInitialJson,
|
||||
projectInitialJson,
|
||||
defaultBranchName,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,15 @@ export default {
|
|||
GlLink,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['searchType', 'defaultBranchName', 'query', 'searchLevel', 'query']),
|
||||
...mapState([
|
||||
'searchType',
|
||||
'advancedSearchAvailable',
|
||||
'zoektAvailable',
|
||||
'defaultBranchName',
|
||||
'query',
|
||||
'searchLevel',
|
||||
'query',
|
||||
]),
|
||||
...mapGetters(['currentScope']),
|
||||
isZoekt() {
|
||||
return this.searchType === ZOEKT_SEARCH_TYPE && this.currentScope === SCOPE_BLOB;
|
||||
|
|
@ -67,7 +75,14 @@ export default {
|
|||
|
||||
return BASIC_SEARCH_TYPE;
|
||||
},
|
||||
isEnabled() {
|
||||
searchTypeAvailableTestId() {
|
||||
if (this.zoektAvailable) {
|
||||
return ZOEKT_SEARCH_TYPE;
|
||||
}
|
||||
|
||||
return ADVANCED_SEARCH_TYPE;
|
||||
},
|
||||
useAdvancedOrZoekt() {
|
||||
const repoRef = this.query.repository_ref;
|
||||
switch (this.searchLevel) {
|
||||
case SEARCH_LEVEL_GLOBAL:
|
||||
|
|
@ -83,11 +98,14 @@ export default {
|
|||
return false;
|
||||
}
|
||||
},
|
||||
isFallBacktoBasicSearch() {
|
||||
return !this.useAdvancedOrZoekt && (this.advancedSearchAvailable || this.zoektAvailable);
|
||||
},
|
||||
isBasicSearch() {
|
||||
return this.searchType === BASIC_SEARCH_TYPE;
|
||||
},
|
||||
disabledMessage() {
|
||||
return this.isZoekt
|
||||
return this.zoektAvailable
|
||||
? this.$options.i18n.zoekt_disabled
|
||||
: this.$options.i18n.advanced_disabled;
|
||||
},
|
||||
|
|
@ -98,7 +116,7 @@ export default {
|
|||
return this.isZoekt ? this.$options.i18n.zoekt_enabled : this.$options.i18n.advanced_enabled;
|
||||
},
|
||||
syntaxHelpUrl() {
|
||||
return this.isZoekt
|
||||
return this.zoektAvailable
|
||||
? this.$options.zoektSyntaxHelpUrl
|
||||
: this.$options.advancedSearchSyntaxHelpUrl;
|
||||
},
|
||||
|
|
@ -108,28 +126,29 @@ export default {
|
|||
|
||||
<template>
|
||||
<div class="gl-inline gl-text-gray-600">
|
||||
<div v-if="isBasicSearch" data-testid="basic"></div>
|
||||
<div v-else-if="isEnabled" :data-testid="`${searchTypeTestId}-enabled`" class="gl-inline">
|
||||
<div v-if="isBasicSearch" data-testid="basic">
|
||||
<div v-if="isFallBacktoBasicSearch" :data-testid="`${searchTypeAvailableTestId}-disabled`">
|
||||
<gl-sprintf :message="disabledMessage">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }}</gl-link>
|
||||
</template>
|
||||
<template #ref_elem>
|
||||
<code v-gl-tooltip :title="query.repository_ref">{{ query.repository_ref }}</code>
|
||||
</template>
|
||||
<template #docs_link>
|
||||
<gl-link :href="syntaxHelpUrl" target="_blank" data-testid="syntax-docs-link"
|
||||
>{{ $options.i18n.more }}
|
||||
</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else :data-testid="`${searchTypeTestId}-enabled`" class="gl-inline">
|
||||
<gl-sprintf :message="enabledMessage">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
<div v-else :data-testid="`${searchTypeTestId}-disabled`" class="gl-inline">
|
||||
<gl-sprintf :message="disabledMessage">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="helpUrl" target="_blank" data-testid="docs-link">{{ content }}</gl-link>
|
||||
</template>
|
||||
<template #ref_elem>
|
||||
<code v-gl-tooltip :title="query.repository_ref">{{ query.repository_ref }}</code>
|
||||
</template>
|
||||
<template #docs_link>
|
||||
<gl-link :href="syntaxHelpUrl" target="_blank" data-testid="syntax-docs-link"
|
||||
>{{ $options.i18n.more }}
|
||||
</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ import NavItem from './nav_item.vue';
|
|||
// triangles, one above the section title, one below, do listen to events,
|
||||
// keeping hover.
|
||||
|
||||
// The flyout menu gets some padding, to keep it open when the cursor goes out
|
||||
// of bounds just a little bit. This padding is compensated with an offset, to
|
||||
// not have any visual effect.
|
||||
export const FLYOUT_PADDING = 12;
|
||||
|
||||
export default {
|
||||
name: 'FlyoutMenu',
|
||||
components: { NavItem },
|
||||
|
|
@ -59,6 +64,15 @@ export default {
|
|||
|
||||
return `${x}, ${y} 100, ${y} 100, 100`;
|
||||
},
|
||||
flyoutStyle() {
|
||||
return {
|
||||
padding: `${FLYOUT_PADDING}px`,
|
||||
// Add extra padding on the left, to completely overlap the scrollbar of
|
||||
// the sidebar, which can be pretty wide, depending on the user's browser.
|
||||
// See https://gitlab.com/gitlab-org/gitlab/-/issues/426023
|
||||
'padding-left': `${FLYOUT_PADDING * 2}px`,
|
||||
};
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const target = document.querySelector(`#${this.targetId}`);
|
||||
|
|
@ -71,7 +85,14 @@ export default {
|
|||
|
||||
const updatePosition = () =>
|
||||
computePosition(target, flyout, {
|
||||
middleware: [offset({ alignmentAxis: -12 }), flip(), shift()],
|
||||
middleware: [
|
||||
offset({
|
||||
mainAxis: -FLYOUT_PADDING,
|
||||
alignmentAxis: -FLYOUT_PADDING,
|
||||
}),
|
||||
flip(),
|
||||
shift(),
|
||||
],
|
||||
placement: 'right-start',
|
||||
strategy: 'fixed',
|
||||
}).then(({ x, y }) => {
|
||||
|
|
@ -126,7 +147,8 @@ export default {
|
|||
<template>
|
||||
<div
|
||||
:id="`${targetId}-flyout`"
|
||||
class="gl-fixed gl-z-9999 -gl-mx-1 gl-max-h-full gl-overflow-y-auto gl-p-4"
|
||||
:style="flyoutStyle"
|
||||
class="gl-fixed gl-z-9999 -gl-mx-1 gl-max-h-full gl-overflow-y-auto"
|
||||
@mouseover="$emit('mouseover')"
|
||||
@mouseleave="$emit('mouseleave')"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { GlBreadcrumb } from '@gitlab/ui';
|
||||
import { s__, __ } from '~/locale';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { ROUTES, WORK_ITEM_TYPE_ENUM_EPIC } from '../constants';
|
||||
|
||||
const BREADCRUMB_LABELS = {
|
||||
|
|
@ -12,22 +13,31 @@ export default {
|
|||
components: {
|
||||
GlBreadcrumb,
|
||||
},
|
||||
mixins: [glFeatureFlagMixin()],
|
||||
inject: {
|
||||
workItemType: {
|
||||
default: null,
|
||||
},
|
||||
epicsListPath: {
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isEpicsList() {
|
||||
return this.workItemType === WORK_ITEM_TYPE_ENUM_EPIC;
|
||||
},
|
||||
crumbs() {
|
||||
const crumbs = [
|
||||
{
|
||||
text: this.isEpicsList ? __('Epics') : s__('WorkItem|Work items'),
|
||||
to: { name: ROUTES.index, query: this.$route.query },
|
||||
},
|
||||
];
|
||||
const indexCrumb = {
|
||||
text: this.isEpicsList ? __('Epics') : s__('WorkItem|Work items'),
|
||||
};
|
||||
|
||||
if (this.glFeatures.workItemEpicsList) {
|
||||
indexCrumb.to = { name: ROUTES.index, query: this.$route.query };
|
||||
} else {
|
||||
indexCrumb.href = this.epicsListPath;
|
||||
}
|
||||
|
||||
const crumbs = [indexCrumb];
|
||||
|
||||
if (this.$route.name === ROUTES.new) {
|
||||
crumbs.push({
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ export const initWorkItemsRoot = ({ workItemType, workspaceType } = {}) => {
|
|||
if (isGroup)
|
||||
injectVueAppBreadcrumbs(router, WorkItemBreadcrumb, apolloProvider, {
|
||||
workItemType: listWorkItemType,
|
||||
epicsListPath,
|
||||
});
|
||||
|
||||
apolloProvider.clients.defaultClient.cache.writeQuery({
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ class SearchServicePresenter < Gitlab::View::Presenter::Delegated
|
|||
def advanced_search_enabled?
|
||||
false
|
||||
end
|
||||
|
||||
def zoekt_enabled?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
SearchServicePresenter.prepend_mod_with('SearchServicePresenter')
|
||||
|
|
|
|||
|
|
@ -18,6 +18,16 @@
|
|||
|
||||
#js-search-topbar{ data: { "default-branch-name": @project&.default_branch } }
|
||||
.results.lg:gl-flex.gl-mt-0
|
||||
#js-search-sidebar{ data: { navigation_json: search_navigation_json, search_type: search_service.search_type, search_level: search_service.level, group_initial_json: group_attributes.to_json, project_initial_json: project_attributes.to_json, ref: @project.present? ? repository_ref(@project) : nil } }
|
||||
#js-search-sidebar{
|
||||
data: {
|
||||
navigation_json: search_navigation_json,
|
||||
search_type: search_service.search_type,
|
||||
advanced_search_available: @search_service_presenter.advanced_search_enabled?.to_s,
|
||||
zoekt_available: @search_service_presenter.zoekt_enabled?.to_s,
|
||||
search_level: search_service.level,
|
||||
group_initial_json: group_attributes.to_json,
|
||||
project_initial_json: project_attributes.to_json,
|
||||
ref: @project.present? ? repository_ref(@project) : nil
|
||||
} }
|
||||
- if @search_term
|
||||
= render 'search/results'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: prompt_migration_summarize_comments
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/475044
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/163772
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/480550
|
||||
milestone: '17.4'
|
||||
group: group::custom models
|
||||
type: experiment
|
||||
default_enabled: false
|
||||
|
|
@ -29,34 +29,3 @@ namespace :user_settings do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Redirect routes till GitLab 17.0 release
|
||||
|
||||
resource :profile, only: [] do
|
||||
resources :active_sessions, only: [:destroy], controller: 'user_settings/active_sessions'
|
||||
resources :personal_access_tokens, controller: 'user_settings/personal_access_tokens', only: [] do
|
||||
member do
|
||||
put :revoke
|
||||
end
|
||||
end
|
||||
member do
|
||||
get :show, to: redirect(path: '-/user_settings/profile')
|
||||
put :update, controller: 'user_settings/profiles'
|
||||
patch :update, controller: 'user_settings/profiles'
|
||||
|
||||
get :active_sessions, to: redirect(path: '-/user_settings/active_sessions')
|
||||
get :personal_access_tokens, to: redirect(path: '-/user_settings/personal_access_tokens')
|
||||
end
|
||||
get 'password/new', to: redirect(path: '-/user_settings/password/new')
|
||||
get "password/edit", to: redirect(path: '-/user_settings/password/edit')
|
||||
|
||||
get 'gpg_keys', to: redirect(path: '-/user_settings/gpg_keys#index')
|
||||
post 'gpg_keys', to: redirect(path: '-/user_settings/gpg_keys#create')
|
||||
get 'gpg_keys/:id', to: redirect(path: '-/user_settings/gpg_keys#show')
|
||||
delete 'gpg_keys/:id', to: redirect(path: '-/user_settings/gpg_keys#destroy')
|
||||
|
||||
get 'keys', to: redirect(path: '-/user_settings/ssh_keys#index')
|
||||
post 'keys', to: redirect(path: '-/user_settings/ssh_keys#create')
|
||||
get 'keys/:id', to: redirect(path: '-/user_settings/ssh_keys#show')
|
||||
delete 'keys/:id', to: redirect(path: '-/user_settings/ssh_keys#destroy')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
- title: "Rate limits for common User, Project, and Group API endpoints"
|
||||
# The milestones for the deprecation announcement, and the removal.
|
||||
removal_milestone: "18.0"
|
||||
announcement_milestone: "17.4"
|
||||
# Change breaking_change to false if needed.
|
||||
breaking_change: true
|
||||
# The stage and GitLab username of the person reporting the change,
|
||||
# and a link to the deprecation issue
|
||||
reporter: joshlambert
|
||||
stage: systems
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/480914
|
||||
impact: low # Can be one of: [critical, high, medium, low]
|
||||
scope: instance # Can be one or a combination of: [instance, group, project]
|
||||
resolution_role: Admin # Can be one of: [Admin, Owner, Maintainer, Developer]
|
||||
manual_task: false # Can be true or false. Use this to denote whether a resolution action must be performed manually (true), or if it can be automated by using the API or other automation (false).
|
||||
body: |
|
||||
Rate limits will be enabled by default for commonly used [User](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html),
|
||||
[Project](https://docs.gitlab.com/ee/administration/settings/rate_limit_on_projects_api.html), and [Group](https://docs.gitlab.com/ee/administration/settings/rate_limit_on_groups_api.html) endpoints.
|
||||
Enabling these rate limits by default can help improve overall system stability,
|
||||
by reducing the potential for heavy API usage to negatively impact the broader user experience. Requests made above the rate
|
||||
limit will return an [HTTP 429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) error code and [additional rate limit headers](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html#response-headers).
|
||||
|
||||
The default rate limits have been intentionally set fairly high to not disrupt most usage, based on the request rates we see on GitLab.com.
|
||||
Instance administrators can set higher or lower limits as needed in the Admin area, similarly to other rate limits already in place.
|
||||
|
|
@ -203,8 +203,8 @@ To use self-managed runners, install [GitLab Runner](https://docs.gitlab.com/run
|
|||
To help you migrate your data to GitLab Dedicated, choose from the following options:
|
||||
|
||||
1. When migrating from another GitLab instance, you can import groups and projects by either:
|
||||
- Using [direct transfer](../../user/group/import/index.md).
|
||||
- Using the [direct transfer](../../api/bulk_imports.md) API.
|
||||
- Using [direct transfer](../../user/group/import/index.md).
|
||||
- Using the [direct transfer](../../api/bulk_imports.md) API.
|
||||
1. When migrating from third-party services, you can use [the GitLab importers](../../user/project/import/index.md#supported-import-sources).
|
||||
1. You can also engage [Professional Services](../../user/project/import/index.md#migrate-by-engaging-professional-services).
|
||||
|
||||
|
|
|
|||
|
|
@ -337,10 +337,10 @@ To resolve this issue, you can update the password expiration by either:
|
|||
|
||||
- Using `gitlab-psql`:
|
||||
|
||||
```sql
|
||||
# gitlab-psql
|
||||
UPDATE users SET password_expires_at = null WHERE username='<USERNAME>';
|
||||
```
|
||||
```sql
|
||||
# gitlab-psql
|
||||
UPDATE users SET password_expires_at = null WHERE username='<USERNAME>';
|
||||
```
|
||||
|
||||
The bug was reported [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/332455).
|
||||
|
||||
|
|
|
|||
|
|
@ -382,9 +382,9 @@ The directory for package metadata changed with the release of 16.2 from `vendor
|
|||
1. Update any automation scripts or commands saved to change `vendor/package_metadata_db` to `vendor/package_metadata/licenses`.
|
||||
1. Update any cron entries to change `vendor/package_metadata_db` to `vendor/package_metadata/licenses`.
|
||||
|
||||
```shell
|
||||
sed -i '.bckup' -e 's#vendor/package_metadata_db#vendor/package_metadata/licenses#g' [FILE ...]
|
||||
```
|
||||
```shell
|
||||
sed -i '.bckup' -e 's#vendor/package_metadata_db#vendor/package_metadata/licenses#g' [FILE ...]
|
||||
```
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ Learn how to use the [Google Cloud Run component](https://gitlab.com/google-gitl
|
|||
|
||||
1. To run the commands on this page, set up the `gcloud` CLI in one of the following development environments:
|
||||
|
||||
- [Cloud Shell](https://cloud.google.com/shell/docs/using-cloud-shell)
|
||||
- [Local shell](https://cloud.google.com/sdk/docs/install)
|
||||
- [Cloud Shell](https://cloud.google.com/shell/docs/using-cloud-shell)
|
||||
- [Local shell](https://cloud.google.com/sdk/docs/install)
|
||||
|
||||
1. Set your default Google Cloud project by running the following command:
|
||||
|
||||
|
|
@ -31,9 +31,9 @@ Learn how to use the [Google Cloud Run component](https://gitlab.com/google-gitl
|
|||
|
||||
1. Enable the Compute Engine and Cloud Run APIs:
|
||||
|
||||
```shell
|
||||
gcloud services enable compute.googleapis.com artifactregistry.googleapis.com run.googleapis.com
|
||||
```
|
||||
```shell
|
||||
gcloud services enable compute.googleapis.com artifactregistry.googleapis.com run.googleapis.com
|
||||
```
|
||||
|
||||
1. Grant the following roles to your workload identity pool:
|
||||
|
||||
|
|
@ -271,10 +271,10 @@ Replace the following:
|
|||
**Caution**: Deleting a project has the following effects:
|
||||
|
||||
- **Everything in the project is deleted.** If you used an existing project for the tasks in this document, when
|
||||
you delete it, you also delete any other work you've done in the project.
|
||||
you delete it, you also delete any other work you've done in the project.
|
||||
- **Custom project IDs are lost.** When you created this project, you might have created a custom project ID that
|
||||
you want to use in the future. To preserve the URLs that use the project ID, such as an appspot.com URL, delete selected
|
||||
resources inside the project instead of deleting the whole project.
|
||||
you want to use in the future. To preserve the URLs that use the project ID, such as an appspot.com URL, delete selected
|
||||
resources inside the project instead of deleting the whole project.
|
||||
|
||||
If you plan to explore multiple architectures, tutorials, or quick start tutorials on Google Cloud, reusing projects can help you
|
||||
avoid exceeding project quota limits.
|
||||
|
|
|
|||
|
|
@ -12,78 +12,77 @@ Learn how to connect GitLab to Google Cloud and create a GitLab pipeline using r
|
|||
|
||||
1. To run the commands on this page, set up the `gcloud` CLI in one of the following development environments:
|
||||
|
||||
- [Cloud Shell](https://cloud.google.com/shell/docs/using-cloud-shell)
|
||||
- [Local shell](https://cloud.google.com/sdk/docs/install)
|
||||
- [Cloud Shell](https://cloud.google.com/shell/docs/using-cloud-shell)
|
||||
- [Local shell](https://cloud.google.com/sdk/docs/install)
|
||||
|
||||
1. Create or select a Google Cloud project.
|
||||
|
||||
NOTE:
|
||||
If you don't plan to keep the resources that you create in this procedure, then create a new Google Cloud project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.
|
||||
NOTE:
|
||||
If you don't plan to keep the resources that you create in this procedure, then create a new Google Cloud project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.
|
||||
|
||||
To create a Google Cloud project, run the following command:
|
||||
To create a Google Cloud project, run the following command:
|
||||
|
||||
```shell
|
||||
gcloud projects create PROJECT_ID
|
||||
```
|
||||
```shell
|
||||
gcloud projects create PROJECT_ID
|
||||
```
|
||||
|
||||
Replace `PROJECT_ID` with a name for the Google Cloud project you are creating.
|
||||
Replace `PROJECT_ID` with a name for the Google Cloud project you are creating.
|
||||
|
||||
1. Select the Google Cloud project that you created:
|
||||
|
||||
```shell
|
||||
gcloud config set project PROJECT_ID
|
||||
```
|
||||
```shell
|
||||
gcloud config set project PROJECT_ID
|
||||
```
|
||||
|
||||
Replace `PROJECT_ID` with your Google Cloud project name.
|
||||
Replace `PROJECT_ID` with your Google Cloud project name.
|
||||
|
||||
1. [Make sure that billing is enabled for your Google Cloud project](https://cloud.google.com/billing/docs/how-to/verify-billing-enabled#console).
|
||||
|
||||
1. Enable the Compute Engine and Artifact Registry APIs:
|
||||
|
||||
```shell
|
||||
gcloud services enable compute.googleapis.com artifactregistry.googleapis.com
|
||||
|
||||
```
|
||||
```shell
|
||||
gcloud services enable compute.googleapis.com artifactregistry.googleapis.com
|
||||
```
|
||||
|
||||
1. Set up the GitLab on Google Cloud integration by following the
|
||||
instructions in [Google Cloud Workload Identity Federation and IAM policies](../../integration/google_cloud_iam.md).
|
||||
instructions in [Google Cloud Workload Identity Federation and IAM policies](../../integration/google_cloud_iam.md).
|
||||
|
||||
1. [Create a standard mode Docker format Artifact Registry repository](https://cloud.google.com/artifact-registry/docs/repositories/create-repos#create).
|
||||
|
||||
1. Connect your Artifact Registry repository to your GitLab project by following the
|
||||
instructions in [Set up the Google Artifact Registry registry in a GitLab project](../../user/project/integrations/google_artifact_management.md).
|
||||
instructions in [Set up the Google Artifact Registry registry in a GitLab project](../../user/project/integrations/google_artifact_management.md).
|
||||
|
||||
## Clone your GitLab repository
|
||||
|
||||
1. To clone your GitLab repository to your working environment using SSH or
|
||||
HTTPS, follow the instructions in
|
||||
[Clone a Git repository to your local computer](../../topics/git/clone.md).
|
||||
HTTPS, follow the instructions in
|
||||
[Clone a Git repository to your local computer](../../topics/git/clone.md).
|
||||
|
||||
1. If you are working in your local shell,
|
||||
[install Terraform](https://developer.hashicorp.com/terraform/install?product_intent=terraform). Terraform is already installed in
|
||||
Cloud Shell.
|
||||
[install Terraform](https://developer.hashicorp.com/terraform/install?product_intent=terraform). Terraform is already installed in
|
||||
Cloud Shell.
|
||||
|
||||
## Create a Dockerfile
|
||||
|
||||
1. In your cloned repository, create a new file named `Dockerfile`.
|
||||
1. Copy and paste the following into your `Dockerfile`.
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile for test purposes. Generates a new random image in every build.
|
||||
FROM alpine:3.15.11
|
||||
RUN dd if=/dev/urandom of=random bs=10 count=1
|
||||
```
|
||||
```dockerfile
|
||||
# Dockerfile for test purposes. Generates a new random image in every build.
|
||||
FROM alpine:3.15.11
|
||||
RUN dd if=/dev/urandom of=random bs=10 count=1
|
||||
```
|
||||
|
||||
1. Add your `Dockerfile` to Git, commit, and push to your GitLab repository.
|
||||
|
||||
```shell
|
||||
git add Dockerfile
|
||||
git commit -m "add dockerfile"
|
||||
git push
|
||||
```
|
||||
```shell
|
||||
git add Dockerfile
|
||||
git commit -m "add dockerfile"
|
||||
git push
|
||||
```
|
||||
|
||||
You are prompted to enter your username and
|
||||
[personal access token](../../user/profile/personal_access_tokens.md).
|
||||
You are prompted to enter your username and
|
||||
[personal access token](../../user/profile/personal_access_tokens.md).
|
||||
|
||||
The Dockerfile generates a new random image for every build, and is only for
|
||||
test purposes.
|
||||
|
|
@ -111,47 +110,47 @@ Create a pipeline that builds your Docker image, pushes it to the GitLab contain
|
|||
registry, and copies the image to Google Artifact Registry.
|
||||
|
||||
1. In your GitLab project, create a
|
||||
[`.gitlab-ci.yml` file](../../ci/quick_start/index.md#create-a-gitlab-ciyml-file).
|
||||
[`.gitlab-ci.yml` file](../../ci/quick_start/index.md#create-a-gitlab-ciyml-file).
|
||||
|
||||
1. To create a pipeline that builds your image, pushes it to the GitLab container
|
||||
registry, and copies it to Google Artifact Registry, modify the contents of your
|
||||
`.gitlab-ci.yml` file to resemble the following.
|
||||
registry, and copies it to Google Artifact Registry, modify the contents of your
|
||||
`.gitlab-ci.yml` file to resemble the following.
|
||||
|
||||
In the example, replace the following:
|
||||
In the example, replace the following:
|
||||
|
||||
- <var><code>LOCATION</code></var>: the
|
||||
Google Cloud region where you created your Google Artifact Registry repository.
|
||||
- <var><code>PROJECT</code></var>: your
|
||||
Google Cloud project ID.
|
||||
- <var><code>REPOSITORY</code></var>: the
|
||||
repository ID of your Google Artifact Registry repository.
|
||||
- <var><code>LOCATION</code></var>: the
|
||||
Google Cloud region where you created your Google Artifact Registry repository.
|
||||
- <var><code>PROJECT</code></var>: your
|
||||
Google Cloud project ID.
|
||||
- <var><code>REPOSITORY</code></var>: the
|
||||
repository ID of your Google Artifact Registry repository.
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
```yaml
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
GITLAB_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
|
||||
variables:
|
||||
GITLAB_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
|
||||
|
||||
build-sample-image:
|
||||
image: docker:24.0.5
|
||||
stage: build
|
||||
services:
|
||||
- docker:24.0.5-dind
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker build -t $GITLAB_IMAGE .
|
||||
- docker push $GITLAB_IMAGE
|
||||
build-sample-image:
|
||||
image: docker:24.0.5
|
||||
stage: build
|
||||
services:
|
||||
- docker:24.0.5-dind
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
script:
|
||||
- docker build -t $GITLAB_IMAGE .
|
||||
- docker push $GITLAB_IMAGE
|
||||
|
||||
include:
|
||||
- component: gitlab.com/google-gitlab-components/artifact-registry/upload-artifact-registry@0.1.0
|
||||
inputs:
|
||||
stage: deploy
|
||||
source: $GITLAB_IMAGE
|
||||
target: LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/image:v1.0.0
|
||||
```
|
||||
include:
|
||||
- component: gitlab.com/google-gitlab-components/artifact-registry/upload-artifact-registry@0.1.0
|
||||
inputs:
|
||||
stage: deploy
|
||||
source: $GITLAB_IMAGE
|
||||
target: LOCATION-docker.pkg.dev/PROJECT/REPOSITORY/image:v1.0.0
|
||||
```
|
||||
|
||||
The pipeline uses Docker in Docker to build the image `docker:24.0.5`, stores it
|
||||
in the GitLab container registry, and then uses the
|
||||
|
|
@ -173,7 +172,7 @@ To view your artifact in Google Artifact Registry:
|
|||
1. Select the name of your linked repository.
|
||||
1. Select the name of the image to view the version name and tags.
|
||||
1. Select the name of the image version to view the version's build, pull, and
|
||||
manifest information.
|
||||
manifest information.
|
||||
|
||||
## Clean up
|
||||
|
||||
|
|
@ -215,10 +214,10 @@ Replace the following:
|
|||
**Caution**: Deleting a project has the following effects:
|
||||
|
||||
- **Everything in the project is deleted.** If you used an existing project for the tasks in this document, when
|
||||
you delete it, you also delete any other work you've done in the project.
|
||||
you delete it, you also delete any other work you've done in the project.
|
||||
- **Custom project IDs are lost.** When you created this project, you might have created a custom project ID that
|
||||
you want to use in the future. To preserve the URLs that use the project ID, such as an appspot.com URL, delete selected
|
||||
resources inside the project instead of deleting the whole project.
|
||||
you want to use in the future. To preserve the URLs that use the project ID, such as an appspot.com URL, delete selected
|
||||
resources inside the project instead of deleting the whole project.
|
||||
|
||||
If you plan to explore multiple architectures, tutorials, or quick start tutorials on Google Cloud, reusing projects can help you
|
||||
avoid exceeding project quota limits.
|
||||
|
|
@ -231,4 +230,4 @@ avoid exceeding project quota limits.
|
|||
|
||||
- Learn how to [Optimize GitLab CI/CD configuration files](../../ci/yaml/yaml_optimization.md).
|
||||
- Read about how the GitLab on Google Cloud integration uses IAM with
|
||||
workload identity federation to control access to Google Cloud in [Access control with IAM](https://cloud.google.com/docs/gitlab/access-control).
|
||||
workload identity federation to control access to Google Cloud in [Access control with IAM](https://cloud.google.com/docs/gitlab/access-control).
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ First, create a GitLab project and a corresponding access token.
|
|||
1. Select **Create from template**.
|
||||
1. Select **Spring** and then **Use template**.
|
||||
1. Enter the project details.
|
||||
- In the **Project name** field, enter a name such as `test-spring-o11y`
|
||||
- In the **Project name** field, enter a name such as `test-spring-o11y`
|
||||
1. Select **Create project**.
|
||||
1. In the `test-sprint-o11y` project, on the left sidebar, select **Settings > Access tokens**.
|
||||
1. Create an access token with the `api` scope and Developer role. Store the token value somewhere safe.
|
||||
|
|
@ -39,7 +39,9 @@ Next, we'll run the application to ensure that it works.
|
|||
|
||||
1. After cloning the project from GitLab, open it in IntelliJ (or your preferred IDE).
|
||||
1. Open `src/main/java/com.example.demo/DemoApplication` and run the application:
|
||||

|
||||
|
||||

|
||||
|
||||
1. After initialization, the application should be available at `http://localhost:8000`. Test it out, then in the IDE select the **Stop** button.
|
||||
|
||||
## Add the OpenTelemetry dependencies
|
||||
|
|
@ -48,44 +50,44 @@ Use auto-instrumentation to instrument the application:
|
|||
|
||||
1. In the `pom.xml` file, add the required dependencies:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
```xml
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-bom</artifactId>
|
||||
<version>1.40.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
```
|
||||
```xml
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.opentelemetry</groupId>
|
||||
<artifactId>opentelemetry-bom</artifactId>
|
||||
<version>1.40.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
```
|
||||
|
||||
1. Update dependencies by selecting **Update Maven Changes**:
|
||||
|
||||

|
||||

|
||||
|
||||
1. Download the OpenTelemetry java agent file from the OpenTelemetry repository.
|
||||
|
||||
```shell
|
||||
curl --location --http1.0 "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar"
|
||||
```
|
||||
```shell
|
||||
curl --location --http1.0 "https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar"
|
||||
```
|
||||
|
||||
## Define environment variables
|
||||
|
||||
|
|
@ -93,11 +95,11 @@ The OpenTelemetry autoconfigure libraries read their configuration from environm
|
|||
|
||||
1. From the top-right menu, select **Edit Configurations...**:
|
||||
|
||||

|
||||

|
||||
|
||||
1. In the configuration menu, select the icon in the **Environment Variables** field.
|
||||
|
||||

|
||||

|
||||
|
||||
1. Add the following set of environment variables, replacing `{{PATH_TO_JAVA_AGENT}}`, `{{PROJECT_ID}}`, `{{PROJECT_ACCESS_TOKEN}}` and `{{SERVICE_NAME}}` with the correct values. If using a self-managed GitLab instance, replace `gitlab.com` with your self-managed instance hostname.
|
||||
- `JAVA_TOOL_OPTIONS=-javaagent:{{PATH_TO_JAVA_AGENT}}/opentelemetry-javaagent.jar`
|
||||
|
|
|
|||
|
|
@ -83,39 +83,39 @@ To instrument your new website:
|
|||
1. In the left Web IDE toolbar, select **File Explorer** and open the `public/index.html` file.
|
||||
1. In the `public/index.html` file, before the closing `</body>` tag, paste the snippet you copied in the previous section.
|
||||
|
||||
The code in the `index.html` file should look like this (where `appId` and `host` have the values provided in the onboarding section):
|
||||
The code in the `index.html` file should look like this (where `appId` and `host` have the values provided in the onboarding section):
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="GitLab Pages">
|
||||
<title>Plain HTML site using GitLab Pages</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<a href="https://pages.gitlab.io/plain-html/">Plain HTML Example</a>
|
||||
<a href="https://gitlab.com/pages/plain-html/">Repository</a>
|
||||
<a href="https://gitlab.com/pages/">Other Examples</a>
|
||||
</div>
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="generator" content="GitLab Pages">
|
||||
<title>Plain HTML site using GitLab Pages</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar">
|
||||
<a href="https://pages.gitlab.io/plain-html/">Plain HTML Example</a>
|
||||
<a href="https://gitlab.com/pages/plain-html/">Repository</a>
|
||||
<a href="https://gitlab.com/pages/">Other Examples</a>
|
||||
</div>
|
||||
|
||||
<h1>Hello World!</h1>
|
||||
<h1>Hello World!</h1>
|
||||
|
||||
<p>
|
||||
This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.
|
||||
</p>
|
||||
<script src="https://unpkg.com/@gitlab/application-sdk-browser/dist/gl-sdk.min.js"></script>
|
||||
<script>
|
||||
window.glClient = window.glSDK.glClientSDK({
|
||||
appId: 'YOUR_APP_ID',
|
||||
host: 'YOUR_HOST',
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
<p>
|
||||
This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.
|
||||
</p>
|
||||
<script src="https://unpkg.com/@gitlab/application-sdk-browser/dist/gl-sdk.min.js"></script>
|
||||
<script>
|
||||
window.glClient = window.glSDK.glClientSDK({
|
||||
appId: 'YOUR_APP_ID',
|
||||
host: 'YOUR_HOST',
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
1. In the left Web IDE toolbar, select **Source Control**.
|
||||
1. Enter a commit message, such as `Add GitLab product analytics tracking snippet`.
|
||||
|
|
|
|||
|
|
@ -458,6 +458,29 @@ The project page will be removed entirely from the group settings in 18.0.
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="18.0">
|
||||
|
||||
### Rate limits for common User, Project, and Group API endpoints
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
||||
- Announced in GitLab <span class="milestone">17.4</span>
|
||||
- Removal in GitLab <span class="milestone">18.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change))
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/480914).
|
||||
|
||||
</div>
|
||||
|
||||
Rate limits will be enabled by default for commonly used [User](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html),
|
||||
[Project](https://docs.gitlab.com/ee/administration/settings/rate_limit_on_projects_api.html), and [Group](https://docs.gitlab.com/ee/administration/settings/rate_limit_on_groups_api.html) endpoints.
|
||||
Enabling these rate limits by default can help improve overall system stability,
|
||||
by reducing the potential for heavy API usage to negatively impact the broader user experience. Requests made above the rate
|
||||
limit will return an [HTTP 429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) error code and [additional rate limit headers](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html#response-headers).
|
||||
|
||||
The default rate limits have been intentionally set fairly high to not disrupt most usage, based on the request rates we see on GitLab.com.
|
||||
Instance administrators can set higher or lower limits as needed in the Admin area, similarly to other rate limits already in place.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="18.0">
|
||||
|
||||
### Registration tokens and server-side runner arguments in `POST /api/v4/runners` endpoint
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
|
|||
|
|
@ -10,36 +10,45 @@ DETAILS:
|
|||
**Tier:** Free
|
||||
**Offering:** GitLab.com
|
||||
|
||||
A five-user limit applies to newly created top-level namespaces with
|
||||
private visibility on GitLab.com. For existing namespaces created before December 28, 2022, the limit was applied on June 13, 2023.
|
||||
You can add up to five users to newly created top-level namespaces with
|
||||
private visibility on GitLab.com.
|
||||
|
||||
When the five-user limit is applied, top-level private namespaces
|
||||
exceeding the user limit are placed in a read-only state. These
|
||||
namespaces cannot write new data to repositories, Git Large File
|
||||
Storage (LFS), packages, or registries. For the full list of restricted
|
||||
actions, see [Read-only namespaces](read_only_namespaces.md).
|
||||
If the namespace was created before December 28, 2022, this user limit was
|
||||
applied on June 13, 2023.
|
||||
|
||||
In the Free tier of GitLab.com, user limits do not apply to users in:
|
||||
Top-level private namespaces with more than five users are placed in a read-only
|
||||
state. These namespaces cannot write new data to any of the following:
|
||||
|
||||
- Public top-level groups
|
||||
- Paid tiers
|
||||
- [Community programs](https://about.gitlab.com/community/):
|
||||
- GitLab for Open Source
|
||||
- GitLab for Education
|
||||
- GitLab for Startups
|
||||
- Repositories
|
||||
- Git Large File Storage (LFS)
|
||||
- Packages
|
||||
- Registries.
|
||||
|
||||
[Self-managed subscriptions](../subscriptions/self_managed/index.md) do not have user limits on the Free tier. You can also [talk to an expert](https://page.gitlab.com/usage_limits_help.html) for more information about your options.
|
||||
For the full list of restricted actions, see [read-only namespaces](read_only_namespaces.md).
|
||||
|
||||
NOTE:
|
||||
Personal namespaces are public by default and are excluded from the user limit.
|
||||
User limits do not apply to users in the Free tier of:
|
||||
|
||||
## Determining namespace user counts
|
||||
- GitLab.com, for:
|
||||
- Public top-level groups
|
||||
- Personal namespaces, because they are public by default
|
||||
- Paid tiers
|
||||
- The following [community programs](https://about.gitlab.com/community/):
|
||||
- GitLab for Open Source
|
||||
- GitLab for Education
|
||||
- GitLab for Startups
|
||||
- [Self-managed subscriptions](../subscriptions/self_managed/index.md)
|
||||
|
||||
Every unique user of a top-level namespace with private visibility counts towards the five-user limit. This includes every user of a group, subgroup, and project within a namespace.
|
||||
For more information, you can [talk to an expert](https://page.gitlab.com/usage_limits_help.html).
|
||||
|
||||
For example:
|
||||
## Determine namespace user counts
|
||||
|
||||
The group `example-1` has:
|
||||
Every unique user of a top-level namespace with private visibility counts towards
|
||||
the five-user limit. This includes every user of a group, subgroup, and project
|
||||
within a namespace.
|
||||
|
||||
For example, there are two groups, `example-1` and `example-2`.
|
||||
|
||||
The `example-1` group has:
|
||||
|
||||
- One group owner, `A`.
|
||||
- One subgroup called `subgroup-1` with one member, `B`.
|
||||
|
|
@ -47,9 +56,10 @@ The group `example-1` has:
|
|||
- One project in `subgroup-1` called `project-1` with two members, `C` and `D`.
|
||||
- `project-1` inherits `A` and `B` as members from `subgroup-1`.
|
||||
|
||||
The namespace `example-1` has four unique members: `A`, `B`, `C`, and `D`. Because `example-1` has only four unique members, it is not impacted by the five-user limit.
|
||||
The namespace `example-1` has four unique members: `A`, `B`, `C`, and `D`, so
|
||||
does not exceed the five-user limit.
|
||||
|
||||
The group `example-2` has:
|
||||
The `example-2` group has:
|
||||
|
||||
- One group owner, `A`.
|
||||
- One subgroup called `subgroup-2` with one member, `B`.
|
||||
|
|
@ -59,7 +69,8 @@ The group `example-2` has:
|
|||
- One project in `subgroup-2` called `project-2b` with two members, `E` and `F`.
|
||||
- `project-2b` inherits `A` and `B` as members from `subgroup-2`.
|
||||
|
||||
The namespace `example-2` has six unique members: `A`, `B`, `C`, `D`, `E`, and `F`. Because `example-2` has six unique users, it is impacted by the five-user limit.
|
||||
The namespace `example-2` has six unique members: `A`, `B`, `C`, `D`, `E`, and `F`,
|
||||
so it exceeds the five-user limit.
|
||||
|
||||
## Manage members in your group namespace
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {
|
|||
GlFormCombobox,
|
||||
GlFormGroup,
|
||||
GlFormInput,
|
||||
GlFormSelect,
|
||||
GlCollapsibleListbox,
|
||||
GlLink,
|
||||
GlModal,
|
||||
GlSprintf,
|
||||
|
|
@ -102,7 +102,7 @@ describe('CI Variable Drawer', () => {
|
|||
const findValueLabel = () => wrapper.findByTestId('ci-variable-value-label');
|
||||
const findHiddenVariableTip = () => wrapper.findByTestId('hidden-variable-tip');
|
||||
const findTitle = () => findDrawer().find('h2');
|
||||
const findTypeDropdown = () => wrapper.findComponent(GlFormSelect);
|
||||
const findTypeDropdown = () => wrapper.findComponent(GlCollapsibleListbox);
|
||||
const findVariablesPrecedenceDocsLink = () =>
|
||||
wrapper.findByTestId('ci-variable-precedence-docs-link');
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ describe('CI Variable Drawer', () => {
|
|||
});
|
||||
|
||||
it('adds each type option as a dropdown item', () => {
|
||||
expect(findTypeDropdown().findAll('option')).toHaveLength(variableOptions.length);
|
||||
expect(findTypeDropdown().props('items')).toHaveLength(variableOptions.length);
|
||||
|
||||
variableOptions.forEach((v) => {
|
||||
expect(findTypeDropdown().text()).toContain(v.text);
|
||||
|
|
@ -143,9 +143,7 @@ describe('CI Variable Drawer', () => {
|
|||
});
|
||||
|
||||
it('is set to environment variable by default', () => {
|
||||
expect(findTypeDropdown().findAll('option').at(0).attributes('value')).toBe(
|
||||
variableTypes.envType,
|
||||
);
|
||||
expect(findTypeDropdown().props('items')[0].value).toBe(variableTypes.envType);
|
||||
});
|
||||
|
||||
it('renders the selected variable type', () => {
|
||||
|
|
@ -157,7 +155,7 @@ describe('CI Variable Drawer', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(findTypeDropdown().attributes('value')).toBe(variableTypes.fileType);
|
||||
expect(findTypeDropdown().props('selected')).toBe(variableTypes.fileType);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { STATUS_CLOSED, STATUS_OPEN, STATUS_MERGED } from '~/issues/constants';
|
|||
import { TYPENAME_USER } from '~/graphql_shared/constants';
|
||||
import { convertToGraphQLId } from '~/graphql_shared/utils';
|
||||
import {
|
||||
TOKEN_TYPE_APPROVED_BY,
|
||||
TOKEN_TYPE_AUTHOR,
|
||||
TOKEN_TYPE_DRAFT,
|
||||
TOKEN_TYPE_LABEL,
|
||||
|
|
@ -139,6 +140,7 @@ describe('Merge requests list app', () => {
|
|||
|
||||
it('does not have preloaded users when gon.current_user_id does not exist', () => {
|
||||
expect(findIssuableList().props('searchTokens')).toMatchObject([
|
||||
{ type: TOKEN_TYPE_APPROVED_BY, preloadedUsers: [] },
|
||||
{ type: TOKEN_TYPE_ASSIGNEE },
|
||||
{ type: TOKEN_TYPE_REVIEWER, preloadedUsers: [] },
|
||||
{ type: TOKEN_TYPE_AUTHOR, preloadedUsers: [] },
|
||||
|
|
@ -155,6 +157,7 @@ describe('Merge requests list app', () => {
|
|||
|
||||
describe('when all tokens are available', () => {
|
||||
const urlParams = {
|
||||
'approved_by_usernames[]': 'anthony',
|
||||
assignee_username: 'bob',
|
||||
reviewer_username: 'bill',
|
||||
draft: 'yes',
|
||||
|
|
@ -190,6 +193,7 @@ describe('Merge requests list app', () => {
|
|||
];
|
||||
|
||||
expect(findIssuableList().props('searchTokens')).toMatchObject([
|
||||
{ type: TOKEN_TYPE_APPROVED_BY, preloadedUsers },
|
||||
{ type: TOKEN_TYPE_ASSIGNEE },
|
||||
{ type: TOKEN_TYPE_REVIEWER, preloadedUsers },
|
||||
{ type: TOKEN_TYPE_AUTHOR, preloadedUsers },
|
||||
|
|
@ -205,6 +209,7 @@ describe('Merge requests list app', () => {
|
|||
|
||||
it('pre-displays tokens that are in the url search parameters', () => {
|
||||
expect(findIssuableList().props('initialFilterValue')).toMatchObject([
|
||||
{ type: TOKEN_TYPE_APPROVED_BY },
|
||||
{ type: TOKEN_TYPE_ASSIGNEE },
|
||||
{ type: TOKEN_TYPE_REVIEWER },
|
||||
{ type: TOKEN_TYPE_DRAFT },
|
||||
|
|
|
|||
|
|
@ -47,30 +47,32 @@ describe('SearchTypeIndicator', () => {
|
|||
// all possible combinations
|
||||
|
||||
describe.each`
|
||||
searchType | searchLevel | repository | scope | showSearchTypeIndicator
|
||||
${'advanced'} | ${'project'} | ${'master'} | ${'blobs'} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'project'} | ${'v0.1'} | ${'blobs'} | ${'advanced-disabled'}
|
||||
${'advanced'} | ${'group'} | ${'master'} | ${'blobs'} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'global'} | ${'master'} | ${'blobs'} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'master'} | ${'blobs'} | ${'zoekt-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'v0.1'} | ${'blobs'} | ${'zoekt-disabled'}
|
||||
${'zoekt'} | ${'group'} | ${'master'} | ${'blobs'} | ${'zoekt-enabled'}
|
||||
${'advanced'} | ${'project'} | ${'master'} | ${'issues'} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'project'} | ${'v0.1'} | ${'issues'} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'group'} | ${'master'} | ${'issues'} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'global'} | ${'master'} | ${'issues'} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'master'} | ${'issues'} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'v0.1'} | ${'issues'} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'group'} | ${'master'} | ${'issues'} | ${'advanced-enabled'}
|
||||
searchType | searchLevel | repository | scope | zoektAvailable | showSearchTypeIndicator
|
||||
${'advanced'} | ${'project'} | ${'master'} | ${'blobs'} | ${false} | ${'advanced-enabled'}
|
||||
${'basic'} | ${'project'} | ${'v0.1'} | ${'blobs'} | ${false} | ${'advanced-disabled'}
|
||||
${'advanced'} | ${'group'} | ${'master'} | ${'blobs'} | ${false} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'global'} | ${'master'} | ${'blobs'} | ${false} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'master'} | ${'blobs'} | ${true} | ${'zoekt-enabled'}
|
||||
${'basic'} | ${'project'} | ${'v0.1'} | ${'blobs'} | ${true} | ${'zoekt-disabled'}
|
||||
${'zoekt'} | ${'group'} | ${'master'} | ${'blobs'} | ${true} | ${'zoekt-enabled'}
|
||||
${'advanced'} | ${'project'} | ${'master'} | ${'issues'} | ${false} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'project'} | ${'v0.1'} | ${'issues'} | ${false} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'group'} | ${'master'} | ${'issues'} | ${false} | ${'advanced-enabled'}
|
||||
${'advanced'} | ${'global'} | ${'master'} | ${'issues'} | ${false} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'master'} | ${'issues'} | ${true} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'project'} | ${'v0.1'} | ${'issues'} | ${true} | ${'advanced-enabled'}
|
||||
${'zoekt'} | ${'group'} | ${'master'} | ${'issues'} | ${true} | ${'advanced-enabled'}
|
||||
`(
|
||||
'search type indicator for $searchType $searchLevel $scope',
|
||||
({ searchType, repository, showSearchTypeIndicator, scope, searchLevel }) => {
|
||||
({ searchType, repository, showSearchTypeIndicator, scope, searchLevel, zoektAvailable }) => {
|
||||
beforeEach(() => {
|
||||
getterSpies.currentScope = jest.fn(() => scope);
|
||||
createComponent({
|
||||
query: { repository_ref: repository, scope },
|
||||
searchType,
|
||||
searchLevel,
|
||||
advancedSearchAvailable: true,
|
||||
zoektAvailable,
|
||||
defaultBranchName: 'master',
|
||||
});
|
||||
});
|
||||
|
|
@ -124,22 +126,27 @@ describe('SearchTypeIndicator', () => {
|
|||
});
|
||||
|
||||
describe.each`
|
||||
searchType | syntaxdocsLink
|
||||
${'advanced'} | ${'/help/user/search/advanced_search#syntax'}
|
||||
${'zoekt'} | ${'/help/user/search/exact_code_search#syntax'}
|
||||
`('Syntax documentation $searchType', ({ searchType, syntaxdocsLink }) => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
query: { repository_ref: '000', scope: 'blobs' },
|
||||
searchType,
|
||||
searchLevel: 'project',
|
||||
defaultBranchName: 'master',
|
||||
searchType | advancedSearchAvailable | zoektAvailable | syntaxdocsLink
|
||||
${'basic'} | ${true} | ${false} | ${'/help/user/search/advanced_search#syntax'}
|
||||
${'basic'} | ${true} | ${true} | ${'/help/user/search/exact_code_search#syntax'}
|
||||
`(
|
||||
'Syntax documentation $searchType',
|
||||
({ searchType, advancedSearchAvailable, zoektAvailable, syntaxdocsLink }) => {
|
||||
beforeEach(() => {
|
||||
createComponent({
|
||||
query: { repository_ref: '000', scope: 'blobs' },
|
||||
searchType,
|
||||
advancedSearchAvailable,
|
||||
zoektAvailable,
|
||||
searchLevel: 'project',
|
||||
defaultBranchName: 'master',
|
||||
});
|
||||
});
|
||||
});
|
||||
it('has correct link', () => {
|
||||
expect(findSyntaxDocsLink().attributes('href')).toBe(syntaxdocsLink);
|
||||
});
|
||||
});
|
||||
it('has correct link', () => {
|
||||
expect(findSyntaxDocsLink().attributes('href')).toBe(syntaxdocsLink);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe('Indicator is not using url query as source of truth', () => {
|
||||
beforeEach(() => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import FlyoutMenu from '~/super_sidebar/components/flyout_menu.vue';
|
||||
import FlyoutMenu, { FLYOUT_PADDING } from '~/super_sidebar/components/flyout_menu.vue';
|
||||
|
||||
jest.mock('@floating-ui/dom');
|
||||
|
||||
|
|
@ -32,4 +32,9 @@ describe('FlyoutMenu', () => {
|
|||
it('renders the component', () => {
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('applies the correct padding', () => {
|
||||
expect(wrapper.element.style.padding).toContain(`${FLYOUT_PADDING}px`);
|
||||
expect(wrapper.element.style.paddingLeft).toContain(`${FLYOUT_PADDING * 2}px`);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,10 +8,14 @@ describe('WorkItemBreadcrumb', () => {
|
|||
|
||||
const findBreadcrumb = () => wrapper.findComponent(GlBreadcrumb);
|
||||
|
||||
const createComponent = ({ workItemType = null, $route = {} } = {}) => {
|
||||
const createComponent = ({ workItemType = null, workItemEpicsList = true, $route = {} } = {}) => {
|
||||
wrapper = shallowMount(WorkItemBreadcrumb, {
|
||||
provide: {
|
||||
workItemType,
|
||||
glFeatures: {
|
||||
workItemEpicsList,
|
||||
},
|
||||
epicsListPath: '/epics',
|
||||
},
|
||||
mocks: {
|
||||
$route,
|
||||
|
|
@ -19,6 +23,17 @@ describe('WorkItemBreadcrumb', () => {
|
|||
});
|
||||
};
|
||||
|
||||
it('renders a href to the legacy epics page if the workItemEpicsList feature is disabled', () => {
|
||||
createComponent({ workItemType: WORK_ITEM_TYPE_ENUM_EPIC, workItemEpicsList: false });
|
||||
|
||||
expect(findBreadcrumb().props('items')).toEqual([
|
||||
{
|
||||
text: 'Epics',
|
||||
href: '/epics',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('renders root `Work items` breadcrumb on work items list page', () => {
|
||||
createComponent();
|
||||
|
||||
|
|
|
|||
|
|
@ -57,4 +57,10 @@ RSpec.describe SearchServicePresenter, feature_category: :global_search do
|
|||
|
||||
it { expect(presenter.advanced_search_enabled?).to eq(false) }
|
||||
end
|
||||
|
||||
describe '#zoekt_enabled?' do
|
||||
let(:scope) { nil }
|
||||
|
||||
it { expect(presenter.zoekt_enabled?).to eq(false) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe "Legacy routes", type: :request, feature_category: :system_access do
|
||||
let(:user) { create(:user) }
|
||||
let(:token) { create(:personal_access_token, user: user) }
|
||||
|
||||
before do
|
||||
login_as(user)
|
||||
end
|
||||
|
||||
it "GET /-/profile" do
|
||||
get "/-/profile"
|
||||
expect(response).to redirect_to('/-/user_settings/profile')
|
||||
end
|
||||
|
||||
it "PUT /-/profile" do
|
||||
put "/-/profile", params: { user: { pronouns: 'they/them' } }
|
||||
expect(user.reload.pronouns).to eq('they/them')
|
||||
end
|
||||
|
||||
it "PATCH /-/profile" do
|
||||
patch "/-/profile", params: { user: { pronouns: 'they/them' } }
|
||||
expect(user.reload.pronouns).to eq('they/them')
|
||||
end
|
||||
|
||||
it "/-/profile/audit_log" do
|
||||
get "/-/profile/audit_log"
|
||||
expect(response).to redirect_to('/-/user_settings/authentication_log')
|
||||
end
|
||||
|
||||
it "/-/profile/active_sessions" do
|
||||
get "/-/profile/active_sessions"
|
||||
expect(response).to redirect_to('/-/user_settings/active_sessions')
|
||||
end
|
||||
|
||||
it "/-/profile/personal_access_tokens" do
|
||||
get "/-/profile/personal_access_tokens"
|
||||
expect(response).to redirect_to('/-/user_settings/personal_access_tokens')
|
||||
|
||||
get "/-/profile/personal_access_tokens?name=GitLab+Dangerbot&scopes=api"
|
||||
expect(response).to redirect_to('/-/user_settings/personal_access_tokens?name=GitLab+Dangerbot&scopes=api')
|
||||
end
|
||||
|
||||
it "/-/profile/personal_access_tokens/:id/revoke" do
|
||||
put "/-/profile/personal_access_tokens/#{token.id}/revoke"
|
||||
expect(token.reload).to be_revoked
|
||||
end
|
||||
|
||||
it "/-/profile/applications" do
|
||||
get "/-/profile/applications"
|
||||
expect(response).to redirect_to('/-/user_settings/applications')
|
||||
end
|
||||
|
||||
it "/-/profile/password/new" do
|
||||
get "/-/profile/password/new"
|
||||
expect(response).to redirect_to('/-/user_settings/password/new')
|
||||
|
||||
get "/-/profile/password/new?abc=xyz"
|
||||
expect(response).to redirect_to('/-/user_settings/password/new?abc=xyz')
|
||||
end
|
||||
|
||||
it "/-/profile/password/edit" do
|
||||
get "/-/profile/password/edit"
|
||||
expect(response).to redirect_to('/-/user_settings/password/edit')
|
||||
|
||||
get "/-/profile/password/edit?abc=xyz"
|
||||
expect(response).to redirect_to('/-/user_settings/password/edit?abc=xyz')
|
||||
end
|
||||
|
||||
it "/-/profile/gpg_keys" do
|
||||
get "/-/profile/gpg_keys"
|
||||
expect(response).to redirect_to('/-/user_settings/gpg_keys#index')
|
||||
|
||||
post("/-/profile/gpg_keys")
|
||||
expect(response).to redirect_to('/-/user_settings/gpg_keys#create')
|
||||
|
||||
get("/-/profile/gpg_keys/1")
|
||||
expect(response).to redirect_to('/-/user_settings/gpg_keys#show')
|
||||
|
||||
delete("/-/profile/gpg_keys/1")
|
||||
expect(response).to redirect_to('/-/user_settings/gpg_keys#destroy')
|
||||
end
|
||||
|
||||
it "/-/profile/keys" do
|
||||
get "/-/profile/keys"
|
||||
expect(response).to redirect_to('/-/user_settings/ssh_keys#index')
|
||||
|
||||
post("/-/profile/keys")
|
||||
expect(response).to redirect_to('/-/user_settings/ssh_keys#create')
|
||||
|
||||
get("/-/profile/keys/1")
|
||||
expect(response).to redirect_to('/-/user_settings/ssh_keys#show')
|
||||
|
||||
delete("/-/profile/keys/1")
|
||||
expect(response).to redirect_to('/-/user_settings/ssh_keys#destroy')
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,11 @@ RSpec.describe 'search/show', feature_category: :global_search do
|
|||
let(:search_term) { nil }
|
||||
let(:user) { build(:user) }
|
||||
let(:search_service_presenter) do
|
||||
instance_double(SearchServicePresenter, without_count?: false, advanced_search_enabled?: false)
|
||||
instance_double(SearchServicePresenter,
|
||||
without_count?: false,
|
||||
advanced_search_enabled?: false,
|
||||
zoekt_enabled?: false
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
@ -58,7 +62,11 @@ RSpec.describe 'search/show', feature_category: :global_search do
|
|||
|
||||
context 'search with full count' do
|
||||
let(:search_service_presenter) do
|
||||
instance_double(SearchServicePresenter, without_count?: false, advanced_search_enabled?: false)
|
||||
instance_double(SearchServicePresenter,
|
||||
without_count?: false,
|
||||
advanced_search_enabled?: false,
|
||||
zoekt_enabled?: false
|
||||
)
|
||||
end
|
||||
|
||||
it 'renders meta tags for a group' do
|
||||
|
|
@ -81,7 +89,11 @@ RSpec.describe 'search/show', feature_category: :global_search do
|
|||
|
||||
context 'search without full count' do
|
||||
let(:search_service_presenter) do
|
||||
instance_double(SearchServicePresenter, without_count?: true, advanced_search_enabled?: false)
|
||||
instance_double(SearchServicePresenter,
|
||||
without_count?: true,
|
||||
advanced_search_enabled?: false,
|
||||
zoekt_enabled?: false
|
||||
)
|
||||
end
|
||||
|
||||
it 'renders meta tags for a group' do
|
||||
|
|
|
|||
Loading…
Reference in New Issue