Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-09-02 15:07:11 +00:00
parent cba5b2d7ea
commit 41c37d81e7
34 changed files with 494 additions and 390 deletions

View File

@ -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:

View File

@ -1 +1 @@
a70abfad8ef4d4d1cb4b5d6667b8df8ccd772f3d
a2ca345cd681ef39094623d8f4b6ed65996de57d

View File

@ -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

View File

@ -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',

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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>

View File

@ -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')"
>

View File

@ -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({

View File

@ -64,6 +64,7 @@ export const initWorkItemsRoot = ({ workItemType, workspaceType } = {}) => {
if (isGroup)
injectVueAppBreadcrumbs(router, WorkItemBreadcrumb, apolloProvider, {
workItemType: listWorkItemType,
epicsListPath,
});
apolloProvider.clients.defaultClient.cache.writeQuery({

View File

@ -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')

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -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).

View File

@ -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

View File

@ -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.

View File

@ -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).

View File

@ -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:
![Run application screenshot](img/java_start_application.png)
![Run application screenshot](img/java_start_application.png)
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**:
![Maven changes update UI](img/maven_changes.png)
![Maven changes update UI](img/maven_changes.png)
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...**:
![Edit configuration](img/java_edit_configuration.png)
![Edit configuration](img/java_edit_configuration.png)
1. In the configuration menu, select the icon in the **Environment Variables** field.
![Configuration menu](img/java_configuration_menu.png)
![Configuration menu](img/java_configuration_menu.png)
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`

View File

@ -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`.

View File

@ -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">

View File

@ -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

View File

@ -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);
});
});

View File

@ -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 },

View File

@ -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(() => {

View File

@ -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`);
});
});

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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