Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-11-10 03:12:50 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-10 03:12:50 +0300
commit0abbeedd2fe28913033e91964d355addbc8a9746 (patch)
treedf10bc8767a0175ff70ccfb1aef65701d1c96aa5
parentda7b4c2be2e87563f06f2e92672dbfa4f30ca3da (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop.yml5
-rw-r--r--.rubocop_todo/rspec/before_all_role_assignment.yml1
-rw-r--r--.rubocop_todo/rspec/context_wording.yml1
-rw-r--r--.rubocop_todo/rspec/useless_dynamic_definition.yml10
-rw-r--r--.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml1
-rw-r--r--.rubocop_todo/style/hash_each_methods.yml2
-rw-r--r--.rubocop_todo/style/inline_disable_annotation.yml11
-rw-r--r--app/assets/javascripts/ci/jobs_page/components/job_cells/job_cell.vue4
-rw-r--r--app/assets/javascripts/content_editor/extensions/copy_paste.js10
-rw-r--r--app/assets/javascripts/lib/utils/keys.js1
-rw-r--r--app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue11
-rw-r--r--app/controllers/explore/catalog_controller.rb2
-rw-r--r--data/deprecations/16-6-package-deprecate-two-graphql-fields.yml13
-rw-r--r--db/migrate/20231103195309_remove_deprecated_package_metadata_sync_worker.rb16
-rw-r--r--db/schema_migrations/202311031953091
-rw-r--r--doc/administration/audit_event_streaming/graphql_api.md23
-rw-r--r--doc/administration/backup_restore/backup_gitlab.md5
-rw-r--r--doc/administration/gitaly/configure_gitaly.md4
-rw-r--r--doc/api/graphql/reference/index.md9
-rw-r--r--doc/architecture/blueprints/new_diffs.md10
-rw-r--r--doc/update/deprecations.md18
-rw-r--r--doc/user/ai_features.md43
-rw-r--r--doc/user/application_security/policies/scan-result-policies.md80
-rw-r--r--doc/user/project/repository/code_suggestions/index.md11
-rw-r--r--doc/user/project/repository/code_suggestions/self_managed.md2
-rw-r--r--lib/sidebars/explore/menus/catalog_menu.rb2
-rw-r--r--locale/gitlab.pot23
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb2
-rw-r--r--spec/frontend/ci/jobs_page/components/job_cells/job_cell_spec.js10
-rw-r--r--spec/frontend/content_editor/extensions/copy_paste_spec.js42
-rw-r--r--spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js43
-rw-r--r--spec/models/ci/resource_group_spec.rb2
-rw-r--r--spec/models/concerns/has_user_type_spec.rb2
-rw-r--r--spec/requests/api/graphql/project/environments_spec.rb2
-rw-r--r--spec/services/packages/npm/generate_metadata_service_spec.rb2
-rw-r--r--spec/services/packages/nuget/update_package_from_metadata_service_spec.rb12
-rw-r--r--spec/support/helpers/cycle_analytics_helpers/test_generation.rb166
37 files changed, 327 insertions, 275 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index af65786c3eb..23f4ee435bb 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -1092,3 +1092,8 @@ Cop/ExperimentsTestCoverage:
- 'lib/**/*'
- 'ee/app/**/*'
- 'ee/lib/**/*'
+
+RSpec/UselessDynamicDefinition:
+ Exclude:
+ - 'spec/factories/**/*'
+ - 'ee/spec/factories/**/*'
diff --git a/.rubocop_todo/rspec/before_all_role_assignment.yml b/.rubocop_todo/rspec/before_all_role_assignment.yml
index d4a8b837ae1..9f85e031775 100644
--- a/.rubocop_todo/rspec/before_all_role_assignment.yml
+++ b/.rubocop_todo/rspec/before_all_role_assignment.yml
@@ -1504,7 +1504,6 @@ RSpec/BeforeAllRoleAssignment:
- 'spec/services/work_items/widgets/description_service/update_service_spec.rb'
- 'spec/services/work_items/widgets/hierarchy_service/create_service_spec.rb'
- 'spec/services/work_items/widgets/hierarchy_service/update_service_spec.rb'
- - 'spec/support/helpers/cycle_analytics_helpers/test_generation.rb'
- 'spec/support/shared_contexts/changes_access_checks_shared_context.rb'
- 'spec/support/shared_contexts/design_management_shared_contexts.rb'
- 'spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb'
diff --git a/.rubocop_todo/rspec/context_wording.yml b/.rubocop_todo/rspec/context_wording.yml
index 5b33661b580..e89db09d623 100644
--- a/.rubocop_todo/rspec/context_wording.yml
+++ b/.rubocop_todo/rspec/context_wording.yml
@@ -2764,7 +2764,6 @@ RSpec/ContextWording:
- 'spec/services/wikis/create_attachment_service_spec.rb'
- 'spec/services/work_items/create_service_spec.rb'
- 'spec/services/work_items/parent_links/create_service_spec.rb'
- - 'spec/support/helpers/cycle_analytics_helpers/test_generation.rb'
- 'spec/support/shared_contexts/bulk_imports_requests_shared_context.rb'
- 'spec/support/shared_contexts/changes_access_checks_shared_context.rb'
- 'spec/support/shared_contexts/container_repositories_shared_context.rb'
diff --git a/.rubocop_todo/rspec/useless_dynamic_definition.yml b/.rubocop_todo/rspec/useless_dynamic_definition.yml
deleted file mode 100644
index 75bea5601ae..00000000000
--- a/.rubocop_todo/rspec/useless_dynamic_definition.yml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-RSpec/UselessDynamicDefinition:
- Exclude:
- - 'ee/spec/factories/ci/builds.rb'
- - 'ee/spec/factories/ci/job_artifacts.rb'
- - 'ee/spec/factories/ci/pipelines.rb'
- - 'ee/spec/lib/gitlab/usage/metrics/instrumentations/count_security_scans_metric_spec.rb'
- - 'spec/models/ci/resource_group_spec.rb'
- - 'spec/services/packages/nuget/update_package_from_metadata_service_spec.rb'
- - 'spec/support/helpers/cycle_analytics_helpers/test_generation.rb'
diff --git a/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml b/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml
index 15d1051ae76..0c8affcd964 100644
--- a/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml
+++ b/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml
@@ -405,7 +405,6 @@ SidekiqLoadBalancing/WorkerDataConsistency:
- 'ee/app/workers/merge_trains/refresh_worker.rb'
- 'ee/app/workers/namespaces/sync_namespace_name_worker.rb'
- 'ee/app/workers/new_epic_worker.rb'
- - 'ee/app/workers/package_metadata/sync_worker.rb'
- 'ee/app/workers/personal_access_tokens/groups/policy_worker.rb'
- 'ee/app/workers/personal_access_tokens/instance/policy_worker.rb'
- 'ee/app/workers/projects/register_suggested_reviewers_project_worker.rb'
diff --git a/.rubocop_todo/style/hash_each_methods.yml b/.rubocop_todo/style/hash_each_methods.yml
index 3af43e08634..97e2cb8645a 100644
--- a/.rubocop_todo/style/hash_each_methods.yml
+++ b/.rubocop_todo/style/hash_each_methods.yml
@@ -65,9 +65,7 @@ Style/HashEachMethods:
- 'spec/lib/gitlab/ci/status/build/failed_spec.rb'
- 'spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb'
- 'spec/models/ci/job_artifact_spec.rb'
- - 'spec/models/ci/resource_group_spec.rb'
- 'spec/models/clusters/cluster_spec.rb'
- - 'spec/models/concerns/has_user_type_spec.rb'
- 'spec/models/packages/package_spec.rb'
- 'spec/models/project_spec.rb'
- 'spec/models/user_spec.rb'
diff --git a/.rubocop_todo/style/inline_disable_annotation.yml b/.rubocop_todo/style/inline_disable_annotation.yml
index d2774f1b8e5..87c4ca68ad0 100644
--- a/.rubocop_todo/style/inline_disable_annotation.yml
+++ b/.rubocop_todo/style/inline_disable_annotation.yml
@@ -296,7 +296,6 @@ Style/InlineDisableAnnotation:
- 'app/graphql/types/nested_environment_type.rb'
- 'app/graphql/types/notes/deleted_note_type.rb'
- 'app/graphql/types/notes/diff_position_type.rb'
- - 'app/graphql/types/organizations/organization_user_type.rb'
- 'app/graphql/types/packages/composer/json_type.rb'
- 'app/graphql/types/packages/helm/dependency_type.rb'
- 'app/graphql/types/packages/helm/maintainer_type.rb'
@@ -1781,8 +1780,6 @@ Style/InlineDisableAnnotation:
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_db_embeddings_per_doc_file_worker.rb'
- 'ee/app/workers/llm/embedding/gitlab_documentation/create_empty_embeddings_records_worker.rb'
- 'ee/app/workers/llm/embedding/gitlab_documentation/set_embeddings_on_the_record_worker.rb'
- - 'ee/app/workers/llm/tanuki_bot/recreate_records_worker.rb'
- - 'ee/app/workers/llm/tanuki_bot/remove_previous_records_worker.rb'
- 'ee/app/workers/members_destroyer/clean_up_group_protected_branch_rules_worker.rb'
- 'ee/app/workers/merge_request_reset_approvals_worker.rb'
- 'ee/app/workers/new_epic_worker.rb'
@@ -1790,7 +1787,6 @@ Style/InlineDisableAnnotation:
- 'ee/app/workers/open_ai/clear_conversations_worker.rb'
- 'ee/app/workers/package_metadata/advisories_sync_worker.rb'
- 'ee/app/workers/package_metadata/licenses_sync_worker.rb'
- - 'ee/app/workers/package_metadata/sync_worker.rb'
- 'ee/app/workers/personal_access_tokens/instance/policy_worker.rb'
- 'ee/app/workers/product_analytics/initialize_snowplow_product_analytics_worker.rb'
- 'ee/app/workers/project_template_export_worker.rb'
@@ -2134,7 +2130,6 @@ Style/InlineDisableAnnotation:
- 'ee/spec/lib/remote_development/workspaces/create/creator_spec.rb'
- 'ee/spec/lib/remote_development/workspaces/create/personal_access_token_creator_spec.rb'
- 'ee/spec/lib/remote_development/workspaces/create/post_flatten_devfile_validator_spec.rb'
- - 'ee/spec/lib/remote_development/workspaces/create/pre_flatten_devfile_validator_spec.rb'
- 'ee/spec/lib/remote_development/workspaces/create/workspace_creator_spec.rb'
- 'ee/spec/lib/remote_development/workspaces/create/workspace_variables_creator_spec.rb'
- 'ee/spec/lib/remote_development/workspaces/reconcile/input/factory_spec.rb'
@@ -2955,7 +2950,6 @@ Style/InlineDisableAnnotation:
- 'spec/finders/groups/projects_requiring_authorizations_refresh/on_direct_membership_finder_spec.rb'
- 'spec/finders/groups/projects_requiring_authorizations_refresh/on_transfer_finder_spec.rb'
- 'spec/finders/packages/build_infos_finder_spec.rb'
- - 'spec/finders/packages/group_packages_finder_spec.rb'
- 'spec/fixtures/packages/rubygems/package.gemspec'
- 'spec/frontend/fixtures/merge_requests.rb'
- 'spec/graphql/mutations/clusters/agent_tokens/create_spec.rb'
@@ -3132,7 +3126,6 @@ Style/InlineDisableAnnotation:
- 'spec/lib/omni_auth/strategies/jwt_spec.rb'
- 'spec/lib/result_spec.rb'
- 'spec/mailers/notify_spec.rb'
- - 'spec/metrics_server/metrics_server_spec.rb'
- 'spec/migrations/20230403085957_add_tmp_partial_index_on_vulnerability_report_types2_spec.rb'
- 'spec/migrations/20230426085615_queue_backfill_resource_link_events_spec.rb'
- 'spec/migrations/20230613192703_swap_ci_build_needs_to_big_int_for_self_hosts_spec.rb'
@@ -3186,7 +3179,6 @@ Style/InlineDisableAnnotation:
- 'spec/models/concerns/bulk_insertable_associations_spec.rb'
- 'spec/models/concerns/database_event_tracking_spec.rb'
- 'spec/models/concerns/encrypted_user_password_spec.rb'
- - 'spec/models/concerns/has_user_type_spec.rb'
- 'spec/models/concerns/legacy_bulk_insert_spec.rb'
- 'spec/models/concerns/manual_inverse_association_spec.rb'
- 'spec/models/concerns/noteable_spec.rb'
@@ -3220,7 +3212,6 @@ Style/InlineDisableAnnotation:
- 'spec/requests/api/graphql/groups_query_spec.rb'
- 'spec/requests/api/graphql/issues_spec.rb'
- 'spec/requests/api/graphql/mutations/issues/bulk_update_spec.rb'
- - 'spec/requests/api/graphql/project/environments_spec.rb'
- 'spec/requests/api/group_import_spec.rb'
- 'spec/requests/api/internal/base_spec.rb'
- 'spec/requests/api/ml_model_packages_spec.rb'
@@ -3271,7 +3262,6 @@ Style/InlineDisableAnnotation:
- 'spec/services/packages/debian/create_distribution_service_spec.rb'
- 'spec/services/packages/debian/create_package_file_service_spec.rb'
- 'spec/services/packages/debian/update_distribution_service_spec.rb'
- - 'spec/services/packages/npm/generate_metadata_service_spec.rb'
- 'spec/services/packages/rpm/repository_metadata/build_filelist_xml_service_spec.rb'
- 'spec/services/projects/hashed_storage/base_attachment_service_spec.rb'
- 'spec/services/protected_branches/cache_service_spec.rb'
@@ -3295,7 +3285,6 @@ Style/InlineDisableAnnotation:
- 'spec/support/forgery_protection.rb'
- 'spec/support/frontend_fixtures.rb'
- 'spec/support/helpers/batch_destroy_dependent_associations_helper.rb'
- - 'spec/support/helpers/cycle_analytics_helpers/test_generation.rb'
- 'spec/support/helpers/database/multiple_databases_helpers.rb'
- 'spec/support/helpers/database/table_schema_helpers.rb'
- 'spec/support/helpers/drag_to_helper.rb'
diff --git a/app/assets/javascripts/ci/jobs_page/components/job_cells/job_cell.vue b/app/assets/javascripts/ci/jobs_page/components/job_cells/job_cell.vue
index fbdfc7c9c6a..b97243cf2ca 100644
--- a/app/assets/javascripts/ci/jobs_page/components/job_cells/job_cell.vue
+++ b/app/assets/javascripts/ci/jobs_page/components/job_cells/job_cell.vue
@@ -136,8 +136,8 @@ export default {
v-if="triggered"
variant="info"
:size="$options.badgeSize"
- data-testid="triggered-job-badge"
- >{{ s__('Job|triggered') }}
+ data-testid="trigger-token-job-badge"
+ >{{ s__('Job|trigger token') }}
</gl-badge>
<gl-badge
v-if="showAllowedToFailBadge"
diff --git a/app/assets/javascripts/content_editor/extensions/copy_paste.js b/app/assets/javascripts/content_editor/extensions/copy_paste.js
index 3ae5ef0025d..d29a407c5ca 100644
--- a/app/assets/javascripts/content_editor/extensions/copy_paste.js
+++ b/app/assets/javascripts/content_editor/extensions/copy_paste.js
@@ -106,8 +106,16 @@ export default Extension.create({
const handleCutAndCopy = (view, event) => {
const slice = view.state.selection.content();
- const gfmContent = this.options.serializer.serialize({ doc: slice.content });
+ let gfmContent = this.options.serializer.serialize({ doc: slice.content });
+ const gfmContentWithoutSingleTableCell = gfmContent.replace(
+ /^<table>[\s\n]*<tr>[\s\n]*<t[hd]>|<\/t[hd]>[\s\n]*<\/tr>[\s\n]*<\/table>[\s\n]*$/gim,
+ '',
+ );
+ const containsSingleTableCell = !/<t[hd]>/.test(gfmContentWithoutSingleTableCell);
+ if (containsSingleTableCell) {
+ gfmContent = gfmContentWithoutSingleTableCell;
+ }
const documentFragment = DOMSerializer.fromSchema(view.state.schema).serializeFragment(
slice.content,
);
diff --git a/app/assets/javascripts/lib/utils/keys.js b/app/assets/javascripts/lib/utils/keys.js
index 7cfcd11ece9..e5022551b97 100644
--- a/app/assets/javascripts/lib/utils/keys.js
+++ b/app/assets/javascripts/lib/utils/keys.js
@@ -1,5 +1,6 @@
export const ESC_KEY = 'Escape';
export const ENTER_KEY = 'Enter';
+export const NUMPAD_ENTER_KEY = 'NumpadEnter';
export const BACKSPACE_KEY = 'Backspace';
export const ARROW_DOWN_KEY = 'ArrowDown';
export const ARROW_UP_KEY = 'ArrowUp';
diff --git a/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue b/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue
index 61fa360c41f..e6137bda401 100644
--- a/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue
+++ b/app/assets/javascripts/super_sidebar/components/global_search/components/global_search.vue
@@ -15,7 +15,14 @@ import { truncate } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { sprintf } from '~/locale';
-import { ARROW_DOWN_KEY, ARROW_UP_KEY, END_KEY, HOME_KEY, ESC_KEY } from '~/lib/utils/keys';
+import {
+ ARROW_DOWN_KEY,
+ ARROW_UP_KEY,
+ END_KEY,
+ HOME_KEY,
+ ESC_KEY,
+ NUMPAD_ENTER_KEY,
+} from '~/lib/utils/keys';
import {
COMMAND_PALETTE,
MIN_SEARCH_TERM,
@@ -215,6 +222,8 @@ export default {
this.focusNextItem(event, elements, 1);
} else if (code === ESC_KEY) {
this.$refs.searchModal.close();
+ } else if (code === NUMPAD_ENTER_KEY) {
+ event.target?.firstChild.click();
} else {
stop = false;
}
diff --git a/app/controllers/explore/catalog_controller.rb b/app/controllers/explore/catalog_controller.rb
index 54f1e0b3722..3cd3771129e 100644
--- a/app/controllers/explore/catalog_controller.rb
+++ b/app/controllers/explore/catalog_controller.rb
@@ -14,7 +14,7 @@ module Explore
private
def check_feature_flag
- render_404 unless Feature.enabled?(:global_ci_catalog)
+ render_404 unless Feature.enabled?(:global_ci_catalog, current_user)
end
end
end
diff --git a/data/deprecations/16-6-package-deprecate-two-graphql-fields.yml b/data/deprecations/16-6-package-deprecate-two-graphql-fields.yml
new file mode 100644
index 00000000000..fd9498d5871
--- /dev/null
+++ b/data/deprecations/16-6-package-deprecate-two-graphql-fields.yml
@@ -0,0 +1,13 @@
+- title: "GraphQL: deprecate support for `canDestroy` and `canDelete`"
+ announcement_milestone: "16.6"
+ removal_milestone: "17.0"
+ breaking_change: true
+ reporter: trizzi
+ stage: Package
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/390754
+ body: |
+ The Package Registry user interface relies on the GitLab GraphQL API. To make it easy for everyone to contribute, it's important that the frontend is coded consistently across all GitLab product areas. Before GitLab 16.6, however, the Package Registry UI handled permissions differently from other areas of the product.
+
+ In 16.6, we added a new `UserPermissions` field under the `Types::PermissionTypes::Package` type to align the Package Registry with the rest of GitLab. This new field replaces the `canDestroy` field under the `Package`, `PackageBase`, and `PackageDetailsType` types. It also replaces the field `canDelete` for `ContainerRepository`, `ContainerRepositoryDetails`, and `ContainerRepositoryTag`. In GitLab 17.0, the `canDestroy` and `canDelete` fields will be removed.
+
+ This is a breaking change that will be completed in 17.0.
diff --git a/db/migrate/20231103195309_remove_deprecated_package_metadata_sync_worker.rb b/db/migrate/20231103195309_remove_deprecated_package_metadata_sync_worker.rb
new file mode 100644
index 00000000000..ae461d21799
--- /dev/null
+++ b/db/migrate/20231103195309_remove_deprecated_package_metadata_sync_worker.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class RemoveDeprecatedPackageMetadataSyncWorker < Gitlab::Database::Migration[2.2]
+ milestone '16.6'
+ disable_ddl_transaction!
+
+ DEPRECATED_JOB_CLASSES = %w[PackageMetadata::SyncWorker]
+
+ def up
+ sidekiq_remove_jobs(job_klasses: DEPRECATED_JOB_CLASSES)
+ end
+
+ def down
+ # This migration removes any instances of deprecated workers and cannot be undone.
+ end
+end
diff --git a/db/schema_migrations/20231103195309 b/db/schema_migrations/20231103195309
new file mode 100644
index 00000000000..cb5e21db50d
--- /dev/null
+++ b/db/schema_migrations/20231103195309
@@ -0,0 +1 @@
+d237c0aa5d44d58ee0a32246f3c2911d7515d18cff6b177709a95c3d064d000d \ No newline at end of file
diff --git a/doc/administration/audit_event_streaming/graphql_api.md b/doc/administration/audit_event_streaming/graphql_api.md
index 6e1a3424929..58668902b8e 100644
--- a/doc/administration/audit_event_streaming/graphql_api.md
+++ b/doc/administration/audit_event_streaming/graphql_api.md
@@ -177,9 +177,8 @@ Prerequisites:
- Owner role for a top-level group.
-Users with the Owner role for a group can update streaming destinations' custom HTTP headers using the
-`auditEventsStreamingHeadersUpdate` mutation type. You can retrieve the custom HTTP headers ID
-by [listing all the custom HTTP headers](#list-streaming-destinations) for the group.
+To update streaming destinations for a group, use the `externalAuditEventDestinationUpdate` mutation type. You can retrieve the destinations ID
+by [listing all the streaming destinations](#list-streaming-destinations) for the group.
```graphql
mutation {
@@ -206,6 +205,24 @@ Streaming destination is updated if:
- The returned `errors` object is empty.
- The API responds with `200 OK`.
+Users with the Owner role for a group can update streaming destinations' custom HTTP headers using the
+`auditEventsStreamingHeadersUpdate` mutation type. You can retrieve the custom HTTP headers ID
+by [listing all the custom HTTP headers](#list-streaming-destinations) for the group.
+
+```graphql
+mutation {
+ auditEventsStreamingHeadersUpdate(input: { headerId: "gid://gitlab/AuditEvents::Streaming::Header/2", key: "new-key", value: "new-value", active: false }) {
+ errors
+ header {
+ id
+ key
+ value
+ active
+ }
+ }
+}
+```
+
Group owners can remove an HTTP header using the GraphQL `auditEventsStreamingHeadersDestroy` mutation. You can retrieve the header ID
by [listing all the custom HTTP headers](#list-streaming-destinations) for the group.
diff --git a/doc/administration/backup_restore/backup_gitlab.md b/doc/administration/backup_restore/backup_gitlab.md
index b4cc2b48e37..5c0fcbbc4ef 100644
--- a/doc/administration/backup_restore/backup_gitlab.md
+++ b/doc/administration/backup_restore/backup_gitlab.md
@@ -437,7 +437,9 @@ sudo -u git -H bundle exec rake gitlab:backup:create SKIP=tar RAILS_ENV=producti
#### Create server-side repository backups
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4941) in GitLab 16.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4941) in GitLab 16.3.
+> - Server-side support for restoring a specified backup instead of the latest backup [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132188) in GitLab 16.6.
+> - Server-side support for creating incremental backups [introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6475) in GitLab 16.6.
Instead of storing large repository backups in the backup archive, repository
backups can be configured so that the Gitaly node that hosts each repository is
@@ -504,6 +506,7 @@ sudo -u git -H bundle exec rake gitlab:backup:create GITLAB_BACKUP_MAX_CONCURREN
> - Introduced in GitLab 14.9 [with a flag](../feature_flags.md) named `incremental_repository_backup`. Disabled by default.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/355945) in GitLab 14.10.
> - `PREVIOUS_BACKUP` option [introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4184) in GitLab 15.0.
+> - Server-side support for creating incremental backups [introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6475) in GitLab 16.6.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature, an administrator can [disable the feature flag](../feature_flags.md) named `incremental_repository_backup`.
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index 5a7c7c70a42..ffa77a0081d 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -1712,7 +1712,9 @@ Gitaly fails to start up if either:
## Configure server-side backups
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4941) in GitLab 16.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4941) in GitLab 16.3.
+> - Server-side support for restoring a specified backup instead of the latest backup [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132188) in GitLab 16.6.
+> - Server-side support for creating incremental backups [introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6475) in GitLab 16.6.
Repository backups can be configured so that the Gitaly node that hosts each
repository is responsible for creating the backup and streaming it to
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 5d7cc02c7d7..987a94736a3 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1259,6 +1259,7 @@ Input type: `AiActionInput`
| <a id="mutationaiactiongeneratecommitmessage"></a>`generateCommitMessage` | [`AiGenerateCommitMessageInput`](#aigeneratecommitmessageinput) | Input for generate_commit_message AI action. |
| <a id="mutationaiactiongeneratedescription"></a>`generateDescription` | [`AiGenerateDescriptionInput`](#aigeneratedescriptioninput) | Input for generate_description AI action. |
| <a id="mutationaiactiongeneratetestfile"></a>`generateTestFile` | [`GenerateTestFileInput`](#generatetestfileinput) | Input for generate_test_file AI action. |
+| <a id="mutationaiactionresolvevulnerability"></a>`resolveVulnerability` | [`AiResolveVulnerabilityInput`](#airesolvevulnerabilityinput) | Input for resolve_vulnerability AI action. |
| <a id="mutationaiactionsummarizecomments"></a>`summarizeComments` | [`AiSummarizeCommentsInput`](#aisummarizecommentsinput) | Input for summarize_comments AI action. |
| <a id="mutationaiactionsummarizereview"></a>`summarizeReview` | [`AiSummarizeReviewInput`](#aisummarizereviewinput) | Input for summarize_review AI action. |
| <a id="mutationaiactiontanukibot"></a>`tanukiBot` | [`AiTanukiBotInput`](#aitanukibotinput) | Input for tanuki_bot AI action. |
@@ -32331,6 +32332,14 @@ see the associated mutation type above.
| <a id="aigeneratedescriptioninputdescriptiontemplatename"></a>`descriptionTemplateName` | [`String`](#string) | Name of the description template to use to generate message off of. |
| <a id="aigeneratedescriptioninputresourceid"></a>`resourceId` | [`AiModelID!`](#aimodelid) | Global ID of the resource to mutate. |
+### `AiResolveVulnerabilityInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="airesolvevulnerabilityinputresourceid"></a>`resourceId` | [`AiModelID!`](#aimodelid) | Global ID of the resource to mutate. |
+
### `AiSummarizeCommentsInput`
#### Arguments
diff --git a/doc/architecture/blueprints/new_diffs.md b/doc/architecture/blueprints/new_diffs.md
index cb9715cddda..af1e4679c14 100644
--- a/doc/architecture/blueprints/new_diffs.md
+++ b/doc/architecture/blueprints/new_diffs.md
@@ -87,6 +87,16 @@ Simplicity is the opposite of complexity. This uses a definition of simple and c
- Maintainable projects expand on simple code by having simple structure (folders define classes of behaviors, e.g. you can be assured that a component directory will never initiate a network call, because that would be complecting visual display with data access)
- Maintainable applications flow out of simple organization and simple code. The old saying is a cluttered desk is representative of a cluttered mind. Rigorous discipline on simplicity will be represented in our output (the product). By being strict about working simply, we will naturally produce applications where our users can more easily reason about their behavior.
+#### Done
+
+GitLab has an existing [definition of done](/ee/development/contributing/merge_request_workflow.md#definition-of-done) which is geared primarily toward identifying when an MR is ready to be merged.
+
+In addition to the items in the GitLab definition of done, work on new diffs should also adhere to the following requirements:
+
+- Meets or exceeds all metrics
+ - Meets or exceeds our minimum accessibility metrics (these are explicitly not part of our defined priorities, since they are non-negotiable)
+- All work is fully documented for engineers (user documentation is a requirement of the standard definition of done)
+
<!--
This section should contain enough information that the specifics of your
change are understandable. This may include API specs (though not always
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 0cfdf00ec48..dba4a328fb9 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -638,6 +638,24 @@ In GitLab 17.0, the `DISABLED_WITH_OVERRIDE` value of the `SharedRunnersSetting`
<div class="deprecation breaking-change" data-milestone="17.0">
+### GraphQL: deprecate support for `canDestroy` and `canDelete`
+
+<div class="deprecation-notes">
+- Announced in GitLab <span class="milestone">16.6</span>
+- Removal in GitLab <span class="milestone">17.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change))
+- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/390754).
+</div>
+
+The Package Registry user interface relies on the GitLab GraphQL API. To make it easy for everyone to contribute, it's important that the frontend is coded consistently across all GitLab product areas. Before GitLab 16.6, however, the Package Registry UI handled permissions differently from other areas of the product.
+
+In 16.6, we added a new `UserPermissions` field under the `Types::PermissionTypes::Package` type to align the Package Registry with the rest of GitLab. This new field replaces the `canDestroy` field under the `Package`, `PackageBase`, and `PackageDetailsType` types. It also replaces the field `canDelete` for `ContainerRepository`, `ContainerRepositoryDetails`, and `ContainerRepositoryTag`. In GitLab 17.0, the `canDestroy` and `canDelete` fields will be removed.
+
+This is a breaking change that will be completed in 17.0.
+
+</div>
+
+<div class="deprecation breaking-change" data-milestone="17.0">
+
### HashiCorp Vault integration will no longer use CI_JOB_JWT by default
<div class="deprecation-notes">
diff --git a/doc/user/ai_features.md b/doc/user/ai_features.md
index 87fcc924c51..222752a4561 100644
--- a/doc/user/ai_features.md
+++ b/doc/user/ai_features.md
@@ -7,12 +7,16 @@ type: index, reference
# GitLab Duo
+> - [First GitLab Duo features introduced](https://about.gitlab.com/blog/2023/05/03/gitlab-ai-assisted-features/) in GitLab 16.0.
+> - [Removed third-party AI setting](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136144) in GitLab 16.6.
+> - [Removed support for OpenAI from all GitLab Duo features](https://gitlab.com/groups/gitlab-org/-/epics/10964) in GitLab 16.6.
+
GitLab is creating AI-assisted features across our DevSecOps platform. These features aim to help increase velocity and solve key pain points across the software development lifecycle.
| Feature | Purpose | Large Language Model | Current availability | Maturity |
|-|-|-|-|-|
| [Suggested Reviewers](project/merge_requests/reviews/index.md#gitlab-duo-suggested-reviewers) | Assists in creating faster and higher-quality reviews by automatically suggesting reviewers for your merge request. | GitLab creates a machine learning model for each project, which is used to generate reviewers <br><br> [View the issue](https://gitlab.com/gitlab-org/modelops/applied-ml/applied-ml-updates/-/issues/10) | SaaS only <br><br> Ultimate tier | [Generally Available (GA)](../policy/experiment-beta-support.md#generally-available-ga) |
-| [Code Suggestions](project/repository/code_suggestions/index.md) | Helps you write code more efficiently by viewing code suggestions as you type. | For Code Completion: Vertex AI Codey [`code-gecko`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-completion) and Anthropic [`Claude-instant-1.2`](https://docs.anthropic.com/claude/reference/selecting-a-model) <br><br> For Code Generation: Vertex AI Codey [`code-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-generation) and Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model)| [SaaS: All tiers](project/repository/code_suggestions/saas.md) <br><br> [Self-managed: Premium and Ultimate with Cloud Licensing](project/repository/code_suggestions/self_managed.md) | [Beta](../policy/experiment-beta-support.md#beta) |
+| [Code Suggestions](project/repository/code_suggestions/index.md) | Helps you write code more efficiently by viewing code suggestions as you type. | For Code Completion: Vertex AI Codey [`code-gecko`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-completion) <br><br> For Code Generation: Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model)| [SaaS: All tiers](project/repository/code_suggestions/saas.md) <br><br> [Self-managed: Premium and Ultimate with Cloud Licensing](project/repository/code_suggestions/self_managed.md) | [Beta](../policy/experiment-beta-support.md#beta) |
| [Vulnerability summary](application_security/vulnerabilities/index.md#explaining-a-vulnerability) | Helps you remediate vulnerabilities more efficiently, boost your skills, and write more secure code. | Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text) <br><br> Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) if degraded performance | SaaS only <br><br> Ultimate tier | [Beta](../policy/experiment-beta-support.md#beta) |
| [Code explanation](#explain-code-in-the-web-ui-with-code-explanation) | Helps you understand code by explaining it in English language. | Vertex AI Codey [`codechat-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-chat) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
| [GitLab Duo Chat](gitlab_duo_chat.md) | Process and generate text and code in a conversational manner. Helps you quickly identify useful information in large volumes of text in issues, epics, code, and GitLab documentation. | Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) <br><br> Vertex AI Codey [`textembedding-gecko`](https://cloud.google.com/vertex-ai/docs/generative-ai/embeddings/get-text-embeddings) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
@@ -24,7 +28,7 @@ GitLab is creating AI-assisted features across our DevSecOps platform. These fea
| [Test generation](project/merge_requests/ai_in_merge_requests.md#generate-suggested-tests-in-merge-requests) | Automates repetitive tasks and helps catch bugs early. | Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
| [Git suggestions](https://gitlab.com/gitlab-org/gitlab/-/issues/409636) | Helps you discover or recall Git commands when and where you need them. | Vertex AI Codey [`codechat-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/code-chat) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
| [Root cause analysis](#root-cause-analysis) | Assists you in determining the root cause for a pipeline failure and failed CI/CD build. | Vertex AI Codey [`text-bison`](https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/text) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
-| [Issue description generation](#summarize-an-issue-with-issue-description-generation) | Generate issue descriptions. | OpenAI's [`GPT-3`](https://platform.openai.com/docs/models/gpt-3) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
+| [Issue description generation](#summarize-an-issue-with-issue-description-generation) | Generate issue descriptions. | Anthropic [`Claude-2`](https://docs.anthropic.com/claude/reference/selecting-a-model) | SaaS only <br><br> Ultimate tier | [Experiment](../policy/experiment-beta-support.md#experiment) |
## Enable AI/ML features
@@ -184,7 +188,7 @@ For details about this Experimental feature, see [GitLab Duo Chat](gitlab_duo_ch
## Data usage
-GitLab AI features leverage generative AI to help increase velocity and aim to help make you more productive. Each feature operates independently of other features and is not required for other features to function.
+GitLab AI features leverage generative AI to help increase velocity and aim to help make you more productive. Each feature operates independently of other features and is not required for other features to function. GitLab selects the best-in-class large-language models for specific tasks. We use [Google Vertex AI Models](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/overview#genai-models) and [Anthropic Claude](https://www.anthropic.com/product).
### Progressive enhancement
@@ -194,11 +198,38 @@ These features are designed as a progressive enhancement to existing GitLab feat
These features are in a variety of [feature support levels](../policy/experiment-beta-support.md#beta). Due to the nature of these features, there may be high demand for usage which may cause degraded performance or unexpected downtime of the feature. We have built these features to gracefully degrade and have controls in place to allow us to mitigate abuse or misuse. GitLab may disable **beta and experimental** features for any or all customers at any time at our discretion.
-## Third party services
-
### Data privacy
-Some AI features require the use of third-party AI services models and APIs from: Google AI and OpenAI. The processing of any personal data is in accordance with our [Privacy Statement](https://about.gitlab.com/privacy/). You may also visit the [Sub-Processors page](https://about.gitlab.com/privacy/subprocessors/#third-party-sub-processors) to see the list of our Sub-Processors that we use to provide these features.
+GitLab Duo AI features are powered by a generative AI models. The processing of any personal data is in accordance with our [Privacy Statement](https://about.gitlab.com/privacy/). You may also visit the [Sub-Processors page](https://about.gitlab.com/privacy/subprocessors/#third-party-sub-processors) to see the list of our Sub-Processors that we use to provide these features.
+
+### Data retention
+
+The below reflects the current retention periods of GitLab AI model [Sub-Processors](https://about.gitlab.com/privacy/subprocessors/#third-party-sub-processors):
+
+- Anthropic retains input and output data for 30 days.
+- Google discards input and output data immediately after the output is provided. Google currently does not store data for abuse monitoring.
+
+All of these AI providers are under data protection agreements with GitLab that prohibit the use of Customer Content for their own purposes, except to perform their independent legal obligations.
+
+### Telemetry
+
+GitLab Duo collects aggregated or de-identified first-party usage data through our [Snowplow collector](https://about.gitlab.com/handbook/business-technology/data-team/platform/snowplow/). This usage data includes the following metrics:
+
+- Number of unique users
+- Number of unique instances
+- Prompt lengths
+- Model used
+- Status code responses
+- API responses times
+
+### Training data
+
+GitLab does not train generative AI models based on private (non-public) data. The vendors we work with also do not train models based on private data.
+
+For more information on our AI [sub-processors](https://about.gitlab.com/privacy/subprocessors/#third-party-sub-processors), see:
+
+- Google Vertex AI Models APIs [data governance](https://cloud.google.com/vertex-ai/docs/generative-ai/data-governance) and [responsible AI](https://cloud.google.com/vertex-ai/docs/generative-ai/learn/responsible-ai).
+- Anthropic Claude's [constitution](https://www.anthropic.com/index/claudes-constitution).
### Model accuracy and quality
diff --git a/doc/user/application_security/policies/scan-result-policies.md b/doc/user/application_security/policies/scan-result-policies.md
index d70463f4056..d0d3cb2ca03 100644
--- a/doc/user/application_security/policies/scan-result-policies.md
+++ b/doc/user/application_security/policies/scan-result-policies.md
@@ -27,13 +27,18 @@ The following video gives you an overview of GitLab scan result policies:
<iframe src="https://www.youtube-nocookie.com/embed/w5I9gcUgr9U" frameborder="0" allowfullscreen> </iframe>
</figure>
+## Requirements and limitations
+
+- You must add the respective [security scanning tools](../index.md#application-coverage).
+ Otherwise, scan result policies do not have any effect.
+- The maximum number of policies is five.
+- Each policy can have a maximum of five rules.
+- All configured scanners must be present in the merge request's latest pipeline. If not, approvals are required even if some vulnerability criteria have not been met.
+
## Merge request with multiple pipelines
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/379108) in GitLab 16.2 [with a flag](../../../administration/feature_flags.md) named `multi_pipeline_scan_result_policies`. Disabled by default.
-> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/409482) in GitLab 16.3.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, an administrator can [disable the feature flag](../../../administration/feature_flags.md) named `multi_pipeline_scan_result_policies`. On GitLab.com, this feature is available.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/409482) in GitLab 16.3. Feature flag `multi_pipeline_scan_result_policies` removed.
A project can have multiple pipeline types configured. A single commit can initiate multiple
pipelines, each of which may contain a security scan.
@@ -78,36 +83,31 @@ When you save a new policy, GitLab validates its contents against [this JSON sch
If you're not familiar with how to read [JSON schemas](https://json-schema.org/),
the following sections and tables provide an alternative.
-| Field | Type | Required | Possible values | Description |
-|-------|------|----------|-----------------|-------------|
-| `scan_result_policy` | `array` of Scan Result Policy | true | | List of scan result policies (maximum 5). |
+| Field | Type | Required | Possible values | Description |
+|----------------------|-------------------------------|----------|-----------------|------------------------------------------|
+| `scan_result_policy` | `array` of Scan Result Policy | true | | List of scan result policies (maximum 5). |
## Scan result policy schema
-> The `approval_settings` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418752) in GitLab 16.4 [with a flag](../../../administration/feature_flags.md) named `scan_result_any_merge_request`. Disabled by default.
+> The `approval_settings` fields was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418752) in GitLab 16.4 [with flags](../../../administration/feature_flags.md) named `scan_result_policies_block_unprotecting_branches`, `scan_result_any_merge_request`, or `scan_result_policies_block_force_push`. All are disabled by default.
FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available, ask an administrator to [enable the feature flag](../../../administration/feature_flags.md) named `scan_result_any_merge_request`.
-On GitLab.com, this feature is not available.
+On self-managed GitLab, by default the `approval_settings` field is unavailable. To show the feature, an administrator can [enable the feature flags](../../../administration/feature_flags.md) named `scan_result_policies_block_unprotecting_branches`, `scan_result_any_merge_request`, or `scan_result_policies_block_force_push`. See the `approval_settings` section below for more information.
| Field | Type | Required |Possible values | Description |
-|-------|------|----------|----------------|-------------|
+|--------|------|----------|----------------|-------------|
| `name` | `string` | true | | Name of the policy. Maximum of 255 characters.|
-| `description` (optional) | `string` | true | | Description of the policy. |
+| `description` | `string` | false | | Description of the policy. |
| `enabled` | `boolean` | true | `true`, `false` | Flag to enable (`true`) or disable (`false`) the policy. |
| `rules` | `array` of rules | true | | List of rules that the policy applies. |
-| `actions` | `array` of actions | false| | List of actions that the policy enforces. |
-| `approval_settings` | `object` | false | `{prevent_approval_by_author: boolean, prevent_approval_by_commit_author: boolean, remove_approvals_with_new_commit: boolean, require_password_to_approve: boolean}` | Project settings that the policy overrides. |
+| `actions` | `array` of actions | false | | List of actions that the policy enforces. |
+| `approval_settings` | `object` | false | | Project settings that the policy overrides. |
## `scan_finding` rule type
-> - The scan result policy field `vulnerability_attributes` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123052) in GitLab 16.2 [with a flag](../../../administration/feature_flags.md) named `enforce_vulnerability_attributes_rules`. [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/418784) in GitLab 16.3. Feature flag `enforce_vulnerability_attributes_rules` removed in GitLab 16.5.
+> - The scan result policy field `vulnerability_attributes` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123052) in GitLab 16.2 [with a flag](../../../administration/feature_flags.md) named `enforce_vulnerability_attributes_rules`. [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/418784) in GitLab 16.3. Feature flag removed.
> - The scan result policy field `vulnerability_age` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123956) in GitLab 16.2.
-> - The `branch_exceptions` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418741) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. Generally available in GitLab 16.5. Feature flag removed.
-
-FLAG:
-On self-managed GitLab, by default the `branch_exceptions` field is available. To hide the feature, an administrator can [disable the feature flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`.
-On GitLab.com, this feature is available.
+> - The `branch_exceptions` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418741) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133753) in GitLab 16.5. Feature flag removed.
This rule enforces the defined actions based on security scan findings.
@@ -128,11 +128,7 @@ This rule enforces the defined actions based on security scan findings.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/8092) in GitLab 15.9 [with a flag](../../../administration/feature_flags.md) named `license_scanning_policies`.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/397644) in GitLab 15.11. Feature flag `license_scanning_policies` removed.
-> - The `branch_exceptions` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418741) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. Enabled by default.
-
-FLAG:
-On self-managed GitLab, by default the `branch_exceptions` field is available. To hide the feature, an administrator can [disable the feature flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`.
-On GitLab.com, this feature is available.
+> - The `branch_exceptions` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418741) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. Enabled by default. [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133753) in GitLab 16.5. Feature flag removed.
This rule enforces the defined actions based on license findings.
@@ -148,12 +144,11 @@ This rule enforces the defined actions based on license findings.
## `any_merge_request` rule type
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418752) in GitLab 16.4.
-> - The `branch_exceptions` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418741) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. Enabled by default.
+> - The `branch_exceptions` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418741) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. Enabled by default. [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133753) in GitLab 16.5. Feature flag removed.
+> - The `any_merge_request` rule type was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418752) in GitLab 16.4. Disabled by default.
FLAG:
-On self-managed GitLab, by default the `branch_exceptions` field is available. To hide the feature, an administrator can [disable the feature flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`.
-On GitLab.com, this feature is available.
+On self-managed GitLab, by default the `any_merge_request` field is not available. To show the feature, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `any_merge_request`.
This rule enforces the defined actions for any merge request based on the commits signature.
@@ -180,13 +175,28 @@ the defined policy.
| `group_approvers_ids` | `array` of `integer` | false | ID of one of more groups | The IDs of groups to consider as approvers. Users with [direct membership in the group](../../project/merge_requests/approvals/rules.md#group-approvers) are eligible to approve. |
| `role_approvers` | `array` of `string` | false | One or more [roles](../../../user/permissions.md#roles) (for example: `owner`, `maintainer`) | The roles to consider as approvers that are eligible to approve. |
-Requirements and limitations:
+## `approval_settings`
-- You must add the respective [security scanning tools](../index.md#application-coverage).
- Otherwise, scan result policies do not have any effect.
-- The maximum number of policies is five.
-- Each policy can have a maximum of five rules.
-- All configured scanners must be present in the merge request's latest pipeline. If not, approvals are required even if some vulnerability criteria have not been met.
+> - The `block_unprotecting_branches` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/423101) in GitLab 16.4 [with flag](../../../administration/feature_flags.md) named `scan_result_policy_settings`. Disabled by default.
+> - The `scan_result_policy_settings` feature flag was replaced by the `scan_result_policies_block_unprotecting_branches` feature flag in 16.4.
+> - The `prevent_approval_by_author`, `prevent_approval_by_commit_author`, `remove_approvals_with_new_commit`, and `require_password_to_approve` fields were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/418752) in GitLab 16.4 [with flag](../../../administration/feature_flags.md) named `scan_result_any_merge_request`. Disabled by default.
+> - The `prevent_force_pushing` field was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/420629) in GitLab 16.4 [with flag](../../../administration/feature_flags.md) named `scan_result_policies_block_force_push`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default the `block_unprotecting_branches` field is unavailable. To show the feature, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `scan_result_policies_block_unprotecting_branches`. On GitLab.com, this feature is unavailable.
+On self-managed GitLab, by default the `prevent_approval_by_author`, `prevent_approval_by_commit_author`, `remove_approvals_with_new_commit`, and `require_password_to_approve` fields are unavailable. To show the feature, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `scan_result_any_merge_request`. On GitLab.com, this feature is available.
+On self-managed GitLab, by default the `prevent_force_pushing` field is unavailable. To show the feature, an administrator can [enable the feature flag](../../../administration/feature_flags.md) named `security_policies_branch_exceptions`. On GitLab.com, this feature is unavailable.
+
+The settings set in the policy overwrite settings in the project.
+
+| Field | Type | Required | Possible values | Description |
+|-------|------|----------|-----------------|-------------|
+| `block_unprotecting_branches` | `boolean` | false | `true`, `false` | Prevent a user from removing a branch from the protected branches list, deleting a protected branch, or changing the default branch if that branch is included in the security policy. |
+| `prevent_approval_by_author` | `boolean` | false | `true`, `false` | When enabled, two person approval is required on all MRs as merge request authors cannot approve their own MRs and merge them unilaterally. |
+| `prevent_approval_by_commit_author` | `boolean` | false | `true`, `false` | When enabled, users who have contributed code to the MR are ineligible for approval, ensuring code committers cannot introduce vulnerabilities and approve code to merge. |
+| `remove_approvals_with_new_commit` | `boolean` | false | `true`, `false` | If an MR receives all necessary approvals to merge, but then a new commit is added, new approvals are required. This ensures new commits that may include vulnerabilities cannot be introduced. |
+| `require_password_to_approve` | `boolean` | false | `true`, `false` | Password confirmation on approvals provides an additional level of security. Enabling this enforces the setting on all projects targeted by this policy. |
+| `prevent_force_pushing` | `boolean` | false | `true`, `false` | Prevent pushing and force pushing to a protected branch. |
## Example security scan result policies project
diff --git a/doc/user/project/repository/code_suggestions/index.md b/doc/user/project/repository/code_suggestions/index.md
index 8cdee773253..b44e26f8daf 100644
--- a/doc/user/project/repository/code_suggestions/index.md
+++ b/doc/user/project/repository/code_suggestions/index.md
@@ -17,6 +17,11 @@ Beta users should read about the [known limitations](#known-limitations). We loo
Write code more efficiently by using generative AI to suggest code while you're developing.
+Code Suggestions supports two distinct types of interactions:
+
+- Code Completion, which suggests completions the current line you are typing. These suggestions are usually low latency.
+- Code Generation, which generates code based on a natural language code comment block. Generating code can exceed multiple seconds.
+
GitLab Duo Code Suggestions are available:
- On [self-managed](self_managed.md) and [SaaS](saas.md).
@@ -31,7 +36,7 @@ GitLab Duo Code Suggestions are available:
</figure>
During Beta, usage of Code Suggestions is governed by the [GitLab Testing Agreement](https://about.gitlab.com/handbook/legal/testing-agreement/).
-Learn about [data usage when using Code Suggestions](#code-suggestions-data-usage).
+Learn about [data usage when using Code Suggestions](#code-suggestions-data-usage). As Code Suggestions matures to General Availibility it will be governed by our [AI Functionality Terms](https://about.gitlab.com/handbook/legal/ai-functionality-terms/).
## Use Code Suggestions
@@ -120,10 +125,12 @@ This improvement should result in:
Code Suggestions is powered by a generative AI model.
Your personal access token enables a secure API connection to GitLab.com or to your GitLab instance.
-This API connection securely transmits a context window from your IDE/editor to the [GitLab AI Gateway](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist), a GitLab hosted service. The gateway calls the large language model APIs, and then the generated suggestion is transmitted back to your IDE/editor.
+This API connection securely transmits a context window from your IDE/editor to the [GitLab AI Gateway](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist), a GitLab hosted service. The [gateway](../../../../development/ai_architecture.md) calls the large language model APIs, and then the generated suggestion is transmitted back to your IDE/editor.
GitLab selects the best-in-class large-language models for specific tasks. We use [Google Vertex AI Code Models](https://cloud.google.com/vertex-ai/docs/generative-ai/code/code-models-overview) and [Anthropic Claude](https://www.anthropic.com/product) for Code Suggestions.
+[View data retention policies](../../../ai_features.md#data-retention).
+
### Telemetry
For self-managed instances that have enabled Code Suggestions and SaaS accounts, we collect aggregated or de-identified first-party usage data through our [Snowplow collector](https://about.gitlab.com/handbook/business-technology/data-team/platform/snowplow/). This usage data includes the following metrics:
diff --git a/doc/user/project/repository/code_suggestions/self_managed.md b/doc/user/project/repository/code_suggestions/self_managed.md
index ee501212027..fd363e56021 100644
--- a/doc/user/project/repository/code_suggestions/self_managed.md
+++ b/doc/user/project/repository/code_suggestions/self_managed.md
@@ -164,7 +164,7 @@ A self-managed GitLab instance does not generate the code suggestion. After succ
authentication to the self-managed instance, a token is generated.
The IDE/editor then uses this token to securely transmit data directly to
-GitLab.com's Code Suggestions service for processing.
+GitLab.com's Code Suggestions service via the [Cloud Connector gateway service](../../../../architecture/blueprints/cloud_connector/index.md) for processing.
The Code Suggestions service then securely returns an AI-generated code suggestion.
diff --git a/lib/sidebars/explore/menus/catalog_menu.rb b/lib/sidebars/explore/menus/catalog_menu.rb
index 687217c75a0..2d8e8bba08b 100644
--- a/lib/sidebars/explore/menus/catalog_menu.rb
+++ b/lib/sidebars/explore/menus/catalog_menu.rb
@@ -21,7 +21,7 @@ module Sidebars
override :render?
def render?
- Feature.enabled?(:global_ci_catalog)
+ Feature.enabled?(:global_ci_catalog, current_user)
end
override :active_routes
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 48862b6afea..0142f794ecf 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -12595,6 +12595,9 @@ msgstr ""
msgid "ComplianceStandardsAdherence|At least two approvals"
msgstr ""
+msgid "ComplianceStandardsAdherence|Check"
+msgstr ""
+
msgid "ComplianceStandardsAdherence|Failure reason"
msgstr ""
@@ -12610,9 +12613,15 @@ msgstr ""
msgid "ComplianceStandardsAdherence|How to fix"
msgstr ""
+msgid "ComplianceStandardsAdherence|Last Scanned"
+msgstr ""
+
msgid "ComplianceStandardsAdherence|Merge request approval rules"
msgstr ""
+msgid "ComplianceStandardsAdherence|More Information"
+msgstr ""
+
msgid "ComplianceStandardsAdherence|No projects with standards adherence checks found"
msgstr ""
@@ -12631,9 +12640,18 @@ msgstr ""
msgid "ComplianceStandardsAdherence|Prevent committers as approvers"
msgstr ""
+msgid "ComplianceStandardsAdherence|Project"
+msgstr ""
+
msgid "ComplianceStandardsAdherence|Requirement"
msgstr ""
+msgid "ComplianceStandardsAdherence|Standard"
+msgstr ""
+
+msgid "ComplianceStandardsAdherence|Status"
+msgstr ""
+
msgid "ComplianceStandardsAdherence|Success reason"
msgstr ""
@@ -12649,6 +12667,9 @@ msgstr ""
msgid "ComplianceStandardsAdherence|View details"
msgstr ""
+msgid "ComplianceStandardsAdherence|View details (fix available)"
+msgstr ""
+
msgid "ComplianceViolations|Compliance Violations Export"
msgstr ""
@@ -27521,7 +27542,7 @@ msgstr ""
msgid "Job|manual"
msgstr ""
-msgid "Job|triggered"
+msgid "Job|trigger token"
msgstr ""
msgid "Join GitLab today! You and your team can plan, build, and ship secure code all in one application. Get started here for free!"
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index e4a944eb837..a2698bc0153 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -203,7 +203,7 @@ RSpec.describe Packages::GroupPackagesFinder do
end
context 'group has package of all types' do
- package_types.each do |pt| # rubocop:disable RSpec/UselessDynamicDefinition
+ package_types.each do |pt| # rubocop:disable RSpec/UselessDynamicDefinition -- `pt` used in `let`
let_it_be("package_#{pt}") { create("#{pt}_package", project: project) }
end
diff --git a/spec/frontend/ci/jobs_page/components/job_cells/job_cell_spec.js b/spec/frontend/ci/jobs_page/components/job_cells/job_cell_spec.js
index bb44d970bd7..68ff2403b30 100644
--- a/spec/frontend/ci/jobs_page/components/job_cells/job_cell_spec.js
+++ b/spec/frontend/ci/jobs_page/components/job_cells/job_cell_spec.js
@@ -107,11 +107,11 @@ describe('Job Cell', () => {
});
it.each`
- testId | text
- ${'manual-job-badge'} | ${'manual'}
- ${'triggered-job-badge'} | ${'triggered'}
- ${'fail-job-badge'} | ${'allowed to fail'}
- ${'delayed-job-badge'} | ${'delayed'}
+ testId | text
+ ${'manual-job-badge'} | ${'manual'}
+ ${'trigger-token-job-badge'} | ${'trigger token'}
+ ${'fail-job-badge'} | ${'allowed to fail'}
+ ${'delayed-job-badge'} | ${'delayed'}
`('displays the static $text badge', ({ testId, text }) => {
createComponent({
manualJob: true,
diff --git a/spec/frontend/content_editor/extensions/copy_paste_spec.js b/spec/frontend/content_editor/extensions/copy_paste_spec.js
index 49839db44cf..e290b4e5137 100644
--- a/spec/frontend/content_editor/extensions/copy_paste_spec.js
+++ b/spec/frontend/content_editor/extensions/copy_paste_spec.js
@@ -9,6 +9,10 @@ import Bold from '~/content_editor/extensions/bold';
import BulletList from '~/content_editor/extensions/bullet_list';
import ListItem from '~/content_editor/extensions/list_item';
import Italic from '~/content_editor/extensions/italic';
+import Table from '~/content_editor/extensions/table';
+import TableCell from '~/content_editor/extensions/table_cell';
+import TableRow from '~/content_editor/extensions/table_row';
+import TableHeader from '~/content_editor/extensions/table_header';
import { VARIANT_DANGER } from '~/alert';
import eventHubFactory from '~/helpers/event_hub_factory';
import { ALERT_EVENT } from '~/content_editor/constants';
@@ -65,6 +69,10 @@ describe('content_editor/extensions/copy_paste', () => {
Heading,
BulletList,
ListItem,
+ Table,
+ TableCell,
+ TableRow,
+ TableHeader,
CopyPaste.configure({ renderMarkdown, eventHub, serializer: new MarkdownSerializer() }),
],
});
@@ -167,6 +175,40 @@ describe('content_editor/extensions/copy_paste', () => {
});
});
+ describe('when copying content with a single table cell', () => {
+ it('sets the clipboard data properly', () => {
+ const event = buildClipboardEvent({ eventName: 'copy' });
+
+ tiptapEditor.commands.insertContent('<table><tr><td>Cell 1</td></tr></table>');
+ tiptapEditor.commands.selectAll();
+ tiptapEditor.view.dispatchEvent(event);
+
+ expect(event.clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', 'Cell 1');
+ });
+ });
+
+ describe('when copying content with a table with multiple cells', () => {
+ it('sets the clipboard data properly', () => {
+ const event = buildClipboardEvent({ eventName: 'copy' });
+
+ tiptapEditor.commands.insertContent('<table><tr><td>Cell 1</td><td>Cell 2</td></tr></table>');
+ tiptapEditor.commands.selectAll();
+ tiptapEditor.view.dispatchEvent(event);
+
+ expect(event.clipboardData.setData).toHaveBeenCalledWith(
+ 'text/x-gfm',
+ `<table>
+<tr>
+<td>Cell 1</td>
+<td>Cell 2</td>
+</tr>
+</table>
+
+`,
+ );
+ });
+ });
+
describe('when pasting raw markdown source', () => {
it('shows a loading indicator while markdown is being processed', async () => {
await triggerPasteEventHandler(buildClipboardEvent());
diff --git a/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js b/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js
index 038c7a96adc..c1258294110 100644
--- a/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js
+++ b/spec/frontend/super_sidebar/components/global_search/components/global_search_spec.js
@@ -25,7 +25,14 @@ import {
} from '~/super_sidebar/components/global_search/constants';
import { truncate } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
-import { ENTER_KEY } from '~/lib/utils/keys';
+import {
+ ENTER_KEY,
+ ARROW_DOWN_KEY,
+ ARROW_UP_KEY,
+ END_KEY,
+ HOME_KEY,
+ NUMPAD_ENTER_KEY,
+} from '~/lib/utils/keys';
import {
MOCK_SEARCH,
MOCK_SEARCH_QUERY,
@@ -415,7 +422,7 @@ describe('GlobalSearchModal', () => {
class="gl-new-dropdown-item"
tabindex="0"
:data-testid="'test-result-' + n"
- >Result {{ n }}</li>
+ ><a href="#">Result {{ n }}</a></li>
</ul>`,
},
},
@@ -429,26 +436,26 @@ describe('GlobalSearchModal', () => {
});
it('Home key keeps focus in input', () => {
- const event = triggerKeydownEvent(findSearchInput().element, 'Home');
+ const event = triggerKeydownEvent(findSearchInput().element, HOME_KEY);
expect(document.activeElement).toBe(findSearchInput().element);
expect(event.defaultPrevented).toBe(false);
});
it('End key keeps focus on input', () => {
- const event = triggerKeydownEvent(findSearchInput().element, 'End');
- findSearchInput().trigger('keydown', { code: 'End' });
+ const event = triggerKeydownEvent(findSearchInput().element, END_KEY);
+ findSearchInput().trigger('keydown', { code: END_KEY });
expect(document.activeElement).toBe(findSearchInput().element);
expect(event.defaultPrevented).toBe(false);
});
it('ArrowUp keeps focus on input', () => {
- const event = triggerKeydownEvent(findSearchInput().element, 'ArrowUp');
+ const event = triggerKeydownEvent(findSearchInput().element, ARROW_UP_KEY);
expect(document.activeElement).toBe(findSearchInput().element);
expect(event.defaultPrevented).toBe(false);
});
it('ArrowDown focuses the first item', () => {
- const event = triggerKeydownEvent(findSearchInput().element, 'ArrowDown');
+ const event = triggerKeydownEvent(findSearchInput().element, ARROW_DOWN_KEY);
expect(document.activeElement).toBe(wrapper.findByTestId('test-result-1').element);
expect(event.defaultPrevented).toBe(true);
});
@@ -460,32 +467,44 @@ describe('GlobalSearchModal', () => {
});
it('Home key focuses first item', () => {
- const event = triggerKeydownEvent(document.activeElement, 'Home');
+ const event = triggerKeydownEvent(document.activeElement, HOME_KEY);
expect(document.activeElement).toBe(wrapper.findByTestId('test-result-1').element);
expect(event.defaultPrevented).toBe(true);
});
it('End key focuses last item', () => {
- const event = triggerKeydownEvent(document.activeElement, 'End');
+ const event = triggerKeydownEvent(document.activeElement, END_KEY);
expect(document.activeElement).toBe(wrapper.findByTestId('test-result-5').element);
expect(event.defaultPrevented).toBe(true);
});
it('ArrowUp focuses previous item if any, else input', () => {
- let event = triggerKeydownEvent(document.activeElement, 'ArrowUp');
+ let event = triggerKeydownEvent(document.activeElement, ARROW_UP_KEY);
expect(document.activeElement).toBe(wrapper.findByTestId('test-result-1').element);
expect(event.defaultPrevented).toBe(true);
- event = triggerKeydownEvent(document.activeElement, 'ArrowUp');
+ event = triggerKeydownEvent(document.activeElement, ARROW_UP_KEY);
expect(document.activeElement).toBe(findSearchInput().element);
expect(event.defaultPrevented).toBe(true);
});
it('ArrowDown focuses next item', () => {
- const event = triggerKeydownEvent(document.activeElement, 'ArrowDown');
+ const event = triggerKeydownEvent(document.activeElement, ARROW_DOWN_KEY);
expect(document.activeElement).toBe(wrapper.findByTestId('test-result-3').element);
expect(event.defaultPrevented).toBe(true);
});
+
+ it('NumpadEnter clicks the current item child', () => {
+ const focusedElement = document.activeElement;
+ const focusedElementChild = focusedElement.firstChild;
+
+ const clickMock = jest.fn();
+ focusedElementChild.click = clickMock;
+
+ const event = triggerKeydownEvent(focusedElement, NUMPAD_ENTER_KEY);
+ expect(clickMock).toHaveBeenCalled();
+ expect(event.defaultPrevented).toBe(true);
+ });
});
});
});
diff --git a/spec/models/ci/resource_group_spec.rb b/spec/models/ci/resource_group_spec.rb
index 6d518d5c874..9e98cc884de 100644
--- a/spec/models/ci/resource_group_spec.rb
+++ b/spec/models/ci/resource_group_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Ci::ResourceGroup do
let!(:resource_group) { create(:ci_resource_group, process_mode: process_mode, project: project) }
- Ci::HasStatus::STATUSES_ENUM.keys.each do |status| # rubocop:diable RSpec/UselessDynamicDefinition
+ Ci::HasStatus::STATUSES_ENUM.each_key do |status| # rubocop:disable RSpec/UselessDynamicDefinition -- `status` used in `let`
let!("build_1_#{status}") { create(:ci_build, pipeline: pipeline_1, status: status, resource_group: resource_group) }
let!("build_2_#{status}") { create(:ci_build, pipeline: pipeline_2, status: status, resource_group: resource_group) }
end
diff --git a/spec/models/concerns/has_user_type_spec.rb b/spec/models/concerns/has_user_type_spec.rb
index 54614ec2b21..effb588e55f 100644
--- a/spec/models/concerns/has_user_type_spec.rb
+++ b/spec/models/concerns/has_user_type_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe User, feature_category: :system_access do
- User::USER_TYPES.keys.each do |type| # rubocop:disable RSpec/UselessDynamicDefinition
+ User::USER_TYPES.each_key do |type| # rubocop:disable RSpec/UselessDynamicDefinition -- `type` used in `let`
let_it_be(type) { create(:user, username: type, user_type: type) }
end
let(:bots) { User::BOT_USER_TYPES.map { |type| public_send(type) } }
diff --git a/spec/requests/api/graphql/project/environments_spec.rb b/spec/requests/api/graphql/project/environments_spec.rb
index 3a863bd3d77..94ce6b797cd 100644
--- a/spec/requests/api/graphql/project/environments_spec.rb
+++ b/spec/requests/api/graphql/project/environments_spec.rb
@@ -150,7 +150,7 @@ RSpec.describe 'Project Environments query', feature_category: :continuous_deliv
end
describe 'last deployments of environments' do
- ::Deployment.statuses.each do |status, _| # rubocop:disable RSpec/UselessDynamicDefinition
+ ::Deployment.statuses.each_key do |status| # rubocop:disable RSpec/UselessDynamicDefinition -- `status` used in `let_it_be`
let_it_be(:"production_#{status}_deployment") do
create(:deployment, status.to_sym, environment: production, project: project)
end
diff --git a/spec/services/packages/npm/generate_metadata_service_spec.rb b/spec/services/packages/npm/generate_metadata_service_spec.rb
index d8e794405e6..f5d7f13d22c 100644
--- a/spec/services/packages/npm/generate_metadata_service_spec.rb
+++ b/spec/services/packages/npm/generate_metadata_service_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe ::Packages::Npm::GenerateMetadataService, feature_category: :pack
with_them do
if params[:has_dependencies]
- ::Packages::DependencyLink.dependency_types.each_key do |dependency_type| # rubocop:disable RSpec/UselessDynamicDefinition
+ ::Packages::DependencyLink.dependency_types.each_key do |dependency_type| # rubocop:disable RSpec/UselessDynamicDefinition -- `dependency_type` used in `let_it_be`
let_it_be("package_dependency_link_for_#{dependency_type}") do
create(:packages_dependency_link, package: package1, dependency_type: dependency_type)
end
diff --git a/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb b/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
index f80da0a9e61..c199afcf2ca 100644
--- a/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
+++ b/spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
@@ -182,13 +182,15 @@ RSpec.describe Packages::Nuget::UpdatePackageFromMetadataService, :clean_gitlab_
context 'without authors or description' do
%i[authors description].each do |property|
- let(:metadata) { { package_name: package_name, package_version: package_version, property => nil } }
+ context "for #{property}" do
+ let(:metadata) { { package_name: package_name, package_version: package_version, property => nil } }
- before do
- allow(service).to receive(:metadata).and_return(metadata)
- end
+ before do
+ allow(service).to receive(:metadata).and_return(metadata)
+ end
- it_behaves_like 'raising an', described_class::InvalidMetadataError, with_message: described_class::INVALID_METADATA_ERROR_MESSAGE
+ it_behaves_like 'raising an', described_class::InvalidMetadataError, with_message: described_class::INVALID_METADATA_ERROR_MESSAGE
+ end
end
end
end
diff --git a/spec/support/helpers/cycle_analytics_helpers/test_generation.rb b/spec/support/helpers/cycle_analytics_helpers/test_generation.rb
deleted file mode 100644
index 1c7c45c06a1..00000000000
--- a/spec/support/helpers/cycle_analytics_helpers/test_generation.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-# frozen_string_literal: true
-
-# rubocop:disable Layout/LineLength
-# rubocop:disable Metrics/CyclomaticComplexity
-# rubocop:disable Metrics/PerceivedComplexity
-# rubocop:disable Metrics/AbcSize
-
-# Note: The ABC size is large here because we have a method generating test cases with
-# multiple nested contexts. This shouldn't count as a violation.
-module CycleAnalyticsHelpers
- module TestGeneration
- # Generate the most common set of specs that all value stream analytics phases need to have.
- #
- # Arguments:
- #
- # phase: Which phase are we testing? Will call `CycleAnalytics.new.send(phase)` for the final assertion
- # data_fn: A function that returns a hash, constituting initial data for the test case
- # start_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with
- # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`).
- # Each `condition_fn` is expected to implement a case which consitutes the start of the given value stream analytics phase.
- # end_time_conditions: An array of `conditions`. Each condition is an tuple of `condition_name` and `condition_fn`. `condition_fn` is called with
- # `context` (no lexical scope, so need to do `context.create` for factories, for example) and `data` (from the `data_fn`).
- # Each `condition_fn` is expected to implement a case which consitutes the end of the given value stream analytics phase.
- # before_end_fn: This function is run before calling the end time conditions. Used for setup that needs to be run between the start and end conditions.
- # post_fn: Code that needs to be run after running the end time conditions.
-
- def generate_cycle_analytics_spec(phase:, data_fn:, start_time_conditions:, end_time_conditions:, before_end_fn: nil, post_fn: nil)
- combinations_of_start_time_conditions = (1..start_time_conditions.size).flat_map { |size| start_time_conditions.combination(size).to_a }
- combinations_of_end_time_conditions = (1..end_time_conditions.size).flat_map { |size| end_time_conditions.combination(size).to_a }
-
- scenarios = combinations_of_start_time_conditions.product(combinations_of_end_time_conditions)
- scenarios.each do |start_time_conditions, end_time_conditions|
- let_it_be(:other_project) { create(:project, :repository) }
-
- before do
- other_project.add_developer(user)
- end
-
- context "start condition: #{start_time_conditions.map(&:first).to_sentence}" do
- context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do
- it "finds the median of available durations between the two conditions", :sidekiq_might_not_need_inline do
- time_differences = Array.new(5) do |index|
- data = data_fn[self]
- start_time = (index * 10).days.from_now
- end_time = start_time + rand(1..5).days
-
- start_time_conditions.each_value do |condition_fn|
- travel_to(start_time) { condition_fn[self, data] }
- end
-
- # Run `before_end_fn` at the midpoint between `start_time` and `end_time`
- travel_to(start_time + ((end_time - start_time) / 2)) { before_end_fn[self, data] } if before_end_fn
-
- end_time_conditions.each_value do |condition_fn|
- travel_to(end_time) { condition_fn[self, data] }
- end
-
- travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
-
- end_time - start_time
- end
-
- median_time_difference = time_differences.sort[2]
- expect(subject[phase].project_median).to be_within(5).of(median_time_difference)
- end
-
- context "when the data belongs to another project" do
- it "returns nil" do
- # Use a stub to "trick" the data/condition functions
- # into using another project. This saves us from having to
- # define separate data/condition functions for this particular
- # test case.
- allow(self).to receive(:project) { other_project }
-
- data = data_fn[self]
- start_time = Time.now
- end_time = rand(1..10).days.from_now
-
- start_time_conditions.each_value do |condition_fn|
- travel_to(start_time) { condition_fn[self, data] }
- end
-
- end_time_conditions.each_value do |condition_fn|
- travel_to(end_time) { condition_fn[self, data] }
- end
-
- travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
-
- # Turn off the stub before checking assertions
- allow(self).to receive(:project).and_call_original
-
- expect(subject[phase].project_median).to be_nil
- end
- end
-
- context "when the end condition happens before the start condition" do
- it 'returns nil' do
- data = data_fn[self]
- start_time = Time.now
- end_time = start_time + rand(1..5).days
-
- # Run `before_end_fn` at the midpoint between `start_time` and `end_time`
- travel_to(start_time + ((end_time - start_time) / 2)) { before_end_fn[self, data] } if before_end_fn
-
- end_time_conditions.each_value do |condition_fn|
- travel_to(start_time) { condition_fn[self, data] }
- end
-
- start_time_conditions.each_value do |condition_fn|
- travel_to(end_time) { condition_fn[self, data] }
- end
-
- travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
-
- expect(subject[phase].project_median).to be_nil
- end
- end
- end
-
- context "end condition NOT PRESENT: #{end_time_conditions.map(&:first).to_sentence}" do
- it "returns nil" do
- data = data_fn[self]
- start_time = Time.now
-
- start_time_conditions.each_value do |condition_fn|
- travel_to(start_time) { condition_fn[self, data] }
- end
-
- post_fn[self, data] if post_fn
-
- expect(subject[phase].project_median).to be_nil
- end
- end
- end
-
- context "start condition NOT PRESENT: #{start_time_conditions.map(&:first).to_sentence}" do
- context "end condition: #{end_time_conditions.map(&:first).to_sentence}" do
- it "returns nil" do
- data = data_fn[self]
- end_time = rand(1..10).days.from_now
-
- end_time_conditions.each_with_index do |(_condition_name, condition_fn), index|
- travel_to(end_time + index.days) { condition_fn[self, data] }
- end
-
- travel_to(end_time + 1.day) { post_fn[self, data] } if post_fn
-
- expect(subject[phase].project_median).to be_nil
- end
- end
- end
- end
-
- context "when none of the start / end conditions are matched" do
- it "returns nil" do
- expect(subject[phase].project_median).to be_nil
- end
- end
- end
- end
-end
-
-# rubocop:enable Layout/LineLength
-# rubocop:enable Metrics/CyclomaticComplexity
-# rubocop:enable Metrics/PerceivedComplexity
-# rubocop:enable Metrics/AbcSize