From d0bb0e04f40b962576353ce56e270aa7bd25a5c0 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 19 May 2022 15:09:09 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/docs.gitlab-ci.yml | 4 +- .../components/extensions/base.vue | 36 +++++++++- .../components/notes/noteable_warning.vue | 6 +- app/assets/stylesheets/framework/buttons.scss | 18 ++--- .../boards/base_items_list_service.rb | 7 +- ...geCommitMessageWithDescription-graphql.yml | 4 +- .../15_0/15-0-merge-commit-message.yml | 16 +++++ ...9_schedule_purging_stale_security_scans.rb | 32 +++++++++ db/schema_migrations/20220407163559 | 1 + doc/api/dora4_project_analytics.md | 49 ++----------- doc/api/graphql/reference/index.md | 11 +++ doc/api/pipelines.md | 9 +++ doc/api/usage_data.md | 8 ++- doc/ci/pipelines/index.md | 10 ++- .../new_fe_guide/modules/widget_extensions.md | 25 +++++++ doc/development/redis.md | 4 ++ doc/raketasks/sidekiq_job_migration.md | 2 +- doc/update/index.md | 2 + doc/update/removals.md | 10 +++ .../policies/scan-execution-policies.md | 3 +- .../purge_stale_security_scans.rb | 32 +++++++++ locale/gitlab.pot | 6 ++ package.json | 2 +- .../vue_mr_widget/mr_widget_options_spec.js | 60 ++++++++++++++++ .../frontend/vue_mr_widget/test_extensions.js | 19 +++++ .../noteable_warning_spec.js.snap | 4 +- ...edule_purging_stale_security_scans_spec.rb | 69 +++++++++++++++++++ .../items_list_service_shared_examples.rb | 40 ++++++++--- yarn.lock | 8 +-- 29 files changed, 404 insertions(+), 93 deletions(-) create mode 100644 data/removals/15_0/15-0-merge-commit-message.yml create mode 100644 db/post_migrate/20220407163559_schedule_purging_stale_security_scans.rb create mode 100644 db/schema_migrations/20220407163559 create mode 100644 lib/gitlab/background_migration/purge_stale_security_scans.rb create mode 100644 spec/migrations/schedule_purging_stale_security_scans_spec.rb diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml index 217da6506bf..93158fca83e 100644 --- a/.gitlab/ci/docs.gitlab-ci.yml +++ b/.gitlab/ci/docs.gitlab-ci.yml @@ -44,7 +44,7 @@ docs-lint markdown: - .default-retry - .docs:rules:docs-lint # When updating the image version here, update it in /scripts/lint-doc.sh too. - image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.15.5-markdownlint-0.31.1 + image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.16.1-markdownlint-0.31.1 stage: lint needs: [] script: @@ -53,7 +53,7 @@ docs-lint markdown: docs-lint links: extends: - .docs:rules:docs-lint - image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.15-ruby-2.7.5-cee62c13 + image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.15-ruby-2.7.5-e6a8a48a stage: lint needs: [] script: diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue index 0bc17de638b..0efc157bcdf 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue @@ -12,6 +12,7 @@ import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scrolle import api from '~/api'; import { sprintf, s__, __ } from '~/locale'; import Poll from '~/lib/utils/poll'; +import { normalizeHeaders } from '~/lib/utils/common_utils'; import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants'; import StatusIcon from './status_icon.vue'; import Actions from './actions.vue'; @@ -147,6 +148,35 @@ export default { this.triggerRedisTracking(); } }, + initExtensionMultiPolling() { + const allData = []; + const requests = this.fetchMultiData(); + + requests.forEach((request) => { + const poll = new Poll({ + resource: { + fetchData: () => request(this.$props), + }, + method: 'fetchData', + successCallback: (response) => { + const headers = normalizeHeaders(response.headers); + + if (!headers['POLL-INTERVAL']) { + allData.push(response.data); + } + + if (allData.length === requests.length) { + this.setCollapsedData(allData); + } + }, + errorCallback: (e) => { + this.setCollapsedError(e); + }, + }); + + poll.makeRequest(); + }); + }, initExtensionPolling() { const poll = new Poll({ resource: { @@ -172,7 +202,11 @@ export default { this.loadingState = LOADING_STATES.collapsedLoading; if (this.$options.enablePolling) { - this.initExtensionPolling(); + if (this.fetchMultiData) { + this.initExtensionMultiPolling(); + } else { + this.initExtensionPolling(); + } } else { this.fetchCollapsedData(this.$props) .then((data) => { diff --git a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue index 7a7074da084..78a7fed6293 100644 --- a/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue +++ b/app/assets/javascripts/vue_shared/components/notes/noteable_warning.vue @@ -98,13 +98,15 @@ export default { {{ confidentialContextText }} {{ __('People without permission will never get a notification.') }} - {{ __('Learn more') }} + {{ + __('Learn more.') + }} {{ lockedContextText }} {{ __('Only project members can comment.') }} - {{ __('Learn more') }} + {{ __('Learn more.') }} diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index 33522c66024..7ecd7ea277f 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -106,15 +106,15 @@ } @mixin btn-blue { - @include btn-color($blue-500, $blue-600, $blue-600, $blue-700, $blue-700, $blue-800, $white); + @include btn-color($blue-500, $blue-600, $blue-600, $blue-700, $blue-700, $blue-800, $white-contrast); } @mixin btn-orange { - @include btn-color($orange-500, $orange-600, $orange-500, $orange-600, $orange-600, $orange-800, $white); + @include btn-color($orange-500, $orange-600, $orange-500, $orange-600, $orange-600, $orange-800, $white-contrast); } @mixin btn-red { - @include btn-color($red-500, $red-600, $red-600, $red-700, $red-700, $red-800, $white); + @include btn-color($red-500, $red-600, $red-600, $red-700, $red-700, $red-800, $white-contrast); } @mixin btn-white { @@ -122,7 +122,7 @@ } @mixin btn-purple { - @include btn-color($purple-700, $purple-800, $purple-800, $purple-900, $purple-900, $purple-950, $white); + @include btn-color($purple-700, $purple-800, $purple-800, $purple-900, $purple-900, $purple-950, $white-contrast); } @mixin btn-with-margin { @@ -417,16 +417,6 @@ fieldset[disabled] .btn, cursor: default; } -// This class helps convert `.gl-button` children so that they consistently -// match the style of `.btn` elements which might be around them. Ideally we -// wouldn't need this class. -// -// Remove by upgrading all buttons in a container to use the new `.gl-button` style. -.gl-button-deprecated-adapter .gl-button { - box-shadow: none; - border-width: 1px; -} - copy-code { @include gl-absolute; @include gl-transition-medium; diff --git a/app/services/boards/base_items_list_service.rb b/app/services/boards/base_items_list_service.rb index 01fad14d036..2a9cbb83cc4 100644 --- a/app/services/boards/base_items_list_service.rb +++ b/app/services/boards/base_items_list_service.rb @@ -78,12 +78,15 @@ module Boards end def list - return unless params.key?(:id) + return unless params.key?(:id) || params.key?(:list) strong_memoize(:list) do id = params[:id] + list = params[:list] - if board.lists.loaded? + if list.present? + list + elsif board.lists.loaded? board.lists.find { |l| l.id == id } else board.lists.find(id) diff --git a/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml b/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml index 85cb235f445..17ce084ada6 100644 --- a/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml +++ b/data/deprecations/14-5-deprecate-defaultMergeCommitMessageWithDescription-graphql.yml @@ -10,7 +10,7 @@ stage: create reporter: phikai tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] - issue_url: # (optional) This is a link to the deprecation issue in GitLab - documentation_url: # (optional) This is a link to the current documentation page + issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345451 # (optional) This is a link to the deprecation issue in GitLab + documentation_url: https://docs.gitlab.com/ee/api/graphql/removed_items.html#graphql-types # (optional) This is a link to the current documentation page image_url: # (optional) This is a link to a thumbnail image depicting the feature video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg diff --git a/data/removals/15_0/15-0-merge-commit-message.yml b/data/removals/15_0/15-0-merge-commit-message.yml new file mode 100644 index 00000000000..ff6acd62304 --- /dev/null +++ b/data/removals/15_0/15-0-merge-commit-message.yml @@ -0,0 +1,16 @@ +- name: "`defaultMergeCommitMessageWithDescription` GraphQL API field" + announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated. + announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post. + removal_milestone: "15.0" # The milestone when this feature is planned to be removed + removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed + breaking_change: true # (required) Change to true if this removal is a breaking change. + reporter: phikai # (required) GitLab username of the person reporting the removal + stage: create # (required) String value of the stage that the feature was created in. e.g., Growth + issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345451 # (required) Link to the deprecation issue in GitLab + body: | # (required) Do not modify this line, instead modify the lines below. + The GraphQL API field `defaultMergeCommitMessageWithDescription` has been removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template. +# The following items are not published on the docs page, but may be used in the future. + tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate] + documentation_url: https://docs.gitlab.com/ee/api/graphql/removed_items.html#graphql-types # (optional) This is a link to the current documentation page + image_url: # (optional) This is a link to a thumbnail image depicting the feature + video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg diff --git a/db/post_migrate/20220407163559_schedule_purging_stale_security_scans.rb b/db/post_migrate/20220407163559_schedule_purging_stale_security_scans.rb new file mode 100644 index 00000000000..fdceb2f2594 --- /dev/null +++ b/db/post_migrate/20220407163559_schedule_purging_stale_security_scans.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +class SchedulePurgingStaleSecurityScans < Gitlab::Database::Migration[2.0] + MIGRATION = 'PurgeStaleSecurityScans' + BATCH_SIZE = 10_000 + DELAY_INTERVAL = 2.minutes + + restrict_gitlab_migration gitlab_schema: :gitlab_main + disable_ddl_transaction! + + def up + return unless should_run? + + queue_background_migration_jobs_by_range_at_intervals( + Gitlab::BackgroundMigration::PurgeStaleSecurityScans::SecurityScan.to_purge, + MIGRATION, + DELAY_INTERVAL, + batch_size: BATCH_SIZE, + track_jobs: true + ) + end + + def down + # no-op + end + + private + + def should_run? + Gitlab.dev_or_test_env? || Gitlab.com? + end +end diff --git a/db/schema_migrations/20220407163559 b/db/schema_migrations/20220407163559 new file mode 100644 index 00000000000..e0517db3672 --- /dev/null +++ b/db/schema_migrations/20220407163559 @@ -0,0 +1 @@ +dabbd8b95ec49b4267d53768013b4e62ae1219a4575dc8b0fccb0e117e725885 \ No newline at end of file diff --git a/doc/api/dora4_project_analytics.md b/doc/api/dora4_project_analytics.md index 53170c3a77f..19c7afd9d22 100644 --- a/doc/api/dora4_project_analytics.md +++ b/doc/api/dora4_project_analytics.md @@ -3,52 +3,11 @@ stage: Manage group: Optimize info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments type: reference, api +remove_date: '2022-05-18' +redirect_to: 'dora/metrics.md' --- -# DORA4 Analytics Project API **(ULTIMATE)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab 13.7. +# DORA4 Analytics Project API (removed) **(ULTIMATE)** WARNING: -These endpoints have been removed in GitLab 14.0. Use the [DORA metrics API](dora/metrics.md) instead. - -All methods require reporter authorization. - -## List project deployment frequencies - -Get a list of all project deployment frequencies, sorted by date: - -```plaintext -GET /projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval -``` - -| Attribute | Type | Required | Description | -|--------------|--------|----------|-----------------------| -| `id` | string | yes | The ID of the project | -| `environment`| string | yes | The name of the environment to filter by | -| `from` | string | yes | Datetime range to start from, inclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) | -| `to` | string | no | Datetime range to end at, exclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) | -| `interval` | string | no | The bucketing interval (`all`, `monthly`, `daily`) | - -Example request: - -```shell -curl --header "PRIVATE-TOKEN: " "https://gitlab.example.com/api/v4/projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval" -``` - -Example response: - -```json -[ - { - "from": "2017-01-01", - "to": "2017-01-02", - "value": 106 - }, - { - "from": "2017-01-02", - "to": "2017-01-03", - "value": 55 - } -] -``` +This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.11 and removed in GitLab 14.0. Use the [DORA metrics API](dora/metrics.md) instead. diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 669ba3bc13d..482d5c926d1 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -145,6 +145,17 @@ Returns [`String!`](#string). | ---- | ---- | ----------- | | `text` | [`String!`](#string) | Text to echo back. | +### `Query.epicBoardList` + +Returns [`EpicList`](#epiclist). + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `epicFilters` | [`EpicFilters`](#epicfilters) | Filters applied when getting epic metadata in the epic board list. | +| `id` | [`BoardsEpicListID!`](#boardsepiclistid) | Global ID of the list. | + ### `Query.geoNode` Find a Geo node. diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md index b05c71d2748..3f5274edc0a 100644 --- a/doc/api/pipelines.md +++ b/doc/api/pipelines.md @@ -422,6 +422,15 @@ Response: > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22988) in GitLab 11.6. +Deleting a pipeline expires all pipeline caches, and deletes all immediately +related objects, such as builds, logs, artifacts, and triggers. +**This action cannot be undone.** + +Deleting a pipeline does not automatically delete its +[child pipelines](../ci/pipelines/parent_child_pipelines.md). +See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39503) +for details. + ```plaintext DELETE /projects/:id/pipelines/:pipeline_id ``` diff --git a/doc/api/usage_data.md b/doc/api/usage_data.md index c7064ebf65b..be816a0f864 100644 --- a/doc/api/usage_data.md +++ b/doc/api/usage_data.md @@ -50,10 +50,10 @@ Example response: ## Export Service Ping SQL queries -This action is available only for the GitLab instance [Administrator](../user/permissions.md) users. +This action is behind the `usage_data_queries_api` feature flag and is available only for the GitLab instance [Administrator](../user/permissions.md) users. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57016) in GitLab 13.11. -> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default. +> - [Deployed behind a feature flag](../user/feature_flags.md) named `usage_data_queries_api`, disabled by default. Return all of the raw SQL queries used to compute Service Ping. @@ -113,8 +113,10 @@ Example response: ## UsageDataNonSqlMetrics API +This action is behind the `usage_data_non_sql_metrics` feature flag and is available only for the GitLab instance [Administrator](../user/permissions.md) users. + > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57050) in GitLab 13.11. -> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default. +> - [Deployed behind a feature flag](../user/feature_flags.md), named `usage_data_non_sql_metrics`, disabled by default. Return all non-SQL metrics data used in the Service ping. diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index c6142ebefc5..20c51dd72fb 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -287,9 +287,15 @@ page, then selecting **Delete**. ![Pipeline Delete](img/pipeline-delete.png) +Deleting a pipeline does not automatically delete its +[child pipelines](parent_child_pipelines.md). +See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39503) +for details. + WARNING: -Deleting a pipeline expires all pipeline caches, and deletes all related objects, -such as builds, logs, artifacts, and triggers. **This action cannot be undone.** +Deleting a pipeline expires all pipeline caches, and deletes all immediately +related objects, such as builds, logs, artifacts, and triggers. +**This action cannot be undone.** ### Pipeline security on protected branches diff --git a/doc/development/new_fe_guide/modules/widget_extensions.md b/doc/development/new_fe_guide/modules/widget_extensions.md index d3be8981abb..1620cbe5cf1 100644 --- a/doc/development/new_fe_guide/modules/widget_extensions.md +++ b/doc/development/new_fe_guide/modules/widget_extensions.md @@ -46,6 +46,7 @@ export default { methods: { fetchCollapsedData(props) {}, // Required: Fetches data required for collapsed state fetchFullData(props) {}, // Required: Fetches data for the full expanded content + fetchMultiData() {}, // Optional: Works in conjunction with `enablePolling` and allows polling multiple endpoints }, }; ``` @@ -232,6 +233,30 @@ export default { }; ``` +If the extension needs to poll multiple endpoints at the same time, then `fetchMultiData` +can be used to return an array of functions. A new `poll` object will be created for each +endpoint and they will be polled separately. Once all endpoints are resolved, polling will +be stopped and `setCollapsedData` will be called with an array of `response.data`. + +```javascript +export default { + //... + enablePolling: true + methods: { + fetchMultiData() { + return [ + () => axios.get(this.reportPath1), + () => axios.get(this.reportPath2), + () => axios.get(this.reportPath3) + }, + }, +}; +``` + +**Important** The function needs to return a `Promise` that resolves the `response` object. +The implementation relies on the `POLL-INTERVAL` header to keep polling, therefore it is +important not to alter the status code and headers. + ### Errors If `fetchCollapsedData()` or `fetchFullData()` methods throw an error: diff --git a/doc/development/redis.md b/doc/development/redis.md index d5f526f2d32..dd84f2b202a 100644 --- a/doc/development/redis.md +++ b/doc/development/redis.md @@ -118,12 +118,16 @@ NOTE: There is a [video showing how to see the slow log](https://youtu.be/BBI68QuYRH8) (GitLab internal) on GitLab.com + + On GitLab.com, entries from the [Redis slow log](https://redis.io/commands/slowlog) are available in the `pubsub-redis-inf-gprd*` index with the [`redis.slowlog` tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)). This shows commands that have taken a long time and may be a performance concern. + + The [`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog) project is responsible for taking the `slowlog` entries from Redis and diff --git a/doc/raketasks/sidekiq_job_migration.md b/doc/raketasks/sidekiq_job_migration.md index 313c9c7220b..a3bc8b2959a 100644 --- a/doc/raketasks/sidekiq_job_migration.md +++ b/doc/raketasks/sidekiq_job_migration.md @@ -11,7 +11,7 @@ This operation should be very uncommon. We do not recommend it for the vast majo Sidekiq routing rules allow administrators to re-route certain background jobs from their regular queue to an alternative queue. By default, GitLab uses one queue per background job type. GitLab has over 400 background job types, and so correspondingly it has over 400 queues. -Most administrators will not need to change this setting. In some cases with particularly large background job processing workloads, Redis performance may suffer due to the number of queues that GitLab listens to. +Most administrators do not need to change this setting. In some cases with particularly large background job processing workloads, Redis performance may suffer due to the number of queues that GitLab listens to. If the Sidekiq routing rules are changed, administrators need to take care with the migration to avoid losing jobs entirely. The basic migration steps are: diff --git a/doc/update/index.md b/doc/update/index.md index 24afb01396a..12f838b6093 100644 --- a/doc/update/index.md +++ b/doc/update/index.md @@ -517,6 +517,8 @@ that may remain stuck permanently in a **pending** state. sudo printf "x /tmp/gitaly-%s-*\n" hooks git-exec-path >/etc/tmpfiles.d/gitaly-workaround.conf ``` + This issue is fixed in GitLab 14.10 and later. + ### 14.6.0 - See [LFS objects import and mirror issue in GitLab 14.6.0 to 14.7.2](#lfs-objects-import-and-mirror-issue-in-gitlab-1460-to-1472). diff --git a/doc/update/removals.md b/doc/update/removals.md index 4e653d5ab0a..c94f9068545 100644 --- a/doc/update/removals.md +++ b/doc/update/removals.md @@ -675,6 +675,16 @@ keyword has been [replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/344533 [`artifacts:reports:coverage_report`](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report). Cobertura is the only supported report file, but this is the first step towards GitLab supporting other report types. +### `defaultMergeCommitMessageWithDescription` GraphQL API field + +WARNING: +This feature was changed or removed in 15.0 +as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes). +Before updating GitLab, review the details carefully to determine if you need to make any +changes to your code, settings, or workflow. + +The GraphQL API field `defaultMergeCommitMessageWithDescription` has been removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template. + ### `omniauth-kerberos` gem WARNING: diff --git a/doc/user/application_security/policies/scan-execution-policies.md b/doc/user/application_security/policies/scan-execution-policies.md index aa23ad30a73..4ff1bb60c51 100644 --- a/doc/user/application_security/policies/scan-execution-policies.md +++ b/doc/user/application_security/policies/scan-execution-policies.md @@ -47,7 +47,8 @@ The policy editor currently only supports the YAML mode. The Rule mode is tracke The YAML file with scan execution policies consists of an array of objects matching scan execution policy schema nested under the `scan_execution_policy` key. You can configure a maximum of 5 -policies under the `scan_execution_policy` key. +policies under the `scan_execution_policy` key. Any other policies configured after +the first 5 are not applied. When you save a new policy, GitLab validates its contents against [this JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/security_orchestration_policy.json). If you're not familiar with how to read [JSON schemas](https://json-schema.org/), diff --git a/lib/gitlab/background_migration/purge_stale_security_scans.rb b/lib/gitlab/background_migration/purge_stale_security_scans.rb new file mode 100644 index 00000000000..8b13a0382b4 --- /dev/null +++ b/lib/gitlab/background_migration/purge_stale_security_scans.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # rubocop:disable Style/Documentation + class PurgeStaleSecurityScans # rubocop:disable Migration/BackgroundMigrationBaseClass + class SecurityScan < ::ApplicationRecord + include EachBatch + + STALE_AFTER = 90.days + + self.table_name = 'security_scans' + + # Otherwise the schema_spec fails + validates :info, json_schema: { filename: 'security_scan_info', draft: 7 } + + enum status: { succeeded: 1, purged: 6 } + + scope :to_purge, -> { where('id <= ?', last_stale_record_id) } + scope :by_range, -> (range) { where(id: range) } + + def self.last_stale_record_id + where('created_at < ?', STALE_AFTER.ago).order(created_at: :desc).first + end + end + + def perform(_start_id, _end_id); end + end + end +end + +Gitlab::BackgroundMigration::PurgeStaleSecurityScans.prepend_mod diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 733f7f7fa0a..8e2b2482f5f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -33677,6 +33677,9 @@ msgstr "" msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again." msgstr "" +msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects in this group." +msgstr "" + msgid "SecurityOrchestration|All policies" msgstr "" @@ -33743,6 +33746,9 @@ msgstr "" msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}" msgstr "" +msgid "SecurityOrchestration|Group level policy" +msgstr "" + msgid "SecurityOrchestration|If any scanner finds a newly detected critical vulnerability in an open merge request targeting the master branch, then require two approvals from any member of App security." msgstr "" diff --git a/package.json b/package.json index db1ea077889..c46b22c0be1 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", "@gitlab/svgs": "2.14.0", - "@gitlab/ui": "40.2.1", + "@gitlab/ui": "40.6.0", "@gitlab/visual-review-tools": "1.7.3", "@rails/actioncable": "6.1.4-7", "@rails/ujs": "6.1.4-7", diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js index 9719e81fe12..5e22780fe19 100644 --- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js @@ -31,6 +31,7 @@ import { fullDataErrorExtension, pollingExtension, pollingErrorExtension, + multiPollingExtension, } from './test_extensions'; jest.mock('~/api.js'); @@ -987,6 +988,8 @@ describe('MrWidgetOptions', () => { beforeEach(() => { pollRequest = jest.spyOn(Poll.prototype, 'makeRequest'); pollStop = jest.spyOn(Poll.prototype, 'stop'); + + registeredExtensions.extensions = []; }); afterEach(() => { @@ -996,6 +999,63 @@ describe('MrWidgetOptions', () => { registeredExtensions.extensions = []; }); + describe('success - multi polling', () => { + const findWidgetTestExtension = () => wrapper.find('[data-testid="widget-extension"]'); + + // Clear all left-over timeouts that may be registered in the poll class + afterEach(() => { + let id = window.setTimeout(() => {}, 0); + + while (id > 0) { + window.clearTimeout(id); + id -= 1; + } + }); + + it('sets data when polling is complete', async () => { + registerExtension( + multiPollingExtension([ + () => + Promise.resolve({ + headers: { 'poll-interval': 0 }, + status: 200, + data: { reports: 'parsed' }, + }), + () => + Promise.resolve({ + status: 200, + data: { reports: 'parsed' }, + }), + ]), + ); + + await createComponent(); + expect(findWidgetTestExtension().html()).toContain( + 'Multi polling test extension reports: parsed, count: 2', + ); + }); + + it('shows loading state until polling is complete', async () => { + registerExtension( + multiPollingExtension([ + () => + Promise.resolve({ + headers: { 'poll-interval': 1 }, + status: 204, + }), + () => + Promise.resolve({ + status: 200, + data: { reports: 'parsed' }, + }), + ]), + ); + + await createComponent(); + expect(findWidgetTestExtension().html()).toContain('Loading...'); + }); + }); + describe('success', () => { beforeEach(() => { registerExtension(pollingExtension); diff --git a/spec/frontend/vue_mr_widget/test_extensions.js b/spec/frontend/vue_mr_widget/test_extensions.js index 6344636873f..f092888e142 100644 --- a/spec/frontend/vue_mr_widget/test_extensions.js +++ b/spec/frontend/vue_mr_widget/test_extensions.js @@ -106,6 +106,25 @@ export const pollingExtension = { enablePolling: true, }; +export const multiPollingExtension = (endpointsToBePolled) => ({ + name: 'WidgetTestMultiPollingExtension', + props: ['targetProjectFullPath'], + computed: { + summary(data) { + return `Multi polling test extension reports: ${data?.[0]?.reports}, count: ${data.length}`; + }, + statusIcon(data) { + return data?.[0]?.reports === 'parsed' ? EXTENSION_ICONS.success : EXTENSION_ICONS.warning; + }, + }, + enablePolling: true, + methods: { + fetchMultiData() { + return endpointsToBePolled; + }, + }, +}); + export const pollingErrorExtension = { ...collapsedDataErrorExtension, enablePolling: true, diff --git a/spec/frontend/vue_shared/components/notes/__snapshots__/noteable_warning_spec.js.snap b/spec/frontend/vue_shared/components/notes/__snapshots__/noteable_warning_spec.js.snap index f878d685b6d..8a187f3cb1f 100644 --- a/spec/frontend/vue_shared/components/notes/__snapshots__/noteable_warning_spec.js.snap +++ b/spec/frontend/vue_shared/components/notes/__snapshots__/noteable_warning_spec.js.snap @@ -10,7 +10,7 @@ exports[`Issue Warning Component when issue is locked but not confidential rende href="locked-path" target="_blank" > - Learn more + Learn more. `; @@ -25,7 +25,7 @@ exports[`Issue Warning Component when noteable is confidential but not locked re href="confidential-path" target="_blank" > - Learn more + Learn more. `; diff --git a/spec/migrations/schedule_purging_stale_security_scans_spec.rb b/spec/migrations/schedule_purging_stale_security_scans_spec.rb new file mode 100644 index 00000000000..b58ded6a4f6 --- /dev/null +++ b/spec/migrations/schedule_purging_stale_security_scans_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe SchedulePurgingStaleSecurityScans do + let_it_be(:namespaces) { table(:namespaces) } + let_it_be(:projects) { table(:projects) } + let_it_be(:pipelines) { table(:ci_pipelines) } + let_it_be(:builds) { table(:ci_builds) } + let_it_be(:security_scans) { table(:security_scans) } + + let_it_be(:namespace) { namespaces.create!(name: "foo", path: "bar") } + let_it_be(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id) } + let_it_be(:pipeline) { pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a', status: 'success') } + let_it_be(:ci_build) { builds.create!(commit_id: pipeline.id, retried: false, type: 'Ci::Build') } + + let!(:security_scan_1) { security_scans.create!(build_id: ci_build.id, scan_type: 1, created_at: 91.days.ago) } + let!(:security_scan_2) { security_scans.create!(build_id: ci_build.id, scan_type: 2, created_at: 91.days.ago) } + + let(:com?) { false } + let(:dev_or_test_env?) { false } + + before do + allow(::Gitlab).to receive(:com?).and_return(com?) + allow(::Gitlab).to receive(:dev_or_test_env?).and_return(dev_or_test_env?) + + stub_const("#{described_class.name}::BATCH_SIZE", 1) + end + + shared_examples_for 'schedules the background jobs' do + before do + # This will not be scheduled as it's not stale + security_scans.create!(build_id: ci_build.id, scan_type: 3) + end + + around do |example| + freeze_time { Sidekiq::Testing.fake! { example.run } } + end + + it 'creates 2 jobs', :aggregate_failures do + migrate! + + expect(BackgroundMigrationWorker.jobs.size).to be(2) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes, security_scan_1.id, security_scan_1.id) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(4.minutes, security_scan_2.id, security_scan_2.id) + end + end + + context 'when the migration does not run on GitLab.com or `dev_or_test_env`' do + it 'does not run the migration' do + expect { migrate! }.not_to change { BackgroundMigrationWorker.jobs.size } + end + end + + context 'when the migration runs on GitLab.com' do + let(:com?) { true } + + it_behaves_like 'schedules the background jobs' + end + + context 'when the migration runs on dev or test env' do + let(:dev_or_test_env?) { true } + + it_behaves_like 'schedules the background jobs' + end +end diff --git a/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb index 9a3a0cc9cc8..ed05a150f8b 100644 --- a/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb +++ b/spec/support/shared_examples/services/boards/items_list_service_shared_examples.rb @@ -3,17 +3,17 @@ RSpec.shared_examples 'items list service' do it 'avoids N+1' do params = { board_id: board.id } - control = ActiveRecord::QueryRecorder.new { described_class.new(parent, user, params).execute } + control = ActiveRecord::QueryRecorder.new { list_service(params).execute } new_list - expect { described_class.new(parent, user, params).execute }.not_to exceed_query_limit(control) + expect { list_service(params).execute }.not_to exceed_query_limit(control) end - it 'returns opened items when list_id is missing' do + it 'returns opened items when list_id and list are missing' do params = { board_id: board.id } - items = described_class.new(parent, user, params).execute + items = list_service(params).execute expect(items).to match_array(backlog_items) end @@ -21,7 +21,7 @@ RSpec.shared_examples 'items list service' do it 'returns opened items when listing items from Backlog' do params = { board_id: board.id, id: backlog.id } - items = described_class.new(parent, user, params).execute + items = list_service(params).execute expect(items).to match_array(backlog_items) end @@ -29,7 +29,7 @@ RSpec.shared_examples 'items list service' do it 'returns opened items that have label list applied when listing items from a label list' do params = { board_id: board.id, id: list1.id } - items = described_class.new(parent, user, params).execute + items = list_service(params).execute expect(items).to match_array(list1_items) end @@ -37,20 +37,24 @@ RSpec.shared_examples 'items list service' do it 'returns closed items when listing items from Closed sorted by closed_at in descending order' do params = { board_id: board.id, id: closed.id } - items = described_class.new(parent, user, params).execute + items = list_service(params).execute expect(items).to eq(closed_items) end it 'raises an error if the list does not belong to the board' do list = create(list_factory) # rubocop:disable Rails/SaveBang - service = described_class.new(parent, user, board_id: board.id, id: list.id) + params = { board_id: board.id, id: list.id } + + service = list_service(params) expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) end - it 'raises an error if list id is invalid' do - service = described_class.new(parent, user, board_id: board.id, id: nil) + it 'raises an error if list and list id are invalid or missing' do + params = { board_id: board.id, id: nil, list: nil } + + service = list_service(params) expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound) end @@ -58,8 +62,22 @@ RSpec.shared_examples 'items list service' do it 'returns items from all lists if :all_list is used' do params = { board_id: board.id, all_lists: true } - items = described_class.new(parent, user, params).execute + items = list_service(params).execute expect(items).to match_array(all_items) end + + it 'returns opened items that have label list applied when using list param' do + params = { board_id: board.id, list: list1 } + + items = list_service(params).execute + + expect(items).to match_array(list1_items) + end + + def list_service(params) + args = [parent, user].push(params) + + described_class.new(*args) + end end diff --git a/yarn.lock b/yarn.lock index ec40f4c9d19..c6842cd459a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -968,10 +968,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.14.0.tgz#92b36bc98ccbed49a4dbca310862146275091cb2" integrity sha512-U9EYmEIiTMl7R3X5DmCrw6fz7gz8c1kjvQtaF6HfJ15xDtR7trRAyCNbn3z7YGk1QJ8Cv/Ifw2/T5SxXwYd7dw== -"@gitlab/ui@40.2.1": - version "40.2.1" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-40.2.1.tgz#510ea1cda0a62afbfb0bc6a74b56e1128ddef428" - integrity sha512-dDsyu8Zuf5MYZwx6A6m2TeIPJL+ytTP7J0x0M8649MOqJJB2/3pq8IfcowWSQAvpO57w5N+G/QlotNypZ3e31w== +"@gitlab/ui@40.6.0": + version "40.6.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-40.6.0.tgz#67ee263d2ce88cb9ef27235e19b2a0844a321c29" + integrity sha512-aib9szbLX/UlejMp1ZG3dzZSLmDwK1V6fKxS5bueaaeHRNKPkQ7sFcyIZNG8sF3sHKUxDwA/OEfciIsRW6xzCQ== dependencies: "@popperjs/core" "^2.11.2" bootstrap-vue "2.20.1"