summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-15 21:14:36 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-15 21:14:36 +0000
commit885275c832d7c76b7290b38190a6cf31438d3898 (patch)
tree7d5de8a98dfa50003440c7e2a6c7e1504a926d90
parentf6b58d14904a1413a5442d13f361671e59ab3ded (diff)
downloadgitlab-ce-885275c832d7c76b7290b38190a6cf31438d3898.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab-ci.yml16
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/header_search/store/getters.js10
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue25
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue18
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue14
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue7
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue9
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql1
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_versions_list.vue5
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue2
-rw-r--r--app/helpers/search_helper.rb4
-rw-r--r--app/models/concerns/has_user_type.rb2
-rw-r--r--app/views/admin/application_settings/_realtime.html.haml4
-rw-r--r--app/views/devise/confirmations/new.html.haml5
-rw-r--r--app/views/projects/feature_flags/index.html.haml2
-rw-r--r--app/views/projects/pages/_pages_settings.html.haml2
-rw-r--r--app/views/registrations/welcome/show.html.haml3
-rw-r--r--config/feature_flags/development/cache_client_with_metrics.yml8
-rw-r--r--db/post_migrate/20230118144623_schedule_migration_for_remediation.rb11
-rw-r--r--db/post_migrate/20230214181633_finalize_ci_build_needs_big_int_conversion.rb8
-rw-r--r--db/post_migrate/20230220102212_swap_columns_ci_build_needs_big_int_conversion.rb57
-rw-r--r--db/post_migrate/20230309071242_delete_security_policy_bot_users.rb21
-rw-r--r--db/post_migrate/20230313150531_reschedule_migration_for_remediation.rb32
-rw-r--r--db/schema_migrations/202302201022121
-rw-r--r--db/schema_migrations/202303090712421
-rw-r--r--db/schema_migrations/202303131505311
-rw-r--r--db/structure.sql4
-rw-r--r--doc/.vale/gitlab/CodeblockFences.yml4
-rw-r--r--doc/.vale/gitlab/Substitutions.yml1
-rw-r--r--doc/administration/gitaly/troubleshooting.md2
-rw-r--r--doc/administration/pages/index.md2
-rw-r--r--doc/api/license.md32
-rw-r--r--doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md4
-rw-r--r--doc/architecture/blueprints/object_storage/index.md2
-rw-r--r--doc/architecture/blueprints/rate_limiting/index.md2
-rw-r--r--doc/ci/examples/index.md2
-rw-r--r--doc/ci/testing/test_coverage_visualization.md2
-rw-r--r--doc/development/backend/create_source_code_be/gitaly_touch_points.md2
-rw-r--r--doc/development/backend/create_source_code_be/index.md2
-rw-r--r--doc/development/documentation/styleguide/word_list.md9
-rw-r--r--doc/development/fips_compliance.md2
-rw-r--r--doc/development/gitaly.md8
-rw-r--r--doc/development/gitlab_shell/index.md4
-rw-r--r--doc/development/go_guide/go_upgrade.md2
-rw-r--r--doc/development/go_guide/index.md10
-rw-r--r--doc/development/secure_coding_guidelines.md32
-rw-r--r--doc/development/uploads/working_with_uploads.md2
-rw-r--r--doc/integration/advanced_search/elasticsearch.md4
-rw-r--r--doc/operations/feature_flags.md6
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md2
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md2
-rw-r--r--doc/user/packages/go_proxy/index.md2
-rw-r--r--doc/user/profile/img/saved_replies_dropdown_v15_10.pngbin0 -> 23623 bytes
-rw-r--r--doc/user/profile/saved_replies.md61
-rw-r--r--lib/api/files.rb14
-rw-r--r--lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb2
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json2
-rw-r--r--spec/frontend/header_search/store/getters_spec.js7
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js39
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js46
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js36
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js22
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js3
-rw-r--r--spec/frontend/packages_and_registries/shared/components/registry_list_spec.js17
-rw-r--r--spec/helpers/search_helper_spec.rb15
-rw-r--r--spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb12
-rw-r--r--spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb8
-rw-r--r--spec/migrations/20230214181633_finalize_ci_build_needs_big_int_conversion_spec.rb43
-rw-r--r--spec/migrations/20230220102212_swap_columns_ci_build_needs_big_int_conversion_spec.rb60
-rw-r--r--spec/migrations/20230309071242_delete_security_policy_bot_users_spec.rb24
-rw-r--r--spec/migrations/20230313150531_reschedule_migration_for_remediation_spec.rb31
-rw-r--r--spec/models/concerns/has_user_type_spec.rb2
-rw-r--r--spec/requests/api/files_spec.rb21
-rw-r--r--spec/requests/api/issues/get_group_issues_spec.rb30
-rw-r--r--spec/requests/api/issues/get_project_issues_spec.rb42
-rw-r--r--spec/requests/api/issues/issues_spec.rb60
-rw-r--r--spec/requests/api/issues/post_projects_issues_spec.rb90
-rw-r--r--spec/requests/api/issues/put_projects_issues_spec.rb62
-rw-r--r--spec/requests/api/pages/internal_access_spec.rb68
-rw-r--r--spec/requests/api/pages/pages_spec.rb12
-rw-r--r--spec/requests/api/pages/private_access_spec.rb68
-rw-r--r--spec/requests/api/pages/public_access_spec.rb68
-rw-r--r--spec/requests/api/pages_domains_spec.rb40
-rw-r--r--spec/spec_helper.rb10
-rw-r--r--yarn.lock8
87 files changed, 892 insertions, 551 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 79f99211bb1..c3087716b13 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -106,28 +106,28 @@ workflow:
# For tags, create a pipeline.
- if: '$CI_COMMIT_TAG'
variables:
- <<: *ruby2-variables
- PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_TAG tag pipeline'
+ <<: *ruby3-variables
+ PIPELINE_NAME: 'Ruby 3 $CI_COMMIT_TAG tag pipeline'
# If `$GITLAB_INTERNAL` isn't set, don't create a pipeline.
- if: '$GITLAB_INTERNAL == null'
when: never
# For stable, auto-deploy, and security branches, create a pipeline.
- if: '$CI_COMMIT_BRANCH =~ /^[\d-]+-stable(-ee)?$/'
variables:
- <<: *ruby2-variables
+ <<: *ruby3-variables
NOTIFY_PIPELINE_FAILURE_CHANNEL: "releases"
- PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline'
+ PIPELINE_NAME: 'Ruby 3 $CI_COMMIT_BRANCH branch pipeline'
CREATE_INCIDENT_FOR_PIPELINE_FAILURE: "true"
BROKEN_BRANCH_INCIDENTS_PROJECT: "gitlab-org/release/tasks"
BROKEN_BRANCH_INCIDENTS_PROJECT_TOKEN: "${BROKEN_STABLE_INCIDENTS_PROJECT_TOKEN}"
- if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/'
variables:
- <<: *ruby2-variables
- PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline'
+ <<: *ruby3-variables
+ PIPELINE_NAME: 'Ruby 3 $CI_COMMIT_BRANCH branch pipeline'
- if: '$CI_COMMIT_BRANCH =~ /^security\//'
variables:
- <<: *ruby2-variables
- PIPELINE_NAME: 'Ruby 2 $CI_COMMIT_BRANCH branch pipeline'
+ <<: *ruby3-variables
+ PIPELINE_NAME: 'Ruby 3 $CI_COMMIT_BRANCH branch pipeline'
variables:
PG_VERSION: "12"
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 2d5269488e5..97fadac1f9d 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-71dbaa115c10ae08292a7df74d3f8297ab38f208
+705e00092a936f0233fe16339aba3a1c65db36b0
diff --git a/app/assets/javascripts/header_search/store/getters.js b/app/assets/javascripts/header_search/store/getters.js
index 3da9d2cd961..3dec857930d 100644
--- a/app/assets/javascripts/header_search/store/getters.js
+++ b/app/assets/javascripts/header_search/store/getters.js
@@ -36,6 +36,10 @@ export const searchQuery = (state) => {
};
export const scopedIssuesPath = (state) => {
+ if (state.searchContext?.project?.id && !state.searchContext?.project_metadata?.issues_path) {
+ return false;
+ }
+
return (
state.searchContext?.project_metadata?.issues_path ||
state.searchContext?.group_metadata?.issues_path ||
@@ -54,7 +58,7 @@ export const scopedMRPath = (state) => {
export const defaultSearchOptions = (state, getters) => {
const userName = gon.current_username;
- return [
+ const issues = [
{
html_id: 'default-issues-assigned',
title: MSG_ISSUES_ASSIGNED_TO_ME,
@@ -65,6 +69,9 @@ export const defaultSearchOptions = (state, getters) => {
title: MSG_ISSUES_IVE_CREATED,
url: `${getters.scopedIssuesPath}/?author_username=${userName}`,
},
+ ];
+
+ const mergeRequests = [
{
html_id: 'default-mrs-assigned',
title: MSG_MR_ASSIGNED_TO_ME,
@@ -81,6 +88,7 @@ export const defaultSearchOptions = (state, getters) => {
url: `${getters.scopedMRPath}/?author_username=${userName}`,
},
];
+ return [...(getters.scopedIssuesPath ? issues : []), ...mergeRequests];
};
export const projectUrl = (state) => {
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
index ed7c9e7abe9..d91f314a86c 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
@@ -1,16 +1,9 @@
<script>
-import {
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
- GlTooltipDirective as GlTooltip,
-} from '@gitlab/ui';
+import { GlDropdown, GlDropdownItem, GlIcon, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
export default {
components: {
GlIcon,
- GlButton,
GlDropdown,
GlDropdownItem,
},
@@ -18,10 +11,6 @@ export default {
GlTooltip,
},
props: {
- isProjectsImportEnabled: {
- type: Boolean,
- required: true,
- },
isFinished: {
type: Boolean,
required: true,
@@ -46,7 +35,7 @@ export default {
<template>
<span class="gl-white-space-nowrap gl-inline-flex gl-align-items-center">
<gl-dropdown
- v-if="isProjectsImportEnabled && (isAvailableForImport || isFinished)"
+ v-if="isAvailableForImport || isFinished"
:text="isFinished ? __('Re-import with projects') : __('Import with projects')"
:disabled="isInvalid"
variant="confirm"
@@ -59,16 +48,6 @@ export default {
isFinished ? __('Re-import without projects') : __('Import without projects')
}}</gl-dropdown-item>
</gl-dropdown>
- <gl-button
- v-else-if="isAvailableForImport || isFinished"
- :disabled="isInvalid"
- variant="confirm"
- category="secondary"
- data-qa-selector="import_group_button"
- @click="$emit('import-group')"
- >
- {{ isFinished ? __('Re-import') : __('Import') }}
- </gl-button>
<gl-icon
v-if="isFinished"
v-gl-tooltip
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
index c9d1d1c56ee..2e6e7cddf8f 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
@@ -1,7 +1,6 @@
<script>
import {
GlAlert,
- GlButton,
GlDropdown,
GlDropdownItem,
GlEmptyState,
@@ -50,7 +49,6 @@ const DEFAULT_TD_CLASSES = 'gl-vertical-align-top!';
export default {
components: {
GlAlert,
- GlButton,
GlDropdown,
GlDropdownItem,
GlEmptyState,
@@ -165,10 +163,6 @@ export default {
],
computed: {
- isProjectsImportEnabled() {
- return Boolean(this.glFeatures.bulkImportProjects);
- },
-
groups() {
return this.bulkImportSourceGroups?.nodes ?? [];
},
@@ -707,11 +701,11 @@ export default {
</gl-sprintf>
</span>
<gl-dropdown
- v-if="isProjectsImportEnabled"
:text="s__('BulkImport|Import with projects')"
:disabled="!hasSelectedGroups"
variant="confirm"
category="primary"
+ data-testid="import-selected-groups-dropdown"
class="gl-ml-4"
split
@click="importSelectedGroups({ migrateProjects: true })"
@@ -720,15 +714,6 @@ export default {
{{ s__('BulkImport|Import without projects') }}
</gl-dropdown-item>
</gl-dropdown>
- <gl-button
- v-else
- category="primary"
- variant="confirm"
- class="gl-ml-4"
- :disabled="!hasSelectedGroups"
- @click="importSelectedGroups"
- >{{ s__('BulkImport|Import selected') }}</gl-button
- >
<span class="gl-ml-3">
<gl-icon name="information-o" :size="12" class="gl-text-blue-600" />
<gl-sprintf
@@ -804,7 +789,6 @@ export default {
</template>
<template #cell(actions)="{ item: group, index }">
<import-actions-cell
- :is-projects-import-enabled="isProjectsImportEnabled"
:is-finished="group.flags.isFinished"
:is-available-for-import="group.flags.isAvailableForImport"
:is-invalid="group.flags.isInvalid"
diff --git a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
index af06884bbb4..92d1a2ffc22 100644
--- a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
+++ b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
@@ -68,7 +68,7 @@ export default {
<div class="card card-slim gl-mt-5 gl-mb-0 gl-bg-gray-10">
<div class="card-header gl-px-5 gl-py-4 gl-bg-white">
<div
- class="card-title gl-relative gl-display-flex gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
+ class="card-title gl-relative gl-display-flex gl-flex-wrap gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
>
<gl-link
class="anchor gl-absolute gl-text-decoration-none"
@@ -82,6 +82,12 @@ export default {
<gl-icon name="merge-request" class="gl-ml-3 gl-mr-2 gl-text-gray-500" />
<span data-testid="count" class="gl-text-gray-500">{{ totalCount }}</span>
</template>
+ <p
+ v-if="hasClosingMergeRequest && !isFetchingMergeRequests"
+ class="gl-font-sm gl-font-weight-normal gl-flex-basis-full gl-mb-0 gl-text-gray-500"
+ >
+ {{ closingMergeRequestsText }}
+ </p>
</div>
</div>
<gl-loading-icon
@@ -110,11 +116,5 @@ export default {
</li>
</ul>
</div>
- <div
- v-if="hasClosingMergeRequest && !isFetchingMergeRequests"
- class="issue-closed-by-widget second-block gl-mt-3"
- >
- {{ closingMergeRequestsText }}
- </div>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
index f128e77da62..863d1c2629b 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
@@ -87,6 +87,9 @@ export default {
tags() {
return this.containerRepository?.tags?.nodes || [];
},
+ hideBulkDelete() {
+ return !(this.containerRepository?.canDelete || false);
+ },
tagsPageInfo() {
return this.containerRepository?.tags?.pageInfo;
},
@@ -98,9 +101,6 @@ export default {
sort: this.sort,
};
},
- showMultiDeleteButton() {
- return this.tags.some((tag) => tag.canDelete) && !this.isMobile;
- },
hasNoTags() {
return this.tags.length === 0;
},
@@ -186,6 +186,7 @@ export default {
/>
<template v-else>
<registry-list
+ :hidden-delete="hideBulkDelete"
:title="listTitle"
:pagination="tagsPageInfo"
:items="tags"
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue
index 38b601ac3ec..8e89128a382 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue
@@ -109,9 +109,6 @@ export default {
isInvalidTag() {
return !this.tag.digest;
},
- isDeleteDisabled() {
- return this.disabled || !this.tag.canDelete;
- },
},
};
</script>
@@ -179,16 +176,16 @@ export default {
</gl-sprintf>
</span>
</template>
- <template #right-action>
+ <template v-if="tag.canDelete" #right-action>
<gl-dropdown
- :disabled="isDeleteDisabled"
+ :disabled="disabled"
icon="ellipsis_v"
:text="$options.i18n.MORE_ACTIONS_TEXT"
:text-sr-only="true"
category="tertiary"
no-caret
right
- :class="{ 'gl-opacity-0 gl-pointer-events-none': isDeleteDisabled }"
+ :class="{ 'gl-opacity-0 gl-pointer-events-none': disabled }"
data-testid="additional-actions"
data-qa-selector="more_actions_menu"
>
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
index e57ac2a9efe..a0a80600603 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
@@ -12,6 +12,7 @@ query getContainerRepositoryTags(
containerRepository(id: $id) {
id
tagsCount
+ canDelete
tags(after: $after, before: $before, first: $first, last: $last, name: $name, sort: $sort) {
nodes {
digest
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_versions_list.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_versions_list.vue
index a06b2cadd6e..3d5ac528920 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_versions_list.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_versions_list.vue
@@ -122,11 +122,8 @@ export default {
@next-page="$emit('next-page')"
>
<template #default="{ first, item, isSelected, selectItem }">
- <!-- `first` prop is used to decide whether to show the top border
- for the first element. We want to show the top border only when
- user has permission to bulk delete versions. -->
<version-row
- :first="canDestroy && first"
+ :first="first"
:package-entity="item"
:selected="isSelected(item)"
@delete="setItemToBeDeleted(item)"
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
index 7485f8282ee..1c8f80972df 100644
--- a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
@@ -125,7 +125,7 @@ export default {
:select-item="selectItem"
:is-selected="isSelected"
:item="item"
- :first="index === 0"
+ :first="!hiddenDelete && index === 0"
></slot>
</div>
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index ca5436ff019..d62dc038388 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -204,7 +204,9 @@ module SearchHelper
if search_has_project?
hash[:project] = { id: @project.id, name: @project.name }
- hash[:project_metadata] = { issues_path: project_issues_path(@project), mr_path: project_merge_requests_path(@project) }
+ hash[:project_metadata] = { mr_path: project_merge_requests_path(@project) }
+ hash[:project_metadata][:issues_path] = project_issues_path(@project) if @project.feature_available?(:issues, current_user)
+
hash[:code_search] = search_scope.nil?
hash[:ref] = @ref if @ref && can?(current_user, :read_code, @project)
end
diff --git a/app/models/concerns/has_user_type.rb b/app/models/concerns/has_user_type.rb
index 752be378ab0..0b1c6780db8 100644
--- a/app/models/concerns/has_user_type.rb
+++ b/app/models/concerns/has_user_type.rb
@@ -14,6 +14,7 @@ module HasUserType
migration_bot: 7,
security_bot: 8,
automation_bot: 9,
+ security_policy_bot: 10, # Currently not in use. See https://gitlab.com/gitlab-org/gitlab/-/issues/384174
admin_bot: 11,
suggested_reviewers_bot: 12,
service_account: 13
@@ -27,6 +28,7 @@ module HasUserType
migration_bot
security_bot
automation_bot
+ security_policy_bot
admin_bot
suggested_reviewers_bot
service_account
diff --git a/app/views/admin/application_settings/_realtime.html.haml b/app/views/admin/application_settings/_realtime.html.haml
index 6a7ec05d206..2b8b023baea 100644
--- a/app/views/admin/application_settings/_realtime.html.haml
+++ b/app/views/admin/application_settings/_realtime.html.haml
@@ -1,4 +1,4 @@
-= form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-realtime-settings'), html: { class: 'fieldset-form' } do |f|
+= gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-realtime-settings'), html: { class: 'fieldset-form' } do |f|
= form_errors(@application_setting)
%fieldset
@@ -8,4 +8,4 @@
.form-text.text-muted
= _('Multiplier to apply to polling intervals. Decimal values are supported. Defaults to 1.')
- = f.submit _('Save changes'), class: "gl-button btn btn-confirm"
+ = f.submit _('Save changes'), pajamas_button: true
diff --git a/app/views/devise/confirmations/new.html.haml b/app/views/devise/confirmations/new.html.haml
index d3bd1d58d21..4b586b2f580 100644
--- a/app/views/devise/confirmations/new.html.haml
+++ b/app/views/devise/confirmations/new.html.haml
@@ -1,7 +1,7 @@
= render 'devise/shared/tab_single', tab_title: 'Resend confirmation instructions'
.login-box.gl-p-5
.login-body
- = form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
+ = gitlab_ui_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post, class: 'gl-show-field-errors' }) do |f|
.devise-errors
= render "devise/shared/error_messages", resource: resource
.form-group
@@ -13,7 +13,8 @@
= recaptcha_tags nonce: content_security_policy_nonce
.gl-mt-5
- = f.submit _("Resend"), class: 'gl-button btn btn-confirm'
+ = render Pajamas::ButtonComponent.new(block: true, type: :submit, variant: :confirm) do
+ = _("Resend")
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
diff --git a/app/views/projects/feature_flags/index.html.haml b/app/views/projects/feature_flags/index.html.haml
index 53fe30422ca..a6eaeacc61f 100644
--- a/app/views/projects/feature_flags/index.html.haml
+++ b/app/views/projects/feature_flags/index.html.haml
@@ -6,7 +6,7 @@
"error-state-svg-path" => image_path('illustrations/feature_flag.svg'),
"feature-flags-help-page-path" => help_page_path("operations/feature_flags"),
"feature-flags-client-libraries-help-page-path" => help_page_path("operations/feature_flags", anchor: "choose-a-client-library"),
- "feature-flags-client-example-help-page-path" => help_page_path("operations/feature_flags", anchor: "golang-application-example"),
+ "feature-flags-client-example-help-page-path" => help_page_path("operations/feature_flags", anchor: "go-application-example"),
"feature-flags-limit-exceeded" => @project.actual_limits.exceeded?(:project_feature_flags, @project.operations_feature_flags.count),
"feature-flags-limit" => @project.actual_limits.project_feature_flags,
"unleash-api-url" => (unleash_api_url(@project) if can?(current_user, :admin_feature_flag, @project)),
diff --git a/app/views/projects/pages/_pages_settings.html.haml b/app/views/projects/pages/_pages_settings.html.haml
index e60cdf754da..11e105d349d 100644
--- a/app/views/projects/pages/_pages_settings.html.haml
+++ b/app/views/projects/pages/_pages_settings.html.haml
@@ -27,4 +27,4 @@
= s_("GitLabPages|When enabled, a unique domain is generated to access pages.").html_safe
.gl-mt-3
- = f.submit s_('GitLabPages|Save changes'), class: 'btn btn-confirm gl-button'
+ = f.submit s_('GitLabPages|Save changes'), pajamas_button: true
diff --git a/app/views/registrations/welcome/show.html.haml b/app/views/registrations/welcome/show.html.haml
index f4e9a597fe2..2796f0c0a7e 100644
--- a/app/views/registrations/welcome/show.html.haml
+++ b/app/views/registrations/welcome/show.html.haml
@@ -38,4 +38,5 @@
- if partial_exists? "registrations/welcome/button"
= render "registrations/welcome/button"
- else
- = f.submit _('Get started!'), class: 'btn-confirm gl-button btn btn-block gl-mb-0 gl-p-3', data: { qa_selector: 'get_started_button' }
+ = render Pajamas::ButtonComponent.new(block: true, type: :submit, variant: :confirm, button_options: { class: 'gl-mb-0', data: { qa_selector: 'get_started_button' }}) do
+ = _('Get started!')
diff --git a/config/feature_flags/development/cache_client_with_metrics.yml b/config/feature_flags/development/cache_client_with_metrics.yml
deleted file mode 100644
index 433b9729df4..00000000000
--- a/config/feature_flags/development/cache_client_with_metrics.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cache_client_with_metrics
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111210
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/392622
-milestone: '15.10'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb b/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb
index af9b7d65a55..ed95ecfaad3 100644
--- a/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb
+++ b/db/post_migrate/20230118144623_schedule_migration_for_remediation.rb
@@ -9,17 +9,10 @@ class ScheduleMigrationForRemediation < Gitlab::Database::Migration[2.1]
BATCH_SIZE = 5000
def up
- queue_batched_background_migration(
- MIGRATION,
- :vulnerability_occurrences,
- :id,
- job_interval: DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- sub_batch_size: SUB_BATCH_SIZE
- )
+ # no-op as described in https://docs.gitlab.com/ee/development/database/batched_background_migrations.html
end
def down
- delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
+ # no-op as described in https://docs.gitlab.com/ee/development/database/batched_background_migrations.html
end
end
diff --git a/db/post_migrate/20230214181633_finalize_ci_build_needs_big_int_conversion.rb b/db/post_migrate/20230214181633_finalize_ci_build_needs_big_int_conversion.rb
index 1ac7b447457..63b6148df6b 100644
--- a/db/post_migrate/20230214181633_finalize_ci_build_needs_big_int_conversion.rb
+++ b/db/post_migrate/20230214181633_finalize_ci_build_needs_big_int_conversion.rb
@@ -8,6 +8,8 @@ class FinalizeCiBuildNeedsBigIntConversion < Gitlab::Database::Migration[2.1]
TABLE_NAME = 'ci_build_needs'
def up
+ return unless should_run?
+
ensure_batched_background_migration_is_finished(
job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
table_name: TABLE_NAME,
@@ -17,4 +19,10 @@ class FinalizeCiBuildNeedsBigIntConversion < Gitlab::Database::Migration[2.1]
end
def down; end
+
+ private
+
+ def should_run?
+ !Gitlab.jh? && (Gitlab.com? || Gitlab.dev_or_test_env?)
+ end
end
diff --git a/db/post_migrate/20230220102212_swap_columns_ci_build_needs_big_int_conversion.rb b/db/post_migrate/20230220102212_swap_columns_ci_build_needs_big_int_conversion.rb
new file mode 100644
index 00000000000..de98847fad4
--- /dev/null
+++ b/db/post_migrate/20230220102212_swap_columns_ci_build_needs_big_int_conversion.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+class SwapColumnsCiBuildNeedsBigIntConversion < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ TABLE_NAME = 'ci_build_needs'
+
+ def up
+ return unless should_run?
+
+ swap
+ end
+
+ def down
+ return unless should_run?
+
+ swap
+ end
+
+ private
+
+ def should_run?
+ !Gitlab.jh? && (Gitlab.com? || Gitlab.dev_or_test_env?)
+ end
+
+ def swap
+ add_concurrent_index TABLE_NAME, :id_convert_to_bigint, unique: true, name:
+ 'index_ci_build_needs_on_id_convert_to_bigint'
+
+ with_lock_retries(raise_on_exhaustion: true) do
+ execute "LOCK TABLE #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
+
+ id_name = quote_column_name(:id)
+ temp_name = quote_column_name('id_tmp')
+ id_convert_to_bigint_name = quote_column_name(:id_convert_to_bigint)
+
+ execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{id_name} TO #{temp_name}"
+ execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{id_convert_to_bigint_name} TO #{id_name}"
+ execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN #{temp_name} TO #{id_convert_to_bigint_name}"
+
+ function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(
+ TABLE_NAME, connection: Ci::ApplicationRecord.connection
+ ).name(
+ :id, :id_convert_to_bigint
+ )
+ execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
+
+ execute "ALTER SEQUENCE ci_build_needs_id_seq OWNED BY #{TABLE_NAME}.id"
+ change_column_default TABLE_NAME, :id, -> { "nextval('ci_build_needs_id_seq'::regclass)" }
+ change_column_default TABLE_NAME, :id_convert_to_bigint, 0
+
+ execute "ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT ci_build_needs_pkey CASCADE"
+ rename_index TABLE_NAME, 'index_ci_build_needs_on_id_convert_to_bigint', 'ci_build_needs_pkey'
+ execute "ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT ci_build_needs_pkey PRIMARY KEY USING INDEX ci_build_needs_pkey"
+ end
+ end
+end
diff --git a/db/post_migrate/20230309071242_delete_security_policy_bot_users.rb b/db/post_migrate/20230309071242_delete_security_policy_bot_users.rb
new file mode 100644
index 00000000000..0a9ace2574c
--- /dev/null
+++ b/db/post_migrate/20230309071242_delete_security_policy_bot_users.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class DeleteSecurityPolicyBotUsers < Gitlab::Database::Migration[2.1]
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ class User < MigrationRecord
+ self.table_name = 'users'
+
+ enum user_type: { security_policy_bot: 10 }
+ end
+
+ def up
+ User.where(user_type: :security_policy_bot).delete_all
+ end
+
+ def down
+ # no-op
+
+ # Deleted records can't be restored
+ end
+end
diff --git a/db/post_migrate/20230313150531_reschedule_migration_for_remediation.rb b/db/post_migrate/20230313150531_reschedule_migration_for_remediation.rb
new file mode 100644
index 00000000000..ebb6e53341f
--- /dev/null
+++ b/db/post_migrate/20230313150531_reschedule_migration_for_remediation.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+# rubocop: disable BackgroundMigration/MissingDictionaryFile
+
+class RescheduleMigrationForRemediation < Gitlab::Database::Migration[2.1]
+ MIGRATION = 'MigrateRemediationsForVulnerabilityFindings'
+ DELAY_INTERVAL = 2.minutes
+ SUB_BATCH_SIZE = 500
+ BATCH_SIZE = 5000
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
+
+ queue_batched_background_migration(
+ MIGRATION,
+ :vulnerability_occurrences,
+ :id,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(MIGRATION, :vulnerability_occurrences, :id, [])
+ end
+end
+# rubocop: enable BackgroundMigration/MissingDictionaryFile
diff --git a/db/schema_migrations/20230220102212 b/db/schema_migrations/20230220102212
new file mode 100644
index 00000000000..a4432c7b517
--- /dev/null
+++ b/db/schema_migrations/20230220102212
@@ -0,0 +1 @@
+7df50689f7e9311ee8e5bd2513f4361be0fceef3962344d2d16bf511132c7a33 \ No newline at end of file
diff --git a/db/schema_migrations/20230309071242 b/db/schema_migrations/20230309071242
new file mode 100644
index 00000000000..dd29a8006b1
--- /dev/null
+++ b/db/schema_migrations/20230309071242
@@ -0,0 +1 @@
+094eb5044e841050288c7362cc58c1b63ce4a349fe49a4c5ebee6b83a05feb56 \ No newline at end of file
diff --git a/db/schema_migrations/20230313150531 b/db/schema_migrations/20230313150531
new file mode 100644
index 00000000000..94625561f6b
--- /dev/null
+++ b/db/schema_migrations/20230313150531
@@ -0,0 +1 @@
+e2f19bbc322127e439fffc4c1e2718288538aa6cb2d50a5248f12470b1c9491e \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 49f713c691d..64b05803829 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -12896,13 +12896,13 @@ CREATE SEQUENCE chat_teams_id_seq
ALTER SEQUENCE chat_teams_id_seq OWNED BY chat_teams.id;
CREATE TABLE ci_build_needs (
- id integer NOT NULL,
+ id_convert_to_bigint integer DEFAULT 0 NOT NULL,
name text NOT NULL,
artifacts boolean DEFAULT true NOT NULL,
optional boolean DEFAULT false NOT NULL,
build_id bigint NOT NULL,
partition_id bigint DEFAULT 100 NOT NULL,
- id_convert_to_bigint bigint DEFAULT 0 NOT NULL
+ id bigint NOT NULL
);
CREATE SEQUENCE ci_build_needs_id_seq
diff --git a/doc/.vale/gitlab/CodeblockFences.yml b/doc/.vale/gitlab/CodeblockFences.yml
index 9d5efe7f60a..27159f7e72e 100644
--- a/doc/.vale/gitlab/CodeblockFences.yml
+++ b/doc/.vale/gitlab/CodeblockFences.yml
@@ -5,9 +5,9 @@
#
# For a list of all options, see https://vale.sh/docs/topics/styles/
extends: existence
-message: "Instead of '%s' for the code block, use yaml, ruby, plaintext, markdown, javascript, shell, golang, python, dockerfile, or typescript."
+message: "Instead of '%s' for the code block, use yaml, ruby, plaintext, markdown, javascript, shell, go, python, dockerfile, or typescript."
link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#code-blocks
level: error
scope: raw
raw:
- - '\`\`\`(yml|rb|text|md|bash|sh\n|js\n|go\n|py\n|docker\n|ts)'
+ - '\`\`\`(yml|rb|text|md|bash|sh\n|js\n|golang\n|py\n|docker\n|ts)'
diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml
index 675abc6ef6d..225e4e74880 100644
--- a/doc/.vale/gitlab/Substitutions.yml
+++ b/doc/.vale/gitlab/Substitutions.yml
@@ -23,6 +23,7 @@ swap:
params: parameters
pg: PostgreSQL
'postgres$': PostgreSQL
+ golang: Go
raketask: Rake task
raketasks: Rake tasks
rspec: RSpec
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index 52d307790be..596348a3177 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -720,7 +720,7 @@ This error occurs when `praefect['database_port']` or `praefect['database_direct
## Profiling Gitaly
-Gitaly exposes several of the Golang built-in performance profiling tools on the Prometheus listen port. For example, if Prometheus is listening
+Gitaly exposes several of the Go built-in performance profiling tools on the Prometheus listen port. For example, if Prometheus is listening
on port `9236` of the GitLab server:
- Get a list of running `goroutines` and their backtraces:
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 609862dba83..efeb19a8d5e 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -863,7 +863,7 @@ Incorrect configuration of these values may result in intermittent
or persistent errors, or the Pages Daemon serving old content.
NOTE:
-Expiry, interval and timeout flags use [Golang's duration formatting](https://pkg.go.dev/time#ParseDuration).
+Expiry, interval and timeout flags use [Go duration formatting](https://pkg.go.dev/time#ParseDuration).
A duration string is a possibly signed sequence of decimal numbers,
each with optional fraction and a unit suffix, such as `300ms`, `1.5h` or `2h45m`.
Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`.
diff --git a/doc/api/license.md b/doc/api/license.md
index ca9d9cf386d..39da6af30d4 100644
--- a/doc/api/license.md
+++ b/doc/api/license.md
@@ -233,3 +233,35 @@ Returns:
- `204 No Content` if the license is successfully deleted.
- `403 Forbidden` if the current user in not permitted to delete the license.
- `404 Not Found` if the license to delete could not be found.
+
+## Trigger recalculation of billable users
+
+```plaintext
+PUT /license/:id/refresh_billable_users
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer | yes | ID of the GitLab license. |
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/license/:id/refresh_billable_users"
+```
+
+Example response:
+
+```json
+{
+ "success": true
+}
+```
+
+Returns:
+
+- `202 Accepted` if the request to refresh billable users is successfully initiated.
+- `403 Forbidden` if the current user in not permitted to refresh billable users for the license.
+- `404 Not Found` if the license could not be found.
+
+| Attribute | Type | Description |
+|:-----------------------------|:--------------|:------------------------------------------|
+| `success` | boolean | Whether the request succeeded or not. |
diff --git a/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md b/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md
index c5bd2440b0c..82d1596bc90 100644
--- a/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md
+++ b/doc/architecture/blueprints/gitlab_observability_backend/metrics/index.md
@@ -93,9 +93,9 @@ Additionally, since we intend to ingest data via Prometheus `remote_write` API,
We also need to make sure to avoid writing a lot of small writes into Clickhouse, therefore it’d be prudent to batch data before writing it into Clickhouse.
-We must also make sure ingestion remains decoupled with `Storage` so as to reduce undue dependence on a given storage implementation. While we do intend to use Clickhouse as our backing storage for any foreseeable future, this ensures we do not tie ourselves in into Clickhouse too much should future business requirements warrant the usage of a different backend/technology. A good way to implement this in Golang would be our implementations adhering to a standard interface, the following for example:
+We must also make sure ingestion remains decoupled with `Storage` so as to reduce undue dependence on a given storage implementation. While we do intend to use Clickhouse as our backing storage for any foreseeable future, this ensures we do not tie ourselves in into Clickhouse too much should future business requirements warrant the usage of a different backend/technology. A good way to implement this in Go would be our implementations adhering to a standard interface, the following for example:
-```golang
+```go
type Storage interface {
Read(
ctx context.Context,
diff --git a/doc/architecture/blueprints/object_storage/index.md b/doc/architecture/blueprints/object_storage/index.md
index 4a8eeaf86a9..6718705a7c8 100644
--- a/doc/architecture/blueprints/object_storage/index.md
+++ b/doc/architecture/blueprints/object_storage/index.md
@@ -53,7 +53,7 @@ This has led to increased complexity across the board, from development
[we no longer recommend](../../../administration/nfs.md) to our
users and is no longer in use on GitLab.com.
- Understanding all the moving parts and the flow is extremely
- complicated: we have CarrierWave, Fog, Golang S3/Azure SDKs, all
+ complicated: we have CarrierWave, Fog, Go S3/Azure SDKs, all
being used, and that complicates testing as well.
- Fog and CarrierWave are not maintained to the level of the native
SDKs (for example, AWS S3 SDK), so we have to maintain or monkey
diff --git a/doc/architecture/blueprints/rate_limiting/index.md b/doc/architecture/blueprints/rate_limiting/index.md
index b466a54e922..92364040962 100644
--- a/doc/architecture/blueprints/rate_limiting/index.md
+++ b/doc/architecture/blueprints/rate_limiting/index.md
@@ -375,7 +375,7 @@ hierarchy. Choosing a proper solution will require a thoughtful research.
- Implementing a separate Go library which uses the same backend (for example, Redis) for rate limiting.
1. **SDK for Satellite Services (Owning Team)**
- - Build Golang SDK.
+ - Build Go SDK.
- Create examples showcasing usage of the new rate limits SDK.
1. **Team fan out for Satellite Services (Stage Groups)**
diff --git a/doc/ci/examples/index.md b/doc/ci/examples/index.md
index 6738c55b6fa..b05c872d624 100644
--- a/doc/ci/examples/index.md
+++ b/doc/ci/examples/index.md
@@ -76,7 +76,7 @@ choose one of these templates:
- [dotNET Core (`dotNET-Core.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml)
- [Elixir (`Elixir.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml)
- [Flutter (`Flutter.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml)
-- [Golang (`Go.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml)
+- [Go (`Go.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml)
- [Gradle (`Gradle.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml)
- [Grails (`Grails.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml)
- [iOS with fastlane (`iOS-Fastlane.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/iOS-Fastlane.gitlab-ci.yml)
diff --git a/doc/ci/testing/test_coverage_visualization.md b/doc/ci/testing/test_coverage_visualization.md
index a54b1f2a610..1b29304d1af 100644
--- a/doc/ci/testing/test_coverage_visualization.md
+++ b/doc/ci/testing/test_coverage_visualization.md
@@ -33,7 +33,7 @@ This format was originally developed for Java, but most coverage analysis framew
for other languages have plugins to add support for it, like:
- [simplecov-cobertura](https://rubygems.org/gems/simplecov-cobertura) (Ruby)
-- [gocover-cobertura](https://github.com/boumenot/gocover-cobertura) (Golang)
+- [gocover-cobertura](https://github.com/boumenot/gocover-cobertura) (Go)
Other coverage analysis frameworks support the format out of the box, for example:
diff --git a/doc/development/backend/create_source_code_be/gitaly_touch_points.md b/doc/development/backend/create_source_code_be/gitaly_touch_points.md
index 6ee2c7f0e51..c689af2f150 100644
--- a/doc/development/backend/create_source_code_be/gitaly_touch_points.md
+++ b/doc/development/backend/create_source_code_be/gitaly_touch_points.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## RPCs
-Gitaly is a wrapper around the `git` binary, running in a [Gitaly Cluster](../../../administration/gitaly/index.md). It provides managed access to the file system housing the `git` repositories, via Golang Remote Procedure Calls (RPCs). Other functions are access optimization, caching, and a form of pagination against the file system.
+Gitaly is a wrapper around the `git` binary, running in a [Gitaly Cluster](../../../administration/gitaly/index.md). It provides managed access to the file system housing the `git` repositories, using Go Remote Procedure Calls (RPCs). Other functions are access optimization, caching, and a form of pagination against the file system.
The comprehensive [Beginner's guide to Gitaly contributions](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/beginners_guide.md) is focused on making updates to Gitaly, and offers many insights into how to understand the Gitaly code.
diff --git a/doc/development/backend/create_source_code_be/index.md b/doc/development/backend/create_source_code_be/index.md
index ba0ed2a2867..d894a14b006 100644
--- a/doc/development/backend/create_source_code_be/index.md
+++ b/doc/development/backend/create_source_code_be/index.md
@@ -39,7 +39,7 @@ To learn about the reasoning behind our creation of `gitlab-sshd`, read the blog
### Gitaly touch points
-Gitaly is a Golang RPC service which handles all the `git` calls made by GitLab.
+Gitaly is a Go RPC service which handles all the `git` calls made by GitLab.
GitLab is not exposed directly, and all traffic comes through Create: Source Code.
For more information, read [Gitaly touch points](gitaly_touch_points.md).
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index d6096b32795..1ea95367d01 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -741,7 +741,7 @@ Do not use **limitations**. Use **known issues** instead.
## log in, log on
-Do not use **log in** or **log on**. Use [sign in](#sign-in) instead. If the user interface has **Log in**, you can use it.
+Do not use **log in** or **log on**. Use [sign in](#sign-in-sign-in) instead. If the user interface has **Log in**, you can use it.
## logged-in user, logged in user
@@ -1154,14 +1154,17 @@ Use **setup** as a noun, and **set up** as a verb. For example:
- Your remote office setup is amazing.
- To set up your remote office correctly, consider the ergonomics of your work area.
-## sign in
+## sign in, sign-in
-Use **sign in** or **sign in to**.
+Use **sign in** or **sign in to** as a verb to describe the action of signing in.
Do not use **sign on** or **sign into**, or **log on**, **log in**, or **log into**.
If the user interface has different words, use those.
+You can use **sign-in** as a noun or adjective. For example, **sign-in page** or
+**sign-in restrictions**.
+
You can use **single sign-on**.
## sign up
diff --git a/doc/development/fips_compliance.md b/doc/development/fips_compliance.md
index 45668b6be0c..f0634107ba5 100644
--- a/doc/development/fips_compliance.md
+++ b/doc/development/fips_compliance.md
@@ -446,7 +446,7 @@ irb(main):001:0> require 'openssl'; OpenSSL.fips_mode
### Go
-Google maintains a [`dev.boringcrypto` branch](https://github.com/golang/go/tree/dev.boringcrypto) in the Golang compiler
+Google maintains a [`dev.boringcrypto` branch](https://github.com/golang/go/tree/dev.boringcrypto) in the Go compiler
that makes it possible to statically link BoringSSL, a FIPS-validated module forked from OpenSSL.
However, BoringSSL is not intended for public use.
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index e7d04a6677e..addab512f89 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -257,13 +257,13 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
1. Create a package scoped flag name:
- ```golang
+ ```go
var findAllTagsFeatureFlag = "go-find-all-tags"
```
1. Create a switch in the code using the `featureflag` package:
- ```golang
+ ```go
if featureflag.IsEnabled(ctx, findAllTagsFeatureFlag) {
// go implementation
} else {
@@ -273,7 +273,7 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
1. Create Prometheus metrics:
- ```golang
+ ```go
var findAllTagsRequests = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "gitaly_find_all_tags_requests_total",
@@ -297,7 +297,7 @@ Here are the steps to gate a new feature in Gitaly behind a feature flag.
1. Set headers in tests:
- ```golang
+ ```go
import (
"google.golang.org/grpc/metadata"
diff --git a/doc/development/gitlab_shell/index.md b/doc/development/gitlab_shell/index.md
index 9dc8d8e01c5..3a1af0fc9e9 100644
--- a/doc/development/gitlab_shell/index.md
+++ b/doc/development/gitlab_shell/index.md
@@ -21,8 +21,8 @@ Ruby to build and test, but not to run.
GitLab Shell runs on `port 22` on an Omnibus installation. To use a regular SSH
service, configure it on an alternative port.
-Download and install the current version of Go from [golang.org](https://go.dev/dl/).
-We follow the [Golang Release Policy](https://golang.org/doc/devel/release.html#policy)
+Download and install the [current version of Go](https://go.dev/dl/).
+We follow the [Go Release Policy](https://go.dev/doc/devel/release#policy)
and support:
- The current stable version.
diff --git a/doc/development/go_guide/go_upgrade.md b/doc/development/go_guide/go_upgrade.md
index b3ec0a15c37..f71fe7b8dac 100644
--- a/doc/development/go_guide/go_upgrade.md
+++ b/doc/development/go_guide/go_upgrade.md
@@ -26,7 +26,7 @@ by Distribution:
## Supporting multiple Go versions
-Individual Golang projects need to support multiple Go versions because:
+Individual Go projects need to support multiple Go versions because:
- When a new version of Go is released, we should start integrating it into the CI pipelines to verify compatibility with the new compiler.
- We must support the [official Omnibus GitLab Go version](#updating-go-version), which may be behind the latest minor release.
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index b1e37ddbde8..6092a05afff 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -216,7 +216,7 @@ When comparing expected and actual values in tests, use
and others to improve readability when comparing structs, errors,
large portions of text, or JSON documents:
-```golang
+```go
type TestData struct {
// ...
}
@@ -291,7 +291,7 @@ easier to debug.
For example:
-```golang
+```go
// Wrap the error
return nil, fmt.Errorf("get cache %s: %w", f.Name, err)
@@ -462,7 +462,7 @@ allocations.
**Don't:**
-```golang
+```go
var s2 []string
for _, val := range s1 {
s2 = append(s2, val)
@@ -471,7 +471,7 @@ for _, val := range s1 {
**Do:**
-```golang
+```go
s2 := make([]string, 0, len(s1))
for _, val := range s1 {
s2 = append(s2, val)
@@ -494,7 +494,7 @@ If the scanner report is small, less than 35 lines, then feel free to [inline th
The [go-cmp](https://github.com/google/go-cmp) package should be used when comparing large structs in tests. It makes it possible to output a specific diff where the two structs differ, rather than seeing the whole of both structs printed out in the test logs. Here is a small example:
-```golang
+```go
package main
import (
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index d41f1d76994..4f644dd018e 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -542,11 +542,11 @@ print(p.join('log', '/etc/passwd', ''))
# renders the path to "/etc/passwd", which is not what we expect!
```
-#### Golang
+#### Go
-Golang has similar behavior with [`path.Clean`](https://pkg.go.dev/path#example-Clean). Remember that with many file systems, using `../../../../` traverses up to the root directory. Any remaining `../` are ignored. This example may give an attacker access to `/etc/passwd`:
+Go has similar behavior with [`path.Clean`](https://pkg.go.dev/path#example-Clean). Remember that with many file systems, using `../../../../` traverses up to the root directory. Any remaining `../` are ignored. This example may give an attacker access to `/etc/passwd`:
-```golang
+```go
path.Clean("/../../etc/passwd")
// renders the path to "etc/passwd"; the file path is relative to whatever the current directory is
path.Clean("../../etc/passwd")
@@ -601,7 +601,7 @@ Go has built-in protections that usually prevent an attacker from successfully i
Consider the following example:
-```golang
+```go
package main
import (
@@ -620,7 +620,7 @@ This echoes `"1; cat /etc/passwd"`.
**Do not** use `sh`, as it bypasses internal protections:
-```golang
+```go
out, _ = exec.Command("sh", "-c", "echo 1 | cat /etc/passwd").Output()
```
@@ -646,15 +646,15 @@ And the following cipher suites (according to the [RFC 8446](https://datatracker
- `TLS_AES_128_GCM_SHA256`
- `TLS_AES_256_GCM_SHA384`
-*Note*: **Golang** does [not support](https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L676) all cipher suites with TLS 1.3.
+*Note*: **Go** does [not support](https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L676) all cipher suites with TLS 1.3.
##### Implementation examples
##### TLS 1.3
-For TLS 1.3, **Golang** only supports [3 cipher suites](https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L676), as such we only need to set the TLS version:
+For TLS 1.3, **Go** only supports [3 cipher suites](https://github.com/golang/go/blob/go1.17/src/crypto/tls/cipher_suites.go#L676), as such we only need to set the TLS version:
-```golang
+```go
cfg := &tls.Config{
MinVersion: tls.VersionTLS13,
}
@@ -678,9 +678,9 @@ response = GitLab::HTTP.perform_request(Net::HTTP::Get, 'https://gitlab.com', ss
##### TLS 1.2
-**Golang** does support multiple cipher suites that we do not want to use with TLS 1.2. We need to explicitly list authorized ciphers:
+**Go** does support multiple cipher suites that we do not want to use with TLS 1.2. We need to explicitly list authorized ciphers:
-```golang
+```go
func secureCipherSuites() []uint16 {
return []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
@@ -692,7 +692,7 @@ func secureCipherSuites() []uint16 {
And then use `secureCipherSuites()` in `tls.Config`:
-```golang
+```go
tls.Config{
(...),
CipherSuites: secureCipherSuites(),
@@ -920,7 +920,7 @@ end
#### Go
-```golang
+```go
// unzip INSECURELY extracts source zip file to destination.
func unzip(src, dest string) error {
r, err := zip.OpenReader(src)
@@ -1016,7 +1016,7 @@ end
You are encouraged to use the secure archive utilities provided by [LabSec](https://gitlab.com/gitlab-com/gl-security/appsec/labsec) which will handle Zip Slip and other types of vulnerabilities for you. The LabSec utilities are also context aware which makes it possible to cancel or timeout extractions:
-```golang
+```go
package main
import "gitlab-com/gl-security/appsec/labsec/archive/zip"
@@ -1041,7 +1041,7 @@ func main() {
In case the LabSec utilities do not fit your needs, here is an example for extracting a zip file with protection against Zip Slip attacks:
-```golang
+```go
// unzip extracts source zip file to destination with protection against Zip Slip attacks.
func unzip(src, dest string) error {
r, err := zip.OpenReader(src)
@@ -1118,7 +1118,7 @@ end
#### Go
-```golang
+```go
// printZipContents INSECURELY prints contents of files in a zip file.
func printZipContents(src string) error {
r, err := zip.OpenReader(src)
@@ -1186,7 +1186,7 @@ You are encouraged to use the secure archive utilities provided by [LabSec](http
In case the LabSec utilities do not fit your needs, here is an example for extracting a zip file with protection against symlink attacks:
-```golang
+```go
// printZipContents prints contents of files in a zip file with protection against symlink attacks.
func printZipContents(src string) error {
r, err := zip.OpenReader(src)
diff --git a/doc/development/uploads/working_with_uploads.md b/doc/development/uploads/working_with_uploads.md
index 6955f9c31cd..5575297ad6b 100644
--- a/doc/development/uploads/working_with_uploads.md
+++ b/doc/development/uploads/working_with_uploads.md
@@ -95,7 +95,7 @@ They consist of:
Example:
-```golang
+```go
u.route("PUT", apiProjectPattern+`packages/nuget/`, mimeMultipartUploader),
```
diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md
index 0b97bfd945a..389c79a281c 100644
--- a/doc/integration/advanced_search/elasticsearch.md
+++ b/doc/integration/advanced_search/elasticsearch.md
@@ -227,8 +227,8 @@ The following Elasticsearch settings are available:
| `AWS Secret Access Key` | The AWS secret access key. |
| `Maximum file size indexed` | See [the explanation in instance limits.](../../administration/instance_limits.md#maximum-file-size-indexed). |
| `Maximum field length` | See [the explanation in instance limits.](../../administration/instance_limits.md#maximum-field-length). |
-| `Maximum bulk request size (MiB)` | Used by the GitLab Ruby and Golang-based indexer processes. This setting indicates how much data must be collected (and stored in memory) in a given indexing process before submitting the payload to the Elasticsearch Bulk API. For the GitLab Golang-based indexer, you should use this setting with `Bulk request concurrency`. `Maximum bulk request size (MiB)` must accommodate the resource constraints of both the Elasticsearch hosts and the hosts running the GitLab Golang-based indexer from either the `gitlab-rake` command or the Sidekiq tasks. |
-| `Bulk request concurrency` | The Bulk request concurrency indicates how many of the GitLab Golang-based indexer processes (or threads) can run in parallel to collect data to subsequently submit to the Elasticsearch Bulk API. This increases indexing performance, but fills the Elasticsearch bulk requests queue faster. This setting should be used together with the Maximum bulk request size setting (see above) and needs to accommodate the resource constraints of both the Elasticsearch hosts and the hosts running the GitLab Golang-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
+| `Maximum bulk request size (MiB)` | Used by the GitLab Ruby and Go-based indexer processes. This setting indicates how much data must be collected (and stored in memory) in a given indexing process before submitting the payload to the Elasticsearch Bulk API. For the GitLab Go-based indexer, you should use this setting with `Bulk request concurrency`. `Maximum bulk request size (MiB)` must accommodate the resource constraints of both the Elasticsearch hosts and the hosts running the GitLab Go-based indexer from either the `gitlab-rake` command or the Sidekiq tasks. |
+| `Bulk request concurrency` | The Bulk request concurrency indicates how many of the GitLab Go-based indexer processes (or threads) can run in parallel to collect data to subsequently submit to the Elasticsearch Bulk API. This increases indexing performance, but fills the Elasticsearch bulk requests queue faster. This setting should be used together with the Maximum bulk request size setting (see above) and needs to accommodate the resource constraints of both the Elasticsearch hosts and the hosts running the GitLab Go-based indexer either from the `gitlab-rake` command or the Sidekiq tasks. |
| `Client request timeout` | Elasticsearch HTTP client request timeout value in seconds. `0` means using the system default timeout value, which depends on the libraries that GitLab application is built upon. |
WARNING:
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 8c7033f318d..968649e94b2 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -297,11 +297,11 @@ For API content, see:
- [Feature flags API](../api/feature_flags.md)
- [Feature flag user lists API](../api/feature_flag_user_lists.md)
-### Golang application example
+### Go application example
-Here's an example of how to integrate feature flags in a Golang application:
+Here's an example of how to integrate feature flags in a Go application:
-```golang
+```go
package main
import (
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index eb00764f002..4731e09474c 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -40,7 +40,7 @@ You can use the following fuzzing engines to test the specified languages.
| Language | Fuzzing Engine | Example |
|---------------------------------------------|------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|
| C/C++ | [libFuzzer](https://llvm.org/docs/LibFuzzer.html) | [c-cpp-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/c-cpp-fuzzing-example) |
-| GoLang | [go-fuzz (libFuzzer support)](https://github.com/dvyukov/go-fuzz) | [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example) |
+| Go | [go-fuzz (libFuzzer support)](https://github.com/dvyukov/go-fuzz) | [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example) |
| Swift | [libFuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.md) | [swift-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/swift-fuzzing-example) |
| Rust | [cargo-fuzz (libFuzzer support)](https://github.com/rust-fuzz/cargo-fuzz) | [rust-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example) |
| Java | [Javafuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/javafuzz) (recommended) | [javafuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/javafuzz-fuzzing-example) |
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
index 7a991d384ac..9419451fd5d 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -281,7 +281,7 @@ Here are some other options you can use to reduce the Container Registry storage
If you see this error message, check the regex patterns to ensure they are valid.
-GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in the cleanup policy. You can test them with the [regex101 regex tester](https://regex101.com/) using the Golang flavor.
+GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in the cleanup policy. You can test them with the [regex101 regex tester](https://regex101.com/) using the `Golang` flavor.
View some common [regex pattern examples](#regex-pattern-examples).
### The cleanup policy doesn't delete any tags
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index 1a089cd82be..f0e10d73d08 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -74,7 +74,7 @@ go env -w GOPROXY='https://gitlab.example.com/api/v4/projects/1234/packages/go,h
With this configuration, Go fetches dependencies in this order:
1. Go attempts to fetch from the project-specific Go proxy.
-1. Go attempts to fetch from [proxy.golang.org](https://proxy.golang.org).
+1. Go attempts to fetch from [`proxy.golang.org`](https://proxy.golang.org).
1. Go fetches directly with version control system operations (like `git clone`,
`svn checkout`, and so on).
diff --git a/doc/user/profile/img/saved_replies_dropdown_v15_10.png b/doc/user/profile/img/saved_replies_dropdown_v15_10.png
new file mode 100644
index 00000000000..50313f71f4a
--- /dev/null
+++ b/doc/user/profile/img/saved_replies_dropdown_v15_10.png
Binary files differ
diff --git a/doc/user/profile/saved_replies.md b/doc/user/profile/saved_replies.md
new file mode 100644
index 00000000000..302daceb31d
--- /dev/null
+++ b/doc/user/profile/saved_replies.md
@@ -0,0 +1,61 @@
+---
+stage: Create
+group: Code Review
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+type: howto
+---
+
+# Saved replies **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352956) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `saved_replies`. Disabled by default.
+
+With saved replies, create and reuse text for any text area in:
+
+- Merge requests, including diffs.
+- Issues, including design management comments.
+- Epics.
+- Work items.
+
+Saved replies can be small, like approving a merge request and unassigning yourself from it,
+or large, like chunks of boilerplate text you use frequently:
+
+![Saved replies dropdown list](img/saved_replies_dropdown_v15_10.png)
+
+## Use saved replies in a text area
+
+To include the text of a saved reply in your comment:
+
+1. In the editor toolbar for your comment, select **Saved replies** (**{symlink}**).
+1. Select your desired saved reply.
+
+## Create saved replies
+
+To create a saved reply for future use:
+
+1. On the top bar, in the upper-right corner, select your avatar.
+1. From the dropdown list, select **Preferences**.
+1. On the left sidebar, select **Saved replies** (**{symlink}**).
+1. Provide a **Name** for your saved reply.
+1. Enter the **Content** of your reply. You can use any formatting you use in
+ other GitLab text areas.
+1. Select **Save**, and the page reloads with your saved reply shown.
+
+## View your saved replies
+
+To go to your saved replies:
+
+1. On the top bar, in the upper-right corner, select your avatar.
+1. From the dropdown list, select **Preferences**.
+1. On the left sidebar, select **Saved replies** (**{symlink}**).
+1. Scroll to **My saved replies**.
+
+## Edit or delete saved replies
+
+To edit or delete a previously saved reply:
+
+1. On the top bar, in the upper-right corner, select your avatar.
+1. From the dropdown list, select **Preferences**.
+1. On the left sidebar, select **Saved replies** (**{symlink}**).
+1. Scroll to **My saved replies**, and identify the saved reply you want to edit.
+1. To edit, select **Edit** (**{pencil}**).
+1. To delete, select **Delete** (**{remove}**), then select **Delete** again from the modal window.
diff --git a/lib/api/files.rb b/lib/api/files.rb
index 06f3b55b742..1850413caa6 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -57,15 +57,11 @@ module API
end
def cache_client
- if Feature.enabled?(:cache_client_with_metrics, user_project)
- Gitlab::Cache::Client.build_with_metadata(
- cache_identifier: 'API::Files#content_sha',
- feature_category: :source_code_management,
- backing_resource: :gitaly
- )
- else
- Rails.cache
- end
+ Gitlab::Cache::Client.build_with_metadata(
+ cache_identifier: 'API::Files#content_sha',
+ feature_category: :source_code_management,
+ backing_resource: :gitaly
+ )
end
def fetch_blame_range(blame_params)
diff --git a/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb b/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb
index 7a2f4dab742..9eadef96db6 100644
--- a/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb
+++ b/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings.rb
@@ -150,7 +150,7 @@ module Gitlab
return [] unless parsed_metadata['remediations']
parsed_metadata['remediations'].filter_map do |remediation|
- next unless remediation
+ next unless remediation && remediation['diff'].present?
remediation.merge('checksum' => DiffFile.checksum(remediation['diff']))
end.compact.uniq
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 9fc511d0d17..c3123b0c1e1 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7732,9 +7732,6 @@ msgstr ""
msgid "BulkImport|Import is finished. Pick another name for re-import"
msgstr ""
-msgid "BulkImport|Import selected"
-msgstr ""
-
msgid "BulkImport|Import with projects"
msgstr ""
diff --git a/package.json b/package.json
index 32c436fce74..5f2c81e591d 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/fonts": "^1.2.0",
"@gitlab/svgs": "3.24.0",
- "@gitlab/ui": "56.4.0",
+ "@gitlab/ui": "56.4.1",
"@gitlab/visual-review-tools": "1.7.3",
"@gitlab/web-ide": "0.0.1-dev-20230223005157",
"@mattiasbuelens/web-streams-adapter": "^0.1.0",
diff --git a/spec/frontend/header_search/store/getters_spec.js b/spec/frontend/header_search/store/getters_spec.js
index a1d9481b5cc..7a7a00178f1 100644
--- a/spec/frontend/header_search/store/getters_spec.js
+++ b/spec/frontend/header_search/store/getters_spec.js
@@ -241,6 +241,13 @@ describe('Header Search Store Getters', () => {
MOCK_DEFAULT_SEARCH_OPTIONS,
);
});
+
+ it('returns the correct array if issues path is false', () => {
+ mockGetters.scopedIssuesPath = undefined;
+ expect(getters.defaultSearchOptions(state, mockGetters)).toStrictEqual(
+ MOCK_DEFAULT_SEARCH_OPTIONS.slice(2, MOCK_DEFAULT_SEARCH_OPTIONS.length),
+ );
+ });
});
describe('scopedSearchOptions', () => {
diff --git a/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js
index e813c9eab11..1a52485f779 100644
--- a/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_actions_cell_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlIcon, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlDropdown, GlIcon, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import ImportActionsCell from '~/import_entities/import_groups/components/import_actions_cell.vue';
@@ -8,7 +8,6 @@ describe('import actions cell', () => {
const createComponent = (props) => {
wrapper = shallowMount(ImportActionsCell, {
propsData: {
- isProjectsImportEnabled: false,
isFinished: false,
isAvailableForImport: false,
isInvalid: false,
@@ -22,10 +21,10 @@ describe('import actions cell', () => {
createComponent({ isAvailableForImport: true });
});
- it('renders import button', () => {
- const button = wrapper.findComponent(GlButton);
- expect(button.exists()).toBe(true);
- expect(button.text()).toBe('Import');
+ it('renders import dropdown', () => {
+ const dropdown = wrapper.findComponent(GlDropdown);
+ expect(dropdown.exists()).toBe(true);
+ expect(dropdown.props('text')).toBe('Import with projects');
});
it('does not render icon with a hint', () => {
@@ -38,10 +37,10 @@ describe('import actions cell', () => {
createComponent({ isAvailableForImport: false, isFinished: true });
});
- it('renders re-import button', () => {
- const button = wrapper.findComponent(GlButton);
- expect(button.exists()).toBe(true);
- expect(button.text()).toBe('Re-import');
+ it('renders re-import dropdown', () => {
+ const dropdown = wrapper.findComponent(GlDropdown);
+ expect(dropdown.exists()).toBe(true);
+ expect(dropdown.props('text')).toBe('Re-import with projects');
});
it('renders icon with a hint', () => {
@@ -53,25 +52,25 @@ describe('import actions cell', () => {
});
});
- it('does not render import button when group is not available for import', () => {
+ it('does not render import dropdown when group is not available for import', () => {
createComponent({ isAvailableForImport: false });
- const button = wrapper.findComponent(GlButton);
- expect(button.exists()).toBe(false);
+ const dropdown = wrapper.findComponent(GlDropdown);
+ expect(dropdown.exists()).toBe(false);
});
- it('renders import button as disabled when group is invalid', () => {
+ it('renders import dropdown as disabled when group is invalid', () => {
createComponent({ isInvalid: true, isAvailableForImport: true });
- const button = wrapper.findComponent(GlButton);
- expect(button.props().disabled).toBe(true);
+ const dropdown = wrapper.findComponent(GlDropdown);
+ expect(dropdown.props().disabled).toBe(true);
});
it('emits import-group event when import button is clicked', () => {
createComponent({ isAvailableForImport: true });
- const button = wrapper.findComponent(GlButton);
- button.vm.$emit('click');
+ const dropdown = wrapper.findComponent(GlDropdown);
+ dropdown.vm.$emit('click');
expect(wrapper.emitted('import-group')).toHaveLength(1);
});
@@ -81,10 +80,10 @@ describe('import actions cell', () => {
${false} | ${'Import'}
${true} | ${'Re-import'}
`(
- 'when import projects is enabled, group is available for import and finish status is $status',
+ 'group is available for import and finish status is $isFinished',
({ isFinished, expectedAction }) => {
beforeEach(() => {
- createComponent({ isProjectsImportEnabled: true, isAvailableForImport: true, isFinished });
+ createComponent({ isAvailableForImport: true, isFinished });
});
it('render import dropdown', () => {
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
index f664f4a4fe7..205218fdabd 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
@@ -49,12 +49,12 @@ describe('import table', () => {
},
};
- const findImportSelectedButton = () =>
- wrapper.findAll('button').wrappers.find((w) => w.text() === 'Import selected');
const findImportSelectedDropdown = () =>
- wrapper.findAll('.gl-dropdown').wrappers.find((w) => w.text().includes('Import with projects'));
- const findImportButtons = () =>
- wrapper.findAll('button').wrappers.filter((w) => w.text() === 'Import');
+ wrapper.find('[data-testid="import-selected-groups-dropdown"]');
+ const findRowImportDropdownAtIndex = (idx) =>
+ wrapper.findAll('tbody td button').wrappers.filter((w) => w.text() === 'Import with projects')[
+ idx
+ ];
const findPaginationDropdown = () => wrapper.find('[data-testid="page-size"]');
const findTargetNamespaceDropdown = (rowWrapper) =>
rowWrapper.find('[data-testid="target-namespace-selector"]');
@@ -70,12 +70,7 @@ describe('import table', () => {
const findRowCheckbox = (idx) => wrapper.findAll('tbody td input[type=checkbox]').at(idx);
const selectRow = (idx) => findRowCheckbox(idx).setChecked(true);
- const createComponent = ({
- bulkImportSourceGroups,
- importGroups,
- defaultTargetNamespace,
- glFeatures = {},
- }) => {
+ const createComponent = ({ bulkImportSourceGroups, importGroups, defaultTargetNamespace }) => {
apolloProvider = createMockApollo(
[
[
@@ -104,9 +99,6 @@ describe('import table', () => {
directives: {
GlTooltip: createMockDirective('gl-tooltip'),
},
- provide: {
- glFeatures,
- },
apolloProvider,
});
};
@@ -130,7 +122,7 @@ describe('import table', () => {
expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
- it('does not renders loading icon when request is completed', async () => {
+ it('does not render loading icon when request is completed', async () => {
createComponent({
bulkImportSourceGroups: () => [],
});
@@ -241,12 +233,13 @@ describe('import table', () => {
await waitForPromises();
- await findImportButtons()[0].trigger('click');
+ await findRowImportDropdownAtIndex(0).trigger('click');
expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
mutation: importGroupsMutation,
variables: {
importRequests: [
{
+ migrateProjects: true,
newName: FAKE_GROUP.lastImportTarget.newName,
sourceGroupId: FAKE_GROUP.id,
targetNamespace: AVAILABLE_NAMESPACES[0].fullPath,
@@ -269,7 +262,7 @@ describe('import table', () => {
});
await waitForPromises();
- await findImportButtons()[0].trigger('click');
+ await findRowImportDropdownAtIndex(0).trigger('click');
await waitForPromises();
expect(createAlert).toHaveBeenCalledWith(
@@ -294,7 +287,7 @@ describe('import table', () => {
});
await waitForPromises();
- await findImportButtons()[0].trigger('click');
+ await findRowImportDropdownAtIndex(0).trigger('click');
await waitForPromises();
expect(createAlert).not.toHaveBeenCalled();
@@ -472,7 +465,7 @@ describe('import table', () => {
});
await waitForPromises();
- expect(findImportSelectedButton().props().disabled).toBe(true);
+ expect(findImportSelectedDropdown().props().disabled).toBe(true);
});
it('import selected button is enabled when groups were selected for import', async () => {
@@ -487,7 +480,7 @@ describe('import table', () => {
await selectRow(0);
- expect(findImportSelectedButton().props().disabled).toBe(false);
+ expect(findImportSelectedDropdown().props().disabled).toBe(false);
});
it('does not allow selecting already started groups', async () => {
@@ -505,7 +498,7 @@ describe('import table', () => {
await selectRow(0);
await nextTick();
- expect(findImportSelectedButton().props().disabled).toBe(true);
+ expect(findImportSelectedDropdown().props().disabled).toBe(true);
});
it('does not allow selecting groups with validation errors', async () => {
@@ -530,10 +523,10 @@ describe('import table', () => {
await selectRow(0);
await nextTick();
- expect(findImportSelectedButton().props().disabled).toBe(true);
+ expect(findImportSelectedDropdown().props().disabled).toBe(true);
});
- it('invokes importGroups mutation when import selected button is clicked', async () => {
+ it('invokes importGroups mutation when import selected dropdown is clicked', async () => {
const NEW_GROUPS = [
generateFakeEntry({ id: 1, status: STATUSES.NONE }),
generateFakeEntry({ id: 2, status: STATUSES.NONE }),
@@ -554,7 +547,7 @@ describe('import table', () => {
await selectRow(1);
await nextTick();
- await findImportSelectedButton().trigger('click');
+ await findImportSelectedDropdown().find('button').trigger('click');
expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
mutation: importGroupsMutation,
@@ -675,7 +668,7 @@ describe('import table', () => {
});
});
- describe('when import projects is enabled', () => {
+ describe('importing projects', () => {
const NEW_GROUPS = [
generateFakeEntry({ id: 1, status: STATUSES.NONE }),
generateFakeEntry({ id: 2, status: STATUSES.NONE }),
@@ -689,9 +682,6 @@ describe('import table', () => {
pageInfo: FAKE_PAGE_INFO,
versionValidation: FAKE_VERSION_VALIDATION,
}),
- glFeatures: {
- bulkImportProjects: true,
- },
});
jest.spyOn(apolloProvider.defaultClient, 'mutate');
return waitForPromises();
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
index 2d08cba5f7c..bfefe46c09b 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
@@ -278,26 +278,30 @@ describe('tags list row', () => {
textSrOnly: true,
category: 'tertiary',
right: true,
+ disabled: false,
});
});
- it.each`
- canDelete | digest | disabled | buttonDisabled
- ${true} | ${null} | ${true} | ${true}
- ${false} | ${'foo'} | ${true} | ${true}
- ${false} | ${null} | ${true} | ${true}
- ${true} | ${'foo'} | ${true} | ${true}
- ${true} | ${'foo'} | ${false} | ${false}
- `(
- 'is $visible that is visible when canDelete is $canDelete and digest is $digest and disabled is $disabled',
- ({ canDelete, digest, disabled, buttonDisabled }) => {
- mountComponent({ ...defaultProps, tag: { ...tag, canDelete, digest }, disabled });
+ it('has the correct classes', () => {
+ mountComponent();
- expect(findAdditionalActionsMenu().props('disabled')).toBe(buttonDisabled);
- expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(buttonDisabled);
- expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(buttonDisabled);
- },
- );
+ expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(false);
+ expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(false);
+ });
+
+ it('is not rendered when tag.canDelete is false', () => {
+ mountComponent({ ...defaultProps, tag: { ...tag, canDelete: false } });
+
+ expect(findAdditionalActionsMenu().exists()).toBe(false);
+ });
+
+ it('is hidden when disabled prop is set to true', () => {
+ mountComponent({ ...defaultProps, disabled: true });
+
+ expect(findAdditionalActionsMenu().props('disabled')).toBe(true);
+ expect(findAdditionalActionsMenu().classes('gl-opacity-0')).toBe(true);
+ expect(findAdditionalActionsMenu().classes('gl-pointer-events-none')).toBe(true);
+ });
describe('delete button', () => {
it('exists and has the correct attrs', () => {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index 8501cbc2bae..09d0370efbf 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -69,10 +69,10 @@ describe('Tags List', () => {
});
describe('registry list', () => {
- beforeEach(() => {
+ beforeEach(async () => {
mountComponent();
fireFirstSortUpdate();
- return waitForApolloRequestRender();
+ await waitForApolloRequestRender();
});
it('has a persisted search', () => {
@@ -94,6 +94,7 @@ describe('Tags List', () => {
pagination: tagsPageInfo,
items: tags,
idProperty: 'name',
+ hiddenDelete: false,
});
});
@@ -182,12 +183,23 @@ describe('Tags List', () => {
});
});
+ describe('when user does not have permission to delete list rows', () => {
+ it('sets registry list hiddenDelete prop to true', async () => {
+ resolver = jest.fn().mockResolvedValue(imageTagsMock({ canDelete: false }));
+ mountComponent();
+ fireFirstSortUpdate();
+ await waitForApolloRequestRender();
+
+ expect(findRegistryList().props('hiddenDelete')).toBe(true);
+ });
+ });
+
describe('when the list of tags is empty', () => {
- beforeEach(() => {
- resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
+ beforeEach(async () => {
+ resolver = jest.fn().mockResolvedValue(imageTagsMock({ nodes: [] }));
mountComponent();
fireFirstSortUpdate();
- return waitForApolloRequestRender();
+ await waitForApolloRequestRender();
});
it('does not show the loader', () => {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index e5b99f15e8c..cd54b856c97 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
@@ -177,11 +177,12 @@ export const tagsMock = [
},
];
-export const imageTagsMock = (nodes = tagsMock) => ({
+export const imageTagsMock = ({ nodes = tagsMock, canDelete = true } = {}) => ({
data: {
containerRepository: {
id: containerRepositoryMock.id,
tagsCount: nodes.length,
+ canDelete,
tags: {
nodes,
pageInfo: { ...tagsPageInfo },
diff --git a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
index b821352922f..a4e0d267023 100644
--- a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
@@ -107,10 +107,21 @@ describe('Registry List', () => {
expect(findDeleteSelected().text()).toBe(component.i18n.deleteSelected);
});
- it('is hidden when hiddenDelete is true', () => {
- mountComponent({ propsData: { ...defaultPropsData, hiddenDelete: true } });
+ describe('when hiddenDelete is true', () => {
+ beforeEach(() => {
+ mountComponent({ propsData: { ...defaultPropsData, hiddenDelete: true } });
+ });
+
+ it('is hidden', () => {
+ expect(findDeleteSelected().exists()).toBe(false);
+ });
- expect(findDeleteSelected().exists()).toBe(false);
+ it('populates the first slot prop correctly', async () => {
+ expect(findScopedSlots().at(0).exists()).toBe(true);
+
+ // it's the first slot
+ expect(findScopedSlotFirstValue(0).text()).toBe('false');
+ });
});
it('is disabled when isLoading is true', () => {
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index c7afe0bf391..ba703914049 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -829,6 +829,21 @@ RSpec.describe SearchHelper, feature_category: :global_search do
expect(header_search_context[:project_metadata]).to eq(project_metadata)
end
+ context 'feature issues is not available' do
+ let(:feature_available) { false }
+ let(:project_metadata) { { mr_path: project_merge_requests_path(project) } }
+
+ before do
+ allow(project).to receive(:feature_available?).and_call_original
+ allow(project).to receive(:feature_available?).with(:issues, current_user).and_return(feature_available)
+ end
+
+ it 'adds the :project and :project-metadata correctly to hash' do
+ expect(header_search_context[:project]).to eq({ id: project.id, name: project.name })
+ expect(header_search_context[:project_metadata]).to eq(project_metadata)
+ end
+ end
+
context 'with scope' do
let(:scope) { 'issues' }
diff --git a/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb b/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb
index 84259505683..b75c0e61b19 100644
--- a/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_remediations_for_vulnerability_findings_spec.rb
@@ -57,6 +57,18 @@ RSpec.describe Gitlab::BackgroundMigration::MigrateRemediationsForVulnerabilityF
end
end
+ context 'with remediation with empty string as the diff key' do
+ let!(:finding) do
+ create_finding!(project1.id, scanner1.id, { remediations: [{ summary: 'summary', diff: '' }] })
+ end
+
+ it 'does not create any remediation' do
+ expect(Gitlab::AppLogger).not_to receive(:error)
+
+ expect { perform_migration }.not_to change { vulnerability_remediations.count }
+ end
+ end
+
context 'with remediation equals to an array of duplicated elements' do
let!(:finding) do
create_finding!(project1.id, scanner1.id, { remediations: [remediation_hash, remediation_hash] })
diff --git a/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb b/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb
index d22aeeaa254..f6d0f32b87c 100644
--- a/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb
+++ b/spec/migrations/20230118144623_schedule_migration_for_remediation_spec.rb
@@ -10,13 +10,7 @@ RSpec.describe ScheduleMigrationForRemediation, :migration, feature_category: :v
it 'schedules a batched background migration' do
migrate!
- expect(migration).to have_scheduled_batched_migration(
- table_name: :vulnerability_occurrences,
- column_name: :id,
- interval: described_class::DELAY_INTERVAL,
- batch_size: described_class::BATCH_SIZE,
- sub_batch_size: described_class::SUB_BATCH_SIZE
- )
+ expect(migration).not_to have_scheduled_batched_migration
end
end
diff --git a/spec/migrations/20230214181633_finalize_ci_build_needs_big_int_conversion_spec.rb b/spec/migrations/20230214181633_finalize_ci_build_needs_big_int_conversion_spec.rb
new file mode 100644
index 00000000000..638fe2a12d5
--- /dev/null
+++ b/spec/migrations/20230214181633_finalize_ci_build_needs_big_int_conversion_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe FinalizeCiBuildNeedsBigIntConversion, migration: :gitlab_ci, feature_category: :continuous_integration do
+ describe '#up' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:dot_com, :dev_or_test, :jh, :expectation) do
+ true | true | true | :not_to
+ true | false | true | :not_to
+ false | true | true | :not_to
+ false | false | true | :not_to
+ true | true | false | :to
+ true | false | false | :to
+ false | true | false | :to
+ false | false | false | :not_to
+ end
+
+ with_them do
+ it 'ensures the migration is completed for GitLab.com, dev, or test' do
+ allow(Gitlab).to receive(:com?).and_return(dot_com)
+ allow(Gitlab).to receive(:dev_or_test_env?).and_return(dev_or_test)
+ allow(Gitlab).to receive(:jh?).and_return(jh)
+
+ migration_arguments = {
+ job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
+ table_name: 'ci_build_needs',
+ column_name: 'id',
+ job_arguments: [['id'], ['id_convert_to_bigint']]
+ }
+
+ expect(described_class).send(
+ expectation,
+ ensure_batched_background_migration_is_finished_for(migration_arguments)
+ )
+
+ migrate!
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20230220102212_swap_columns_ci_build_needs_big_int_conversion_spec.rb b/spec/migrations/20230220102212_swap_columns_ci_build_needs_big_int_conversion_spec.rb
new file mode 100644
index 00000000000..1c21047c0c3
--- /dev/null
+++ b/spec/migrations/20230220102212_swap_columns_ci_build_needs_big_int_conversion_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe SwapColumnsCiBuildNeedsBigIntConversion, feature_category: :continuous_integration do
+ describe '#up' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:dot_com, :dev_or_test, :jh, :swap) do
+ true | true | true | false
+ true | false | true | false
+ false | true | true | false
+ false | false | true | false
+ true | true | false | true
+ true | false | false | true
+ false | true | false | true
+ false | false | false | false
+ end
+
+ with_them do
+ before do
+ connection = described_class.new.connection
+ connection.execute('ALTER TABLE ci_build_needs ALTER COLUMN id TYPE integer')
+ connection.execute('ALTER TABLE ci_build_needs ALTER COLUMN id_convert_to_bigint TYPE bigint')
+ end
+
+ it 'swaps the integer and bigint columns for GitLab.com, dev, or test' do
+ allow(Gitlab).to receive(:com?).and_return(dot_com)
+ allow(Gitlab).to receive(:dev_or_test_env?).and_return(dev_or_test)
+ allow(Gitlab).to receive(:jh?).and_return(jh)
+
+ ci_build_needs = table(:ci_build_needs)
+
+ disable_migrations_output do
+ reversible_migration do |migration|
+ migration.before -> {
+ ci_build_needs.reset_column_information
+
+ expect(ci_build_needs.columns.find { |c| c.name == 'id' }.sql_type).to eq('integer')
+ expect(ci_build_needs.columns.find { |c| c.name == 'id_convert_to_bigint' }.sql_type).to eq('bigint')
+ }
+
+ migration.after -> {
+ ci_build_needs.reset_column_information
+
+ if swap
+ expect(ci_build_needs.columns.find { |c| c.name == 'id' }.sql_type).to eq('bigint')
+ expect(ci_build_needs.columns.find { |c| c.name == 'id_convert_to_bigint' }.sql_type).to eq('integer')
+ else
+ expect(ci_build_needs.columns.find { |c| c.name == 'id' }.sql_type).to eq('integer')
+ expect(ci_build_needs.columns.find { |c| c.name == 'id_convert_to_bigint' }.sql_type).to eq('bigint')
+ end
+ }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20230309071242_delete_security_policy_bot_users_spec.rb b/spec/migrations/20230309071242_delete_security_policy_bot_users_spec.rb
new file mode 100644
index 00000000000..4dd44cad158
--- /dev/null
+++ b/spec/migrations/20230309071242_delete_security_policy_bot_users_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe DeleteSecurityPolicyBotUsers, feature_category: :security_policy_management do
+ let(:users) { table(:users) }
+
+ before do
+ users.create!(user_type: 10, projects_limit: 0, email: 'security_policy_bot@example.com')
+ users.create!(user_type: 1, projects_limit: 0, email: 'support_bot@example.com')
+ users.create!(projects_limit: 0, email: 'human@example.com')
+ end
+
+ describe '#up' do
+ it 'deletes security_policy_bot users' do
+ expect { migrate! }.to change { users.count }.by(-1)
+
+ expect(users.where(user_type: 10).count).to eq(0)
+ expect(users.where(user_type: 1).count).to eq(1)
+ expect(users.where(user_type: nil).count).to eq(1)
+ end
+ end
+end
diff --git a/spec/migrations/20230313150531_reschedule_migration_for_remediation_spec.rb b/spec/migrations/20230313150531_reschedule_migration_for_remediation_spec.rb
new file mode 100644
index 00000000000..00f0836285b
--- /dev/null
+++ b/spec/migrations/20230313150531_reschedule_migration_for_remediation_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe RescheduleMigrationForRemediation, :migration, feature_category: :vulnerability_management do
+ let(:migration) { described_class::MIGRATION }
+
+ describe '#up' do
+ it 'schedules a batched background migration' do
+ migrate!
+
+ expect(migration).to have_scheduled_batched_migration(
+ table_name: :vulnerability_occurrences,
+ column_name: :id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ end
+ end
+
+ describe '#down' do
+ it 'deletes all batched migration records' do
+ migrate!
+ schema_migrate_down!
+
+ expect(migration).not_to have_scheduled_batched_migration
+ end
+ end
+end
diff --git a/spec/models/concerns/has_user_type_spec.rb b/spec/models/concerns/has_user_type_spec.rb
index 87dacc71ca3..03d2c267098 100644
--- a/spec/models/concerns/has_user_type_spec.rb
+++ b/spec/models/concerns/has_user_type_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe User, feature_category: :system_access do
specify 'types consistency checks', :aggregate_failures do
expect(described_class::USER_TYPES.keys)
.to match_array(%w[human ghost alert_bot project_bot support_bot service_user security_bot visual_review_bot
- migration_bot automation_bot admin_bot suggested_reviewers_bot service_account])
+ migration_bot automation_bot security_policy_bot admin_bot suggested_reviewers_bot service_account])
expect(described_class::USER_TYPES).to include(*described_class::BOT_USER_TYPES)
expect(described_class::USER_TYPES).to include(*described_class::NON_INTERNAL_USER_TYPES)
expect(described_class::USER_TYPES).to include(*described_class::INTERNAL_USER_TYPES)
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index c9341934ec9..ed84e3e5f48 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -157,27 +157,6 @@ RSpec.describe API::Files, feature_category: :source_code_management do
head api(route(file_path), current_user, **options), params: params
end
- context 'when feature flag "cache_client_with_metrics" is disabled' do
- before do
- stub_feature_flags(cache_client_with_metrics: false)
- end
-
- it 'caches sha256 of the content', :use_clean_rails_redis_caching do
- head api(route(file_path), current_user, **options), params: params
-
- expect(Gitlab::Cache::Client).not_to receive(:build_with_metadata)
-
- expect(Rails.cache.fetch("blob_content_sha256:#{project.full_path}:#{response.headers['X-Gitlab-Blob-Id']}"))
- .to eq(content_sha256)
-
- expect_next_instance_of(Gitlab::Git::Blob) do |instance|
- expect(instance).not_to receive(:load_all_data!)
- end
-
- head api(route(file_path), current_user, **options), params: params
- end
- end
-
it 'returns file by commit sha' do
# This file is deleted on HEAD
file_path = 'files%2Fjs%2Fcommit%2Ejs%2Ecoffee'
diff --git a/spec/requests/api/issues/get_group_issues_spec.rb b/spec/requests/api/issues/get_group_issues_spec.rb
index 0641c2135c1..eaa3c46d0ca 100644
--- a/spec/requests/api/issues/get_group_issues_spec.rb
+++ b/spec/requests/api/issues/get_group_issues_spec.rb
@@ -74,7 +74,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let(:base_url) { "/groups/#{group.id}/issues" }
shared_examples 'group issues statistics' do
- it 'returns issues statistics' do
+ it 'returns issues statistics', :aggregate_failures do
get api("/groups/#{group.id}/issues_statistics", user), params: params
expect(response).to have_gitlab_http_status(:ok)
@@ -346,7 +346,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
group_project.add_reporter(user)
end
- it 'exposes known attributes' do
+ it 'exposes known attributes', :aggregate_failures do
get api(base_url, admin)
expect(response).to have_gitlab_http_status(:ok)
@@ -355,7 +355,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
it 'returns all group issues (including opened and closed)' do
- get api(base_url, admin)
+ get api(base_url, admin, admin_mode: true)
expect_paginated_array_response([group_closed_issue.id, group_confidential_issue.id, group_issue.id])
end
@@ -385,7 +385,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
it 'returns group confidential issues for admin' do
- get api(base_url, admin), params: { state: :opened }
+ get api(base_url, admin, admin_mode: true), params: { state: :opened }
expect_paginated_array_response([group_confidential_issue.id, group_issue.id])
end
@@ -403,7 +403,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'labels parameter' do
- it 'returns an array of labeled group issues' do
+ it 'returns an array of labeled group issues', :aggregate_failures do
get api(base_url, user), params: { labels: group_label.title }
expect_paginated_array_response(group_issue.id)
@@ -486,7 +486,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'returns an array of issues found by iids' do
+ it 'returns an array of issues found by iids', :aggregate_failures do
get api(base_url, user), params: { iids: [group_issue.iid] }
expect_paginated_array_response(group_issue.id)
@@ -505,14 +505,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect_paginated_array_response([])
end
- it 'returns an array of group issues with any label' do
+ it 'returns an array of group issues with any label', :aggregate_failures do
get api(base_url, user), params: { labels: IssuableFinder::Params::FILTER_ANY }
expect_paginated_array_response(group_issue.id)
expect(json_response.first['id']).to eq(group_issue.id)
end
- it 'returns an array of group issues with any label with labels param as array' do
+ it 'returns an array of group issues with any label with labels param as array', :aggregate_failures do
get api(base_url, user), params: { labels: [IssuableFinder::Params::FILTER_ANY] }
expect_paginated_array_response(group_issue.id)
@@ -555,7 +555,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect_paginated_array_response(group_closed_issue.id)
end
- it 'returns an array of issues with no milestone' do
+ it 'returns an array of issues with no milestone', :aggregate_failures do
get api(base_url, user), params: { milestone: no_milestone_title }
expect(response).to have_gitlab_http_status(:ok)
@@ -688,28 +688,28 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:issue2) { create(:issue, author: user2, project: group_project, created_at: 2.days.ago) }
let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: group_project, created_at: 1.day.ago) }
- it 'returns issues with by assignee_username' do
+ it 'returns issues with by assignee_username', :aggregate_failures do
get api(base_url, user), params: { assignee_username: [assignee.username], scope: 'all' }
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
expect_paginated_array_response([issue3.id, group_confidential_issue.id])
end
- it 'returns issues by assignee_username as string' do
+ it 'returns issues by assignee_username as string', :aggregate_failures do
get api(base_url, user), params: { assignee_username: assignee.username, scope: 'all' }
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
expect_paginated_array_response([issue3.id, group_confidential_issue.id])
end
- it 'returns error when multiple assignees are passed' do
+ it 'returns error when multiple assignees are passed', :aggregate_failures do
get api(base_url, user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response["error"]).to include("allows one value, but found 2")
end
- it 'returns error when assignee_username and assignee_id are passed together' do
+ it 'returns error when assignee_username and assignee_id are passed together', :aggregate_failures do
get api(base_url, user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -719,7 +719,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe "#to_reference" do
- it 'exposes reference path in context of group' do
+ it 'exposes reference path in context of group', :aggregate_failures do
get api(base_url, user)
expect(json_response.first['references']['short']).to eq("##{group_closed_issue.iid}")
@@ -735,7 +735,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
group_closed_issue.reload
end
- it 'exposes reference path in context of parent group' do
+ it 'exposes reference path in context of parent group', :aggregate_failures do
get api("/groups/#{parent_group.id}/issues")
expect(json_response.first['references']['short']).to eq("##{group_closed_issue.iid}")
diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb
index 6fc3903103b..915b8fff75e 100644
--- a/spec/requests/api/issues/get_project_issues_spec.rb
+++ b/spec/requests/api/issues/get_project_issues_spec.rb
@@ -99,7 +99,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
shared_examples 'project issues statistics' do
- it 'returns project issues statistics' do
+ it 'returns project issues statistics', :aggregate_failures do
get api("/projects/#{project.id}/issues_statistics", current_user), params: params
expect(response).to have_gitlab_http_status(:ok)
@@ -317,7 +317,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
it 'returns project confidential issues for admin' do
- get api("#{base_url}/issues", admin)
+ get api("#{base_url}/issues", admin, admin_mode: true)
expect_paginated_array_response([issue.id, confidential_issue.id, closed_issue.id])
end
@@ -526,7 +526,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect_paginated_array_response([closed_issue.id, confidential_issue.id, issue.id])
end
- it 'exposes known attributes' do
+ it 'exposes known attributes', :aggregate_failures do
get api("#{base_url}/issues", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -607,28 +607,28 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:issue2) { create(:issue, author: user2, project: project, created_at: 2.days.ago) }
let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: project, created_at: 1.day.ago) }
- it 'returns issues by assignee_username' do
+ it 'returns issues by assignee_username', :aggregate_failures do
get api("/issues", user), params: { assignee_username: [assignee.username], scope: 'all' }
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
expect_paginated_array_response([confidential_issue.id, issue3.id])
end
- it 'returns issues by assignee_username as string' do
+ it 'returns issues by assignee_username as string', :aggregate_failures do
get api("/issues", user), params: { assignee_username: assignee.username, scope: 'all' }
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
expect_paginated_array_response([confidential_issue.id, issue3.id])
end
- it 'returns error when multiple assignees are passed' do
+ it 'returns error when multiple assignees are passed', :aggregate_failures do
get api("/issues", user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response["error"]).to include("allows one value, but found 2")
end
- it 'returns error when assignee_username and assignee_id are passed together' do
+ it 'returns error when assignee_username and assignee_id are passed together', :aggregate_failures do
get api("/issues", user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -646,7 +646,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'exposes known attributes' do
+ it 'exposes known attributes', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -686,7 +686,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'exposes the closed_at attribute' do
+ it 'exposes the closed_at attribute', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{closed_issue.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -694,7 +694,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'links exposure' do
- it 'exposes related resources full URIs' do
+ it 'exposes related resources full URIs', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue.iid}", user)
links = json_response['_links']
@@ -706,7 +706,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'returns a project issue by internal id' do
+ it 'returns a project issue by internal id', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -738,7 +738,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(response).to have_gitlab_http_status(:not_found)
end
- it 'returns confidential issue for project members' do
+ it 'returns confidential issue for project members', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -746,7 +746,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['iid']).to eq(confidential_issue.iid)
end
- it 'returns confidential issue for author' do
+ it 'returns confidential issue for author', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", author)
expect(response).to have_gitlab_http_status(:ok)
@@ -754,7 +754,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['iid']).to eq(confidential_issue.iid)
end
- it 'returns confidential issue for assignee' do
+ it 'returns confidential issue for assignee', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", assignee)
expect(response).to have_gitlab_http_status(:ok)
@@ -762,8 +762,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['iid']).to eq(confidential_issue.iid)
end
- it 'returns confidential issue for admin' do
- get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin)
+ it 'returns confidential issue for admin', :aggregate_failures do
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq(confidential_issue.title)
@@ -829,7 +829,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:related_mr) { create_referencing_mr(user, project, issue) }
context 'when unauthenticated' do
- it 'return list of referenced merge requests from issue' do
+ it 'return list of referenced merge requests from issue', :aggregate_failures do
get_related_merge_requests(project.id, issue.iid)
expect_paginated_array_response(related_mr.id)
@@ -898,8 +898,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'exposes known attributes' do
- get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", admin)
+ it 'exposes known attributes', :aggregate_failures do
+ get api("/projects/#{project.id}/issues/#{issue.iid}/user_agent_detail", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['user_agent']).to eq(user_agent_detail.user_agent)
@@ -936,7 +936,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
)
end
- it 'returns a full list of participants' do
+ it 'returns a full list of participants', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue.iid}/participants", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -945,7 +945,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when user cannot see a confidential note' do
- it 'returns a limited list of participants' do
+ it 'returns a limited list of participants', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue.iid}/participants", create(:user))
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/requests/api/issues/issues_spec.rb b/spec/requests/api/issues/issues_spec.rb
index 078f00334c3..33f49cefc69 100644
--- a/spec/requests/api/issues/issues_spec.rb
+++ b/spec/requests/api/issues/issues_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
shared_examples 'issues statistics' do
- it 'returns issues statistics' do
+ it 'returns issues statistics', :aggregate_failures do
get api("/issues_statistics", user), params: params
expect(response).to have_gitlab_http_status(:ok)
@@ -109,8 +109,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
context 'as an admin' do
context 'when issue exists' do
- it 'returns the issue' do
- get api("/issues/#{issue.id}", admin)
+ it 'returns the issue', :aggregate_failures do
+ get api("/issues/#{issue.id}", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response.dig('author', 'id')).to eq(issue.author.id)
@@ -121,7 +121,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
context 'when issue does not exist' do
it 'returns 404' do
- get api("/issues/0", admin)
+ get api("/issues/0", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -132,7 +132,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
describe 'GET /issues' do
context 'when unauthenticated' do
- it 'returns an array of all issues' do
+ it 'returns an array of all issues', :aggregate_failures do
get api('/issues'), params: { scope: 'all' }
expect(response).to have_gitlab_http_status(:ok)
@@ -162,14 +162,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(response).to have_gitlab_http_status(:unauthorized)
end
- it 'returns an array of issues matching state in milestone' do
+ it 'returns an array of issues matching state in milestone', :aggregate_failures do
get api('/issues'), params: { milestone: 'foo', scope: 'all' }
expect(response).to have_gitlab_http_status(:ok)
expect_paginated_array_response([])
end
- it 'returns an array of issues matching state in milestone' do
+ it 'returns an array of issues matching state in milestone', :aggregate_failures do
get api('/issues'), params: { milestone: milestone.title, scope: 'all' }
expect(response).to have_gitlab_http_status(:ok)
@@ -273,7 +273,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when authenticated' do
- it 'returns an array of issues' do
+ it 'returns an array of issues', :aggregate_failures do
get api('/issues', user)
expect_paginated_array_response([issue.id, closed_issue.id])
@@ -532,7 +532,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
context 'with incident issues' do
let_it_be(:incident) { create(:incident, project: project) }
- it 'avoids N+1 queries' do
+ it 'avoids N+1 queries', :aggregate_failures do
get api('/issues', user) # warm up
control = ActiveRecord::QueryRecorder.new do
@@ -553,7 +553,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
context 'with issues closed as duplicates' do
let_it_be(:dup_issue_1) { create(:issue, :closed_as_duplicate, project: project) }
- it 'avoids N+1 queries' do
+ it 'avoids N+1 queries', :aggregate_failures do
get api('/issues', user) # warm up
control = ActiveRecord::QueryRecorder.new do
@@ -639,7 +639,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect_paginated_array_response([])
end
- it 'returns an array of labeled issues matching given state' do
+ it 'returns an array of labeled issues matching given state', :aggregate_failures do
get api('/issues', user), params: { labels: label.title, state: :opened }
expect_paginated_array_response(issue.id)
@@ -647,7 +647,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response.first['state']).to eq('opened')
end
- it 'returns an array of labeled issues matching given state with labels param as array' do
+ it 'returns an array of labeled issues matching given state with labels param as array', :aggregate_failures do
get api('/issues', user), params: { labels: [label.title], state: :opened }
expect_paginated_array_response(issue.id)
@@ -917,14 +917,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'matches V4 response schema' do
+ it 'matches V4 response schema', :aggregate_failures do
get api('/issues', user)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/issues')
end
- it 'returns a related merge request count of 0 if there are no related merge requests' do
+ it 'returns a related merge request count of 0 if there are no related merge requests', :aggregate_failures do
get api('/issues', user)
expect(response).to have_gitlab_http_status(:ok)
@@ -932,7 +932,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response.first).to include('merge_requests_count' => 0)
end
- it 'returns a related merge request count > 0 if there are related merge requests' do
+ it 'returns a related merge request count > 0 if there are related merge requests', :aggregate_failures do
create(:merge_requests_closing_issues, issue: issue)
get api('/issues', user)
@@ -1013,28 +1013,28 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:issue2) { create(:issue, author: user2, project: project, created_at: 2.days.ago) }
let!(:issue3) { create(:issue, author: user2, assignees: [assignee, another_assignee], project: project, created_at: 1.day.ago) }
- it 'returns issues with by assignee_username' do
+ it 'returns issues with by assignee_username', :aggregate_failures do
get api("/issues", user), params: { assignee_username: [assignee.username], scope: 'all' }
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
expect_paginated_array_response([confidential_issue.id, issue3.id])
end
- it 'returns issues by assignee_username as string' do
+ it 'returns issues by assignee_username as string', :aggregate_failures do
get api("/issues", user), params: { assignee_username: assignee.username, scope: 'all' }
expect(issue3.reload.assignees.pluck(:id)).to match_array([assignee.id, another_assignee.id])
expect_paginated_array_response([confidential_issue.id, issue3.id])
end
- it 'returns error when multiple assignees are passed' do
+ it 'returns error when multiple assignees are passed', :aggregate_failures do
get api("/issues", user), params: { assignee_username: [assignee.username, another_assignee.username], scope: 'all' }
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response["error"]).to include("allows one value, but found 2")
end
- it 'returns error when assignee_username and assignee_id are passed together' do
+ it 'returns error when assignee_username and assignee_id are passed together', :aggregate_failures do
get api("/issues", user), params: { assignee_username: [assignee.username], assignee_id: another_assignee.id, scope: 'all' }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -1088,7 +1088,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe 'GET /projects/:id/issues/:issue_iid' do
- it 'exposes full reference path' do
+ it 'exposes full reference path', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -1106,7 +1106,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'user does not have permission to view new issue' do
- it 'does not return the issue as closed_as_duplicate_of' do
+ it 'does not return the issue as closed_as_duplicate_of', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue_closed_as_dup.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -1119,7 +1119,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
new_issue.project.add_guest(user)
end
- it 'returns the issue as closed_as_duplicate_of' do
+ it 'returns the issue as closed_as_duplicate_of', :aggregate_failures do
get api("/projects/#{project.id}/issues/#{issue_closed_as_dup.iid}", user)
expect(response).to have_gitlab_http_status(:ok)
@@ -1131,7 +1131,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe "POST /projects/:id/issues" do
- it 'creates a new project issue' do
+ it 'creates a new project issue', :aggregate_failures do
post api("/projects/#{project.id}/issues", user), params: { title: 'new issue' }
expect(response).to have_gitlab_http_status(:created)
@@ -1140,7 +1140,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when confidential is null' do
- it 'responds with 400 error' do
+ it 'responds with 400 error', :aggregate_failures do
post api("/projects/#{project.id}/issues", user), params: { title: 'issue', confidential: nil }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -1155,7 +1155,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'returns and error message and status code from the service' do
+ it 'returns and error message and status code from the service', :aggregate_failures do
post api("/projects/#{project.id}/issues", user), params: { title: 'new issue' }
expect(response).to have_gitlab_http_status(:forbidden)
@@ -1177,15 +1177,15 @@ RSpec.describe API::Issues, feature_category: :team_planning do
travel_to fixed_time
end
- it 'allows admins to set the timestamp' do
- put api("/projects/#{project.id}/issues/#{issue.iid}", admin), params: { labels: 'label1', updated_at: updated_at }
+ it 'allows admins to set the timestamp', :aggregate_failures do
+ put api("/projects/#{project.id}/issues/#{issue.iid}", admin, admin_mode: true), params: { labels: 'label1', updated_at: updated_at }
expect(response).to have_gitlab_http_status(:ok)
expect(Time.parse(json_response['updated_at'])).to be_like_time(updated_at)
expect(ResourceLabelEvent.last.created_at).to be_like_time(updated_at)
end
- it 'does not allow other users to set the timestamp' do
+ it 'does not allow other users to set the timestamp', :aggregate_failures do
reporter = create(:user)
project.add_developer(reporter)
@@ -1268,7 +1268,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'with valid params' do
- it 'reorders issues and returns a successful 200 response' do
+ it 'reorders issues and returns a successful 200 response', :aggregate_failures do
put api("/projects/#{project.id}/issues/#{issue1.iid}/reorder", user), params: { move_after_id: issue2.id, move_before_id: issue3.id }
expect(response).to have_gitlab_http_status(:ok)
@@ -1295,7 +1295,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let(:other_project) { create(:project, group: group) }
let(:other_issue) { create(:issue, project: other_project, relative_position: 80) }
- it 'reorders issues and returns a successful 200 response' do
+ it 'reorders issues and returns a successful 200 response', :aggregate_failures do
put api("/projects/#{other_project.id}/issues/#{other_issue.iid}/reorder", user), params: { move_after_id: issue2.id, move_before_id: issue3.id }
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/requests/api/issues/post_projects_issues_spec.rb b/spec/requests/api/issues/post_projects_issues_spec.rb
index 265091fa698..a17c1389e83 100644
--- a/spec/requests/api/issues/post_projects_issues_spec.rb
+++ b/spec/requests/api/issues/post_projects_issues_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
describe 'POST /projects/:id/issues' do
context 'support for deprecated assignee_id' do
- it 'creates a new project issue' do
+ it 'creates a new project issue', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', assignee_id: user2.id }
@@ -85,7 +85,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['assignees'].first['name']).to eq(user2.name)
end
- it 'creates a new project issue when assignee_id is empty' do
+ it 'creates a new project issue when assignee_id is empty', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', assignee_id: '' }
@@ -96,7 +96,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'single assignee restrictions' do
- it 'creates a new project issue with no more than one assignee' do
+ it 'creates a new project issue with no more than one assignee', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', assignee_ids: [user2.id, guest.id] }
@@ -122,8 +122,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
context 'an internal ID is provided' do
context 'by an admin' do
- it 'sets the internal ID on the new issue' do
- post api("/projects/#{project.id}/issues", admin),
+ it 'sets the internal ID on the new issue', :aggregate_failures do
+ post api("/projects/#{project.id}/issues", admin, admin_mode: true),
params: { title: 'new issue', iid: 9001 }
expect(response).to have_gitlab_http_status(:created)
@@ -132,7 +132,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'by an owner' do
- it 'sets the internal ID on the new issue' do
+ it 'sets the internal ID on the new issue', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', iid: 9001 }
@@ -145,7 +145,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let(:group) { create(:group) }
let(:group_project) { create(:project, :public, namespace: group) }
- it 'sets the internal ID on the new issue' do
+ it 'sets the internal ID on the new issue', :aggregate_failures do
group.add_owner(user2)
post api("/projects/#{group_project.id}/issues", user2),
params: { title: 'new issue', iid: 9001 }
@@ -156,7 +156,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'by another user' do
- it 'ignores the given internal ID' do
+ it 'ignores the given internal ID', :aggregate_failures do
post api("/projects/#{project.id}/issues", user2),
params: { title: 'new issue', iid: 9001 }
@@ -166,8 +166,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when an issue with the same IID exists on database' do
- it 'returns 409' do
- post api("/projects/#{project.id}/issues", admin),
+ it 'returns 409', :aggregate_failures do
+ post api("/projects/#{project.id}/issues", admin, admin_mode: true),
params: { title: 'new issue', iid: issue.iid }
expect(response).to have_gitlab_http_status(:conflict)
@@ -176,7 +176,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'creates a new project issue' do
+ it 'creates a new project issue', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', labels: 'label, label2', weight: 3, assignee_ids: [user2.id] }
@@ -189,7 +189,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['assignees'].first['name']).to eq(user2.name)
end
- it 'creates a new project issue with labels param as array' do
+ it 'creates a new project issue with labels param as array', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', labels: %w(label label2), weight: 3, assignee_ids: [user2.id] }
@@ -202,7 +202,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['assignees'].first['name']).to eq(user2.name)
end
- it 'creates a new confidential project issue' do
+ it 'creates a new confidential project issue', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', confidential: true }
@@ -211,7 +211,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['confidential']).to be_truthy
end
- it 'creates a new confidential project issue with a different param' do
+ it 'creates a new confidential project issue with a different param', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', confidential: 'y' }
@@ -220,7 +220,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['confidential']).to be_truthy
end
- it 'creates a public issue when confidential param is false' do
+ it 'creates a public issue when confidential param is false', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', confidential: false }
@@ -229,7 +229,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['confidential']).to be_falsy
end
- it 'creates a public issue when confidential param is invalid' do
+ it 'creates a public issue when confidential param is invalid', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'new issue', confidential: 'foo' }
@@ -242,7 +242,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'allows special label names' do
+ it 'allows special label names', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: {
title: 'new issue',
@@ -256,7 +256,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['labels']).to include '&'
end
- it 'allows special label names with labels param as array' do
+ it 'allows special label names with labels param as array', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: {
title: 'new issue',
@@ -270,7 +270,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['labels']).to include '&'
end
- it 'returns 400 if title is too long' do
+ it 'returns 400 if title is too long', :aggregate_failures do
post api("/projects/#{project.id}/issues", user),
params: { title: 'g' * 256 }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -313,7 +313,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'with due date' do
- it 'creates a new project issue' do
+ it 'creates a new project issue', :aggregate_failures do
due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
post api("/projects/#{project.id}/issues", user),
@@ -336,8 +336,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'by an admin' do
- it 'sets the creation time on the new issue' do
- post api("/projects/#{project.id}/issues", admin), params: params
+ it 'sets the creation time on the new issue', :aggregate_failures do
+ post api("/projects/#{project.id}/issues", admin, admin_mode: true), params: params
expect(response).to have_gitlab_http_status(:created)
expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time)
@@ -346,7 +346,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'by a project owner' do
- it 'sets the creation time on the new issue' do
+ it 'sets the creation time on the new issue', :aggregate_failures do
post api("/projects/#{project.id}/issues", user), params: params
expect(response).to have_gitlab_http_status(:created)
@@ -356,7 +356,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'by a group owner' do
- it 'sets the creation time on the new issue' do
+ it 'sets the creation time on the new issue', :aggregate_failures do
group = create(:group)
group_project = create(:project, :public, namespace: group)
group.add_owner(user2)
@@ -370,7 +370,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'by another user' do
- it 'ignores the given creation time' do
+ it 'ignores the given creation time', :aggregate_failures do
project.add_developer(user2)
post api("/projects/#{project.id}/issues", user2), params: params
@@ -397,7 +397,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when request exceeds the rate limit' do
- it 'prevents users from creating more issues' do
+ it 'prevents users from creating more issues', :aggregate_failures do
allow(::Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true)
post api("/projects/#{project.id}/issues", user),
@@ -437,7 +437,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect { post_issue }.not_to change(Issue, :count)
end
- it 'returns correct status and message' do
+ it 'returns correct status and message', :aggregate_failures do
post_issue
expect(response).to have_gitlab_http_status(:bad_request)
@@ -476,7 +476,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:target_project) { create(:project, creator_id: user.id, namespace: user.namespace) }
let!(:target_project2) { create(:project, creator_id: non_member.id, namespace: non_member.namespace) }
- it 'moves an issue' do
+ it 'moves an issue', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
params: { to_project_id: target_project.id }
@@ -485,7 +485,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when source and target projects are the same' do
- it 'returns 400 when trying to move an issue' do
+ it 'returns 400 when trying to move an issue', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
params: { to_project_id: project.id }
@@ -495,7 +495,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when the user does not have the permission to move issues' do
- it 'returns 400 when trying to move an issue' do
+ it 'returns 400 when trying to move an issue', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/move", user),
params: { to_project_id: target_project2.id }
@@ -504,8 +504,8 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'moves the issue to another namespace if I am admin' do
- post api("/projects/#{project.id}/issues/#{issue.iid}/move", admin),
+ it 'moves the issue to another namespace if I am admin', :aggregate_failures do
+ post api("/projects/#{project.id}/issues/#{issue.iid}/move", admin, admin_mode: true),
params: { to_project_id: target_project2.id }
expect(response).to have_gitlab_http_status(:created)
@@ -513,7 +513,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when using the issue ID instead of iid' do
- it 'returns 404 when trying to move an issue', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341520' do
+ it 'returns 404 when trying to move an issue', :aggregate_failures, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341520' do
post api("/projects/#{project.id}/issues/#{issue.id}/move", user),
params: { to_project_id: target_project.id }
@@ -523,7 +523,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when issue does not exist' do
- it 'returns 404 when trying to move an issue' do
+ it 'returns 404 when trying to move an issue', :aggregate_failures do
post api("/projects/#{project.id}/issues/123/move", user),
params: { to_project_id: target_project.id }
@@ -533,7 +533,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when source project does not exist' do
- it 'returns 404 when trying to move an issue' do
+ it 'returns 404 when trying to move an issue', :aggregate_failures do
post api("/projects/0/issues/#{issue.iid}/move", user),
params: { to_project_id: target_project.id }
@@ -562,7 +562,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
context 'when user can admin the issue' do
context 'when the user can admin the target project' do
- it 'clones the issue' do
+ it 'clones the issue', :aggregate_failures do
expect do
post_clone_issue(user, issue, valid_target_project)
end.to change { valid_target_project.issues.count }.by(1)
@@ -577,7 +577,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when target project is the same source project' do
- it 'clones the issue' do
+ it 'clones the issue', :aggregate_failures do
expect do
post_clone_issue(user, issue, issue.project)
end.to change { issue.reset.project.issues.count }.by(1)
@@ -595,7 +595,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when the user does not have the permission to clone issues' do
- it 'returns 400' do
+ it 'returns 400', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/clone", user),
params: { to_project_id: invalid_target_project.id }
@@ -605,7 +605,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when using the issue ID instead of iid' do
- it 'returns 404', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341520' do
+ it 'returns 404', :aggregate_failures, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/341520' do
post api("/projects/#{project.id}/issues/#{issue.id}/clone", user),
params: { to_project_id: valid_target_project.id }
@@ -615,7 +615,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when issue does not exist' do
- it 'returns 404' do
+ it 'returns 404', :aggregate_failures do
post api("/projects/#{project.id}/issues/12300/clone", user),
params: { to_project_id: valid_target_project.id }
@@ -625,7 +625,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when source project does not exist' do
- it 'returns 404' do
+ it 'returns 404', :aggregate_failures do
post api("/projects/0/issues/#{issue.iid}/clone", user),
params: { to_project_id: valid_target_project.id }
@@ -635,7 +635,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
context 'when target project does not exist' do
- it 'returns 404' do
+ it 'returns 404', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/clone", user),
params: { to_project_id: 0 }
@@ -644,7 +644,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'clones the issue with notes when with_notes is true' do
+ it 'clones the issue with notes when with_notes is true', :aggregate_failures do
expect do
post api("/projects/#{project.id}/issues/#{issue.iid}/clone", user),
params: { to_project_id: valid_target_project.id, with_notes: true }
@@ -661,7 +661,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe 'POST :id/issues/:issue_iid/subscribe' do
- it 'subscribes to an issue' do
+ it 'subscribes to an issue', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/subscribe", user2)
expect(response).to have_gitlab_http_status(:created)
@@ -694,7 +694,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe 'POST :id/issues/:issue_id/unsubscribe' do
- it 'unsubscribes from an issue' do
+ it 'unsubscribes from an issue', :aggregate_failures do
post api("/projects/#{project.id}/issues/#{issue.iid}/unsubscribe", user)
expect(response).to have_gitlab_http_status(:created)
diff --git a/spec/requests/api/issues/put_projects_issues_spec.rb b/spec/requests/api/issues/put_projects_issues_spec.rb
index f0d174c9e78..6cc639c0bcc 100644
--- a/spec/requests/api/issues/put_projects_issues_spec.rb
+++ b/spec/requests/api/issues/put_projects_issues_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe 'PUT /projects/:id/issues/:issue_iid to update only title' do
- it 'updates a project issue' do
+ it 'updates a project issue', :aggregate_failures do
put api_for_user, params: { title: updated_title }
expect(response).to have_gitlab_http_status(:ok)
@@ -109,7 +109,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(response).to have_gitlab_http_status(:ok)
end
- it 'allows special label names with labels param as array' do
+ it 'allows special label names with labels param as array', :aggregate_failures do
put api_for_user,
params: {
title: updated_title,
@@ -135,42 +135,42 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(response).to have_gitlab_http_status(:forbidden)
end
- it 'updates a confidential issue for project members' do
+ it 'updates a confidential issue for project members', :aggregate_failures do
put api(confidential_issue_path, user), params: { title: updated_title }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq(updated_title)
end
- it 'updates a confidential issue for author' do
+ it 'updates a confidential issue for author', :aggregate_failures do
put api(confidential_issue_path, author), params: { title: updated_title }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq(updated_title)
end
- it 'updates a confidential issue for admin' do
- put api(confidential_issue_path, admin), params: { title: updated_title }
+ it 'updates a confidential issue for admin', :aggregate_failures do
+ put api(confidential_issue_path, admin, admin_mode: true), params: { title: updated_title }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['title']).to eq(updated_title)
end
- it 'sets an issue to confidential' do
+ it 'sets an issue to confidential', :aggregate_failures do
put api_for_user, params: { confidential: true }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['confidential']).to be_truthy
end
- it 'makes a confidential issue public' do
+ it 'makes a confidential issue public', :aggregate_failures do
put api(confidential_issue_path, user), params: { confidential: false }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['confidential']).to be_falsy
end
- it 'does not update a confidential issue with wrong confidential flag' do
+ it 'does not update a confidential issue with wrong confidential flag', :aggregate_failures do
put api(confidential_issue_path, user), params: { confidential: 'foo' }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -209,7 +209,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect { update_issue }.not_to change { issue.reload.title }
end
- it 'returns correct status and message' do
+ it 'returns correct status and message', :aggregate_failures do
update_issue
expect(response).to have_gitlab_http_status(:bad_request)
@@ -246,14 +246,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do
describe 'PUT /projects/:id/issues/:issue_iid to update assignee' do
context 'support for deprecated assignee_id' do
- it 'removes assignee' do
+ it 'removes assignee', :aggregate_failures do
put api_for_user, params: { assignee_id: 0 }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['assignee']).to be_nil
end
- it 'updates an issue with new assignee' do
+ it 'updates an issue with new assignee', :aggregate_failures do
put api_for_user, params: { assignee_id: user2.id }
expect(response).to have_gitlab_http_status(:ok)
@@ -261,21 +261,21 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'removes assignee' do
+ it 'removes assignee', :aggregate_failures do
put api_for_user, params: { assignee_ids: [0] }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['assignees']).to be_empty
end
- it 'updates an issue with new assignee' do
+ it 'updates an issue with new assignee', :aggregate_failures do
put api_for_user, params: { assignee_ids: [user2.id] }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['assignees'].first['name']).to eq(user2.name)
end
- context 'single assignee restrictions' do
+ context 'single assignee restrictions', :aggregate_failures do
it 'updates an issue with several assignees but only one has been applied' do
put api_for_user, params: { assignee_ids: [user2.id, guest.id] }
@@ -289,7 +289,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:label) { create(:label, title: 'dummy', project: project) }
let!(:label_link) { create(:label_link, label: label, target: issue) }
- it 'adds relevant labels' do
+ it 'adds relevant labels', :aggregate_failures do
put api_for_user, params: { add_labels: '1, 2' }
expect(response).to have_gitlab_http_status(:ok)
@@ -300,14 +300,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do
let!(:label2) { create(:label, title: 'a-label', project: project) }
let!(:label_link2) { create(:label_link, label: label2, target: issue) }
- it 'removes relevant labels' do
+ it 'removes relevant labels', :aggregate_failures do
put api_for_user, params: { remove_labels: label2.title }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['labels']).to eq([label.title])
end
- it 'removes all labels' do
+ it 'removes all labels', :aggregate_failures do
put api_for_user, params: { remove_labels: "#{label.title}, #{label2.title}" }
expect(response).to have_gitlab_http_status(:ok)
@@ -315,14 +315,14 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
end
- it 'does not update labels if not present' do
+ it 'does not update labels if not present', :aggregate_failures do
put api_for_user, params: { title: updated_title }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['labels']).to eq([label.title])
end
- it 'removes all labels and touches the record' do
+ it 'removes all labels and touches the record', :aggregate_failures do
travel_to(2.minutes.from_now) do
put api_for_user, params: { labels: '' }
end
@@ -332,7 +332,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['updated_at']).to be > Time.current
end
- it 'removes all labels and touches the record with labels param as array' do
+ it 'removes all labels and touches the record with labels param as array', :aggregate_failures do
travel_to(2.minutes.from_now) do
put api_for_user, params: { labels: [''] }
end
@@ -342,7 +342,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['updated_at']).to be > Time.current
end
- it 'updates labels and touches the record' do
+ it 'updates labels and touches the record', :aggregate_failures do
travel_to(2.minutes.from_now) do
put api_for_user, params: { labels: 'foo,bar' }
end
@@ -352,7 +352,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['updated_at']).to be > Time.current
end
- it 'updates labels and touches the record with labels param as array' do
+ it 'updates labels and touches the record with labels param as array', :aggregate_failures do
travel_to(2.minutes.from_now) do
put api_for_user, params: { labels: %w(foo bar) }
end
@@ -363,21 +363,21 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['updated_at']).to be > Time.current
end
- it 'allows special label names' do
+ it 'allows special label names', :aggregate_failures do
put api_for_user, params: { labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['labels']).to contain_exactly('label:foo', 'label-bar', 'label_bar', 'label/bar', 'label?bar', 'label&bar', '?', '&')
end
- it 'allows special label names with labels param as array' do
+ it 'allows special label names with labels param as array', :aggregate_failures do
put api_for_user, params: { labels: ['label:foo', 'label-bar', 'label_bar', 'label/bar,label?bar,label&bar,?,&'] }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['labels']).to contain_exactly('label:foo', 'label-bar', 'label_bar', 'label/bar', 'label?bar', 'label&bar', '?', '&')
end
- it 'returns 400 if title is too long' do
+ it 'returns 400 if title is too long', :aggregate_failures do
put api_for_user, params: { title: 'g' * 256 }
expect(response).to have_gitlab_http_status(:bad_request)
@@ -386,7 +386,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe 'PUT /projects/:id/issues/:issue_iid to update state and label' do
- it 'updates a project issue' do
+ it 'updates a project issue', :aggregate_failures do
put api_for_user, params: { labels: 'label2', state_event: 'close' }
expect(response).to have_gitlab_http_status(:ok)
@@ -394,7 +394,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(json_response['state']).to eq 'closed'
end
- it 'reopens a project isssue' do
+ it 'reopens a project isssue', :aggregate_failures do
put api(issue_path, user), params: { state_event: 'reopen' }
expect(response).to have_gitlab_http_status(:ok)
@@ -404,7 +404,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
describe 'PUT /projects/:id/issues/:issue_iid to update updated_at param' do
context 'when reporter makes request' do
- it 'accepts the update date to be set' do
+ it 'accepts the update date to be set', :aggregate_failures do
update_time = 2.weeks.ago
put api_for_user, params: { title: 'some new title', updated_at: update_time }
@@ -436,7 +436,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
expect(response).to have_gitlab_http_status(:bad_request)
end
- it 'accepts the update date to be set' do
+ it 'accepts the update date to be set', :aggregate_failures do
update_time = 2.weeks.ago
put api_for_owner, params: { title: 'some new title', updated_at: update_time }
@@ -448,7 +448,7 @@ RSpec.describe API::Issues, feature_category: :team_planning do
end
describe 'PUT /projects/:id/issues/:issue_iid to update due date' do
- it 'creates a new project issue' do
+ it 'creates a new project issue', :aggregate_failures do
due_date = 2.weeks.from_now.strftime('%Y-%m-%d')
put api_for_user, params: { due_date: due_date }
diff --git a/spec/requests/api/pages/internal_access_spec.rb b/spec/requests/api/pages/internal_access_spec.rb
index fdc25ecdcd3..3e7837866ae 100644
--- a/spec/requests/api/pages/internal_access_spec.rb
+++ b/spec/requests/api/pages/internal_access_spec.rb
@@ -35,39 +35,39 @@ RSpec.describe "Internal Project Pages Access", feature_category: :pages do
describe "GET /projects/:id/pages_access" do
context 'access depends on the level' do
- where(:pages_access_level, :with_user, :expected_result) do
- ProjectFeature::DISABLED | "admin" | 403
- ProjectFeature::DISABLED | "owner" | 403
- ProjectFeature::DISABLED | "master" | 403
- ProjectFeature::DISABLED | "developer" | 403
- ProjectFeature::DISABLED | "reporter" | 403
- ProjectFeature::DISABLED | "guest" | 403
- ProjectFeature::DISABLED | "user" | 403
- ProjectFeature::DISABLED | nil | 404
- ProjectFeature::PUBLIC | "admin" | 200
- ProjectFeature::PUBLIC | "owner" | 200
- ProjectFeature::PUBLIC | "master" | 200
- ProjectFeature::PUBLIC | "developer" | 200
- ProjectFeature::PUBLIC | "reporter" | 200
- ProjectFeature::PUBLIC | "guest" | 200
- ProjectFeature::PUBLIC | "user" | 200
- ProjectFeature::PUBLIC | nil | 404
- ProjectFeature::ENABLED | "admin" | 200
- ProjectFeature::ENABLED | "owner" | 200
- ProjectFeature::ENABLED | "master" | 200
- ProjectFeature::ENABLED | "developer" | 200
- ProjectFeature::ENABLED | "reporter" | 200
- ProjectFeature::ENABLED | "guest" | 200
- ProjectFeature::ENABLED | "user" | 200
- ProjectFeature::ENABLED | nil | 404
- ProjectFeature::PRIVATE | "admin" | 200
- ProjectFeature::PRIVATE | "owner" | 200
- ProjectFeature::PRIVATE | "master" | 200
- ProjectFeature::PRIVATE | "developer" | 200
- ProjectFeature::PRIVATE | "reporter" | 200
- ProjectFeature::PRIVATE | "guest" | 200
- ProjectFeature::PRIVATE | "user" | 403
- ProjectFeature::PRIVATE | nil | 404
+ where(:pages_access_level, :with_user, :admin_mode, :expected_result) do
+ ProjectFeature::DISABLED | "admin" | true | 403
+ ProjectFeature::DISABLED | "owner" | false | 403
+ ProjectFeature::DISABLED | "master" | false | 403
+ ProjectFeature::DISABLED | "developer" | false | 403
+ ProjectFeature::DISABLED | "reporter" | false | 403
+ ProjectFeature::DISABLED | "guest" | false | 403
+ ProjectFeature::DISABLED | "user" | false | 403
+ ProjectFeature::DISABLED | nil | false | 404
+ ProjectFeature::PUBLIC | "admin" | false | 200
+ ProjectFeature::PUBLIC | "owner" | false | 200
+ ProjectFeature::PUBLIC | "master" | false | 200
+ ProjectFeature::PUBLIC | "developer" | false | 200
+ ProjectFeature::PUBLIC | "reporter" | false | 200
+ ProjectFeature::PUBLIC | "guest" | false | 200
+ ProjectFeature::PUBLIC | "user" | false | 200
+ ProjectFeature::PUBLIC | nil | false | 404
+ ProjectFeature::ENABLED | "admin" | false | 200
+ ProjectFeature::ENABLED | "owner" | false | 200
+ ProjectFeature::ENABLED | "master" | false | 200
+ ProjectFeature::ENABLED | "developer" | false | 200
+ ProjectFeature::ENABLED | "reporter" | false | 200
+ ProjectFeature::ENABLED | "guest" | false | 200
+ ProjectFeature::ENABLED | "user" | false | 200
+ ProjectFeature::ENABLED | nil | false | 404
+ ProjectFeature::PRIVATE | "admin" | true | 200
+ ProjectFeature::PRIVATE | "owner" | false | 200
+ ProjectFeature::PRIVATE | "master" | false | 200
+ ProjectFeature::PRIVATE | "developer" | false | 200
+ ProjectFeature::PRIVATE | "reporter" | false | 200
+ ProjectFeature::PRIVATE | "guest" | false | 200
+ ProjectFeature::PRIVATE | "user" | false | 403
+ ProjectFeature::PRIVATE | nil | false | 404
end
with_them do
@@ -77,7 +77,7 @@ RSpec.describe "Internal Project Pages Access", feature_category: :pages do
it "correct return value" do
if !with_user.nil?
user = public_send(with_user)
- get api("/projects/#{project.id}/pages_access", user)
+ get api("/projects/#{project.id}/pages_access", user, admin_mode: admin_mode)
else
get api("/projects/#{project.id}/pages_access")
end
diff --git a/spec/requests/api/pages/pages_spec.rb b/spec/requests/api/pages/pages_spec.rb
index c426f2a433c..0f6675799ad 100644
--- a/spec/requests/api/pages/pages_spec.rb
+++ b/spec/requests/api/pages/pages_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe API::Pages, feature_category: :pages do
- let_it_be(:project) { create(:project, path: 'my.project', pages_https_only: false) }
+ let_it_be_with_reload(:project) { create(:project, path: 'my.project', pages_https_only: false) }
let_it_be(:admin) { create(:admin) }
let_it_be(:user) { create(:user) }
@@ -19,7 +19,7 @@ RSpec.describe API::Pages, feature_category: :pages do
end
it_behaves_like '404 response' do
- let(:request) { delete api("/projects/#{project.id}/pages", admin) }
+ let(:request) { delete api("/projects/#{project.id}/pages", admin, admin_mode: true) }
end
end
@@ -30,13 +30,13 @@ RSpec.describe API::Pages, feature_category: :pages do
context 'when Pages are deployed' do
it 'returns 204' do
- delete api("/projects/#{project.id}/pages", admin)
+ delete api("/projects/#{project.id}/pages", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:no_content)
end
it 'removes the pages' do
- delete api("/projects/#{project.id}/pages", admin)
+ delete api("/projects/#{project.id}/pages", admin, admin_mode: true)
expect(project.reload.pages_metadatum.deployed?).to be(false)
end
@@ -48,7 +48,7 @@ RSpec.describe API::Pages, feature_category: :pages do
end
it 'returns 204' do
- delete api("/projects/#{project.id}/pages", admin)
+ delete api("/projects/#{project.id}/pages", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:no_content)
end
@@ -58,7 +58,7 @@ RSpec.describe API::Pages, feature_category: :pages do
it 'returns 404' do
id = -1
- delete api("/projects/#{id}/pages", admin)
+ delete api("/projects/#{id}/pages", admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/api/pages/private_access_spec.rb b/spec/requests/api/pages/private_access_spec.rb
index 5cc1b8f9a69..602eff73b0a 100644
--- a/spec/requests/api/pages/private_access_spec.rb
+++ b/spec/requests/api/pages/private_access_spec.rb
@@ -35,39 +35,39 @@ RSpec.describe "Private Project Pages Access", feature_category: :pages do
describe "GET /projects/:id/pages_access" do
context 'access depends on the level' do
- where(:pages_access_level, :with_user, :expected_result) do
- ProjectFeature::DISABLED | "admin" | 403
- ProjectFeature::DISABLED | "owner" | 403
- ProjectFeature::DISABLED | "master" | 403
- ProjectFeature::DISABLED | "developer" | 403
- ProjectFeature::DISABLED | "reporter" | 403
- ProjectFeature::DISABLED | "guest" | 403
- ProjectFeature::DISABLED | "user" | 404
- ProjectFeature::DISABLED | nil | 404
- ProjectFeature::PUBLIC | "admin" | 200
- ProjectFeature::PUBLIC | "owner" | 200
- ProjectFeature::PUBLIC | "master" | 200
- ProjectFeature::PUBLIC | "developer" | 200
- ProjectFeature::PUBLIC | "reporter" | 200
- ProjectFeature::PUBLIC | "guest" | 200
- ProjectFeature::PUBLIC | "user" | 404
- ProjectFeature::PUBLIC | nil | 404
- ProjectFeature::ENABLED | "admin" | 200
- ProjectFeature::ENABLED | "owner" | 200
- ProjectFeature::ENABLED | "master" | 200
- ProjectFeature::ENABLED | "developer" | 200
- ProjectFeature::ENABLED | "reporter" | 200
- ProjectFeature::ENABLED | "guest" | 200
- ProjectFeature::ENABLED | "user" | 404
- ProjectFeature::ENABLED | nil | 404
- ProjectFeature::PRIVATE | "admin" | 200
- ProjectFeature::PRIVATE | "owner" | 200
- ProjectFeature::PRIVATE | "master" | 200
- ProjectFeature::PRIVATE | "developer" | 200
- ProjectFeature::PRIVATE | "reporter" | 200
- ProjectFeature::PRIVATE | "guest" | 200
- ProjectFeature::PRIVATE | "user" | 404
- ProjectFeature::PRIVATE | nil | 404
+ where(:pages_access_level, :with_user, :admin_mode, :expected_result) do
+ ProjectFeature::DISABLED | "admin" | true | 403
+ ProjectFeature::DISABLED | "owner" | false | 403
+ ProjectFeature::DISABLED | "master" | false | 403
+ ProjectFeature::DISABLED | "developer" | false | 403
+ ProjectFeature::DISABLED | "reporter" | false | 403
+ ProjectFeature::DISABLED | "guest" | false | 403
+ ProjectFeature::DISABLED | "user" | false | 404
+ ProjectFeature::DISABLED | nil | false | 404
+ ProjectFeature::PUBLIC | "admin" | true | 200
+ ProjectFeature::PUBLIC | "owner" | false | 200
+ ProjectFeature::PUBLIC | "master" | false | 200
+ ProjectFeature::PUBLIC | "developer" | false | 200
+ ProjectFeature::PUBLIC | "reporter" | false | 200
+ ProjectFeature::PUBLIC | "guest" | false | 200
+ ProjectFeature::PUBLIC | "user" | false | 404
+ ProjectFeature::PUBLIC | nil | false | 404
+ ProjectFeature::ENABLED | "admin" | true | 200
+ ProjectFeature::ENABLED | "owner" | false | 200
+ ProjectFeature::ENABLED | "master" | false | 200
+ ProjectFeature::ENABLED | "developer" | false | 200
+ ProjectFeature::ENABLED | "reporter" | false | 200
+ ProjectFeature::ENABLED | "guest" | false | 200
+ ProjectFeature::ENABLED | "user" | false | 404
+ ProjectFeature::ENABLED | nil | false | 404
+ ProjectFeature::PRIVATE | "admin" | true | 200
+ ProjectFeature::PRIVATE | "owner" | false | 200
+ ProjectFeature::PRIVATE | "master" | false | 200
+ ProjectFeature::PRIVATE | "developer" | false | 200
+ ProjectFeature::PRIVATE | "reporter" | false | 200
+ ProjectFeature::PRIVATE | "guest" | false | 200
+ ProjectFeature::PRIVATE | "user" | false | 404
+ ProjectFeature::PRIVATE | nil | false | 404
end
with_them do
@@ -77,7 +77,7 @@ RSpec.describe "Private Project Pages Access", feature_category: :pages do
it "correct return value" do
if !with_user.nil?
user = public_send(with_user)
- get api("/projects/#{project.id}/pages_access", user)
+ get api("/projects/#{project.id}/pages_access", user, admin_mode: admin_mode)
else
get api("/projects/#{project.id}/pages_access")
end
diff --git a/spec/requests/api/pages/public_access_spec.rb b/spec/requests/api/pages/public_access_spec.rb
index 1137f91f4b0..8b0ed7c59ab 100644
--- a/spec/requests/api/pages/public_access_spec.rb
+++ b/spec/requests/api/pages/public_access_spec.rb
@@ -35,39 +35,39 @@ RSpec.describe "Public Project Pages Access", feature_category: :pages do
describe "GET /projects/:id/pages_access" do
context 'access depends on the level' do
- where(:pages_access_level, :with_user, :expected_result) do
- ProjectFeature::DISABLED | "admin" | 403
- ProjectFeature::DISABLED | "owner" | 403
- ProjectFeature::DISABLED | "master" | 403
- ProjectFeature::DISABLED | "developer" | 403
- ProjectFeature::DISABLED | "reporter" | 403
- ProjectFeature::DISABLED | "guest" | 403
- ProjectFeature::DISABLED | "user" | 403
- ProjectFeature::DISABLED | nil | 403
- ProjectFeature::PUBLIC | "admin" | 200
- ProjectFeature::PUBLIC | "owner" | 200
- ProjectFeature::PUBLIC | "master" | 200
- ProjectFeature::PUBLIC | "developer" | 200
- ProjectFeature::PUBLIC | "reporter" | 200
- ProjectFeature::PUBLIC | "guest" | 200
- ProjectFeature::PUBLIC | "user" | 200
- ProjectFeature::PUBLIC | nil | 200
- ProjectFeature::ENABLED | "admin" | 200
- ProjectFeature::ENABLED | "owner" | 200
- ProjectFeature::ENABLED | "master" | 200
- ProjectFeature::ENABLED | "developer" | 200
- ProjectFeature::ENABLED | "reporter" | 200
- ProjectFeature::ENABLED | "guest" | 200
- ProjectFeature::ENABLED | "user" | 200
- ProjectFeature::ENABLED | nil | 200
- ProjectFeature::PRIVATE | "admin" | 200
- ProjectFeature::PRIVATE | "owner" | 200
- ProjectFeature::PRIVATE | "master" | 200
- ProjectFeature::PRIVATE | "developer" | 200
- ProjectFeature::PRIVATE | "reporter" | 200
- ProjectFeature::PRIVATE | "guest" | 200
- ProjectFeature::PRIVATE | "user" | 403
- ProjectFeature::PRIVATE | nil | 403
+ where(:pages_access_level, :with_user, :admin_mode, :expected_result) do
+ ProjectFeature::DISABLED | "admin" | false | 403
+ ProjectFeature::DISABLED | "owner" | false | 403
+ ProjectFeature::DISABLED | "master" | false | 403
+ ProjectFeature::DISABLED | "developer" | false | 403
+ ProjectFeature::DISABLED | "reporter" | false | 403
+ ProjectFeature::DISABLED | "guest" | false | 403
+ ProjectFeature::DISABLED | "user" | false | 403
+ ProjectFeature::DISABLED | nil | false | 403
+ ProjectFeature::PUBLIC | "admin" | false | 200
+ ProjectFeature::PUBLIC | "owner" | false | 200
+ ProjectFeature::PUBLIC | "master" | false | 200
+ ProjectFeature::PUBLIC | "developer" | false | 200
+ ProjectFeature::PUBLIC | "reporter" | false | 200
+ ProjectFeature::PUBLIC | "guest" | false | 200
+ ProjectFeature::PUBLIC | "user" | false | 200
+ ProjectFeature::PUBLIC | nil | false | 200
+ ProjectFeature::ENABLED | "admin" | false | 200
+ ProjectFeature::ENABLED | "owner" | false | 200
+ ProjectFeature::ENABLED | "master" | false | 200
+ ProjectFeature::ENABLED | "developer" | false | 200
+ ProjectFeature::ENABLED | "reporter" | false | 200
+ ProjectFeature::ENABLED | "guest" | false | 200
+ ProjectFeature::ENABLED | "user" | false | 200
+ ProjectFeature::ENABLED | nil | false | 200
+ ProjectFeature::PRIVATE | "admin" | true | 200
+ ProjectFeature::PRIVATE | "owner" | false | 200
+ ProjectFeature::PRIVATE | "master" | false | 200
+ ProjectFeature::PRIVATE | "developer" | false | 200
+ ProjectFeature::PRIVATE | "reporter" | false | 200
+ ProjectFeature::PRIVATE | "guest" | false | 200
+ ProjectFeature::PRIVATE | "user" | false | 403
+ ProjectFeature::PRIVATE | nil | false | 403
end
with_them do
@@ -77,7 +77,7 @@ RSpec.describe "Public Project Pages Access", feature_category: :pages do
it "correct return value" do
if !with_user.nil?
user = public_send(with_user)
- get api("/projects/#{project.id}/pages_access", user)
+ get api("/projects/#{project.id}/pages_access", user, admin_mode: admin_mode)
else
get api("/projects/#{project.id}/pages_access")
end
diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb
index ba1fb5105b8..ea83fa384af 100644
--- a/spec/requests/api/pages_domains_spec.rb
+++ b/spec/requests/api/pages_domains_spec.rb
@@ -41,14 +41,14 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
end
it_behaves_like '404 response' do
- let(:request) { get api('/pages/domains', admin) }
+ let(:request) { get api('/pages/domains', admin, admin_mode: true) }
end
end
context 'when pages is enabled' do
context 'when authenticated as an admin' do
- it 'returns paginated all pages domains' do
- get api('/pages/domains', admin)
+ it 'returns paginated all pages domains', :aggregate_failures do
+ get api('/pages/domains', admin, admin_mode: true)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/pages_domain_basics')
@@ -74,7 +74,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
describe 'GET /projects/:project_id/pages/domains' do
shared_examples_for 'get pages domains' do
- it 'returns paginated pages domains' do
+ it 'returns paginated pages domains', :aggregate_failures do
get api(route, user)
expect(response).to have_gitlab_http_status(:ok)
@@ -145,7 +145,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
describe 'GET /projects/:project_id/pages/domains/:domain' do
shared_examples_for 'get pages domain' do
- it 'returns pages domain' do
+ it 'returns pages domain', :aggregate_failures do
get api(route_domain, user)
expect(response).to have_gitlab_http_status(:ok)
@@ -155,7 +155,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(json_response['certificate']).to be_nil
end
- it 'returns pages domain with project path' do
+ it 'returns pages domain with project path', :aggregate_failures do
get api(route_domain_path, user)
expect(response).to have_gitlab_http_status(:ok)
@@ -165,7 +165,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(json_response['certificate']).to be_nil
end
- it 'returns pages domain with a certificate' do
+ it 'returns pages domain with a certificate', :aggregate_failures do
get api(route_secure_domain, user)
expect(response).to have_gitlab_http_status(:ok)
@@ -177,7 +177,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(json_response['auto_ssl_enabled']).to be false
end
- it 'returns pages domain with an expired certificate' do
+ it 'returns pages domain with an expired certificate', :aggregate_failures do
get api(route_expired_domain, user)
expect(response).to have_gitlab_http_status(:ok)
@@ -185,7 +185,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(json_response['certificate']['expired']).to be true
end
- it 'returns pages domain with letsencrypt' do
+ it 'returns pages domain with letsencrypt', :aggregate_failures do
get api(route_letsencrypt_domain, user)
expect(response).to have_gitlab_http_status(:ok)
@@ -258,7 +258,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
let(:params_secure) { pages_domain_secure_params.slice(:domain, :certificate, :key) }
shared_examples_for 'post pages domains' do
- it 'creates a new pages domain' do
+ it 'creates a new pages domain', :aggregate_failures do
expect { post api(route, user), params: params }
.to publish_event(PagesDomains::PagesDomainCreatedEvent)
.with(
@@ -279,7 +279,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain.auto_ssl_enabled).to be false
end
- it 'creates a new secure pages domain' do
+ it 'creates a new secure pages domain', :aggregate_failures do
post api(route, user), params: params_secure
pages_domain = PagesDomain.find_by(domain: json_response['domain'])
@@ -291,7 +291,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain.auto_ssl_enabled).to be false
end
- it 'creates domain with letsencrypt enabled' do
+ it 'creates domain with letsencrypt enabled', :aggregate_failures do
post api(route, user), params: pages_domain_with_letsencrypt_params
pages_domain = PagesDomain.find_by(domain: json_response['domain'])
@@ -301,7 +301,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain.auto_ssl_enabled).to be true
end
- it 'creates domain with letsencrypt enabled and provided certificate' do
+ it 'creates domain with letsencrypt enabled and provided certificate', :aggregate_failures do
post api(route, user), params: params_secure.merge(auto_ssl_enabled: true)
pages_domain = PagesDomain.find_by(domain: json_response['domain'])
@@ -376,7 +376,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
let(:params_secure_nokey) { pages_domain_secure_params.slice(:certificate) }
shared_examples_for 'put pages domain' do
- it 'updates pages domain removing certificate' do
+ it 'updates pages domain removing certificate', :aggregate_failures do
put api(route_secure_domain, user), params: { certificate: nil, key: nil }
pages_domain_secure.reload
@@ -399,7 +399,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
)
end
- it 'updates pages domain adding certificate' do
+ it 'updates pages domain adding certificate', :aggregate_failures do
put api(route_domain, user), params: params_secure
pages_domain.reload
@@ -409,7 +409,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain.key).to eq(params_secure[:key])
end
- it 'updates pages domain adding certificate with letsencrypt' do
+ it 'updates pages domain adding certificate with letsencrypt', :aggregate_failures do
put api(route_domain, user), params: params_secure.merge(auto_ssl_enabled: true)
pages_domain.reload
@@ -420,7 +420,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain.auto_ssl_enabled).to be true
end
- it 'updates pages domain enabling letsencrypt' do
+ it 'updates pages domain enabling letsencrypt', :aggregate_failures do
put api(route_domain, user), params: { auto_ssl_enabled: true }
pages_domain.reload
@@ -429,7 +429,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain.auto_ssl_enabled).to be true
end
- it 'updates pages domain disabling letsencrypt while preserving the certificate' do
+ it 'updates pages domain disabling letsencrypt while preserving the certificate', :aggregate_failures do
put api(route_letsencrypt_domain, user), params: { auto_ssl_enabled: false }
pages_domain_with_letsencrypt.reload
@@ -440,7 +440,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain_with_letsencrypt.certificate).to be
end
- it 'updates pages domain with expired certificate' do
+ it 'updates pages domain with expired certificate', :aggregate_failures do
put api(route_expired_domain, user), params: params_secure
pages_domain_expired.reload
@@ -450,7 +450,7 @@ RSpec.describe API::PagesDomains, feature_category: :pages do
expect(pages_domain_expired.key).to eq(params_secure[:key])
end
- it 'updates pages domain with expired certificate not updating key' do
+ it 'updates pages domain with expired certificate not updating key', :aggregate_failures do
put api(route_secure_domain, user), params: params_secure_nokey
pages_domain_secure.reload
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 44564224193..38e622714e0 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -362,20 +362,10 @@ RSpec.configure do |config|
./spec/requests/api/deploy_tokens_spec.rb
./spec/requests/api/freeze_periods_spec.rb
./spec/requests/api/groups_spec.rb
- ./spec/requests/api/issues/get_group_issues_spec.rb
- ./spec/requests/api/issues/get_project_issues_spec.rb
- ./spec/requests/api/issues/issues_spec.rb
- ./spec/requests/api/issues/post_projects_issues_spec.rb
- ./spec/requests/api/issues/put_projects_issues_spec.rb
./spec/requests/api/keys_spec.rb
./spec/requests/api/merge_requests_spec.rb
./spec/requests/api/namespaces_spec.rb
./spec/requests/api/notes_spec.rb
- ./spec/requests/api/pages/internal_access_spec.rb
- ./spec/requests/api/pages/pages_spec.rb
- ./spec/requests/api/pages/private_access_spec.rb
- ./spec/requests/api/pages/public_access_spec.rb
- ./spec/requests/api/pages_domains_spec.rb
./spec/requests/api/personal_access_tokens/self_information_spec.rb
./spec/requests/api/personal_access_tokens_spec.rb
./spec/requests/api/project_export_spec.rb
diff --git a/yarn.lock b/yarn.lock
index 22b9598215b..2b5aa3bad87 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1237,10 +1237,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.24.0.tgz#bc8265919aa04b06cd08be91637471bad195936d"
integrity sha512-R4s5qJUFUIbPflknpw1aI/PchiNq65vY7LVsJZnQkY+vi+AgmsETdut/AdferbGWmeWMU0q2wuVu9phE8lDUgA==
-"@gitlab/ui@56.4.0":
- version "56.4.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-56.4.0.tgz#35e2ee19fff9ff803f8737300d957b6a9f6ade1f"
- integrity sha512-L+0lf5jXrE34RruiibeDOb4wiziSsUhB+d3CHTQIjtm6qdqcwgYT03AoNTgc/E/YVLshEKywTJnnyakreecAlw==
+"@gitlab/ui@56.4.1":
+ version "56.4.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-56.4.1.tgz#bdf6284053b092608f6f0b70c6abeb36fd352aa2"
+ integrity sha512-WlEryaV/pwaJkHa+ioCcyB9slE+2RoPs15cmS+OtA9XsmWKqZTI1S00uZG9GcnA9hDKZM+HP2Apy7ku+myzLDQ==
dependencies:
"@popperjs/core" "^2.11.2"
bootstrap-vue "2.23.1"