diff options
-rw-r--r-- | app/assets/javascripts/blob/viewer/index.js | 26 | ||||
-rw-r--r-- | app/assets/javascripts/issues_list/components/issues_list_app.vue | 3 | ||||
-rw-r--r-- | app/assets/javascripts/performance/constants.js | 4 | ||||
-rw-r--r-- | app/assets/stylesheets/framework/files.scss | 22 | ||||
-rw-r--r-- | config/routes.rb | 4 | ||||
-rw-r--r-- | doc/user/application_security/configuration/index.md | 3 | ||||
-rw-r--r-- | doc/user/application_security/dependency_scanning/index.md | 44 | ||||
-rw-r--r-- | doc/user/search/index.md | 10 | ||||
-rw-r--r-- | locale/gitlab.pot | 3 | ||||
-rw-r--r-- | spec/frontend/blob/viewer/index_spec.js | 5 | ||||
-rw-r--r-- | spec/frontend/issues_list/components/issues_list_app_spec.js | 2 |
11 files changed, 112 insertions, 14 deletions
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index db91d478b39..4d133659daa 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -6,6 +6,8 @@ import { REPO_BLOB_LOAD_VIEWER_START, REPO_BLOB_LOAD_VIEWER_FINISH, REPO_BLOB_LOAD_VIEWER, + REPO_BLOB_SWITCH_TO_VIEWER_START, + REPO_BLOB_SWITCH_VIEWER, } from '~/performance/constants'; import { performanceMarkAndMeasure } from '~/performance/utils'; import { fixTitle } from '~/tooltips'; @@ -49,6 +51,9 @@ export const handleBlobRichViewer = (viewer, type) => { export default class BlobViewer { constructor() { + performanceMarkAndMeasure({ + mark: REPO_BLOB_LOAD_VIEWER_START, + }); const viewer = document.querySelector('.blob-viewer[data-type="rich"]'); const type = viewer?.dataset?.richType; BlobViewer.initAuxiliaryViewer(); @@ -141,7 +146,7 @@ export default class BlobViewer { switchToViewer(name) { performanceMarkAndMeasure({ - mark: REPO_BLOB_LOAD_VIEWER_START, + mark: REPO_BLOB_SWITCH_TO_VIEWER_START, }); const newViewer = this.$fileHolder[0].querySelector(`.blob-viewer[data-type='${name}']`); if (this.activeViewer === newViewer) return; @@ -171,11 +176,15 @@ export default class BlobViewer { BlobViewer.loadViewer(newViewer) .then((viewer) => { $(viewer).renderGFM(); + window.requestIdleCallback(() => { + this.$fileHolder.trigger('highlight:line'); + handleLocationHash(); - this.$fileHolder.trigger('highlight:line'); - handleLocationHash(); + viewer.setAttribute('data-loaded', 'true'); + this.toggleCopyButtonState(); + eventHub.$emit('showBlobInteractionZones', viewer.dataset.path); + }); - this.toggleCopyButtonState(); performanceMarkAndMeasure({ mark: REPO_BLOB_LOAD_VIEWER_FINISH, measures: [ @@ -183,6 +192,10 @@ export default class BlobViewer { name: REPO_BLOB_LOAD_VIEWER, start: REPO_BLOB_LOAD_VIEWER_START, }, + { + name: REPO_BLOB_SWITCH_VIEWER, + start: REPO_BLOB_SWITCH_TO_VIEWER_START, + }, ], }); }) @@ -205,9 +218,10 @@ export default class BlobViewer { return axios.get(url).then(({ data }) => { viewer.innerHTML = data.html; - viewer.setAttribute('data-loaded', 'true'); - eventHub.$emit('showBlobInteractionZones', viewer.dataset.path); + window.requestIdleCallback(() => { + viewer.removeAttribute('data-loading'); + }); return viewer; }); diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue index e3cc43d2679..6563094ef72 100644 --- a/app/assets/javascripts/issues_list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue @@ -691,8 +691,9 @@ export default { </li> <blocking-issues-count class="blocking-issues gl-display-none gl-sm-display-block" - :blocking-issues-count="issuable.blockedByCount" + :blocking-issues-count="issuable.blockingCount" :is-list-item="true" + data-testid="blocking-issues" /> </template> diff --git a/app/assets/javascripts/performance/constants.js b/app/assets/javascripts/performance/constants.js index 1db80057d0c..b9a9ef215af 100644 --- a/app/assets/javascripts/performance/constants.js +++ b/app/assets/javascripts/performance/constants.js @@ -83,7 +83,9 @@ export const PIPELINES_DETAIL_LINKS_JOB_RATIO = 'pipeline_graph_links_per_job_ra // Marks export const REPO_BLOB_LOAD_VIEWER_START = 'blobviewer-load-viewer-start'; +export const REPO_BLOB_SWITCH_TO_VIEWER_START = 'blobviewer-switch-to-viewerr-start'; export const REPO_BLOB_LOAD_VIEWER_FINISH = 'blobviewer-load-viewer-finish'; // Measures -export const REPO_BLOB_LOAD_VIEWER = 'Repository File Viewer: loading the content'; +export const REPO_BLOB_LOAD_VIEWER = 'Repository File Viewer: loading the viewer'; +export const REPO_BLOB_SWITCH_VIEWER = 'Repository File Viewer: switching the viewer'; diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index bda123fa7ea..5ad7ceecb2b 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -508,3 +508,25 @@ span.idiff { } } } + +// +// IMPORTANT PERFORMANCE OPTIMIZATION BELOW +// +// * :nth-of-type(1n+70) - makes sure we do not render lines 71+ right +// away. Even though the HTML is injected in the DOM, as long as we do +// not render those lines, the browser doesn't need to spend resources +// calculating and repainting what's hidden. +// +// * :not(:last-of-type) makes sure that we output the last line of the +// blob's snippet. This is important because the column with the line +// numbers has auto width and is expanding based on the content in it. +// This leads to unnecessary layout shift when the last lines of the +// snippet are longer than two (2) digits. +// EXAMPLE: Let's say, we have a blob with 100 lines. If we output 70 +// lines, and then, the remaining 30 (incl the line 100), it will lead +// to the layout reflow and styles recalculation when we output line +// 100 (because the width of '100' is always bigger than '70'). By +// outputting the last line right away, we prevent that as the column +// will always be expanded to the maximum needed width. +.blob-viewer[data-loading] .file-content.code .line:nth-of-type(1n+70):not(:last-of-type), +.blob-viewer[data-loading] .file-content.code .file-line-num:nth-of-type(1n+70):not(:last-of-type) {display: none !important;} diff --git a/config/routes.rb b/config/routes.rb index e0744eb809f..c1cb5a2a26f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -184,6 +184,10 @@ Rails.application.routes.draw do resources :survey_responses, only: :index end + Gitlab.jh do + draw :province + end + if ENV['GITLAB_CHAOS_SECRET'] || Rails.env.development? || Rails.env.test? resource :chaos, only: [] do get :leakmem diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md index fc9f2893729..3cc88a40b6f 100644 --- a/doc/user/application_security/configuration/index.md +++ b/doc/user/application_security/configuration/index.md @@ -78,6 +78,9 @@ You can configure the following security controls: - Secret Detection - Select **Configure via Merge Request** to create a merge request with the changes required to enable Secret Detection. For more details, see [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request). +- Dependency Scanning + - Select **Configure via Merge Request** to create a merge request with the changes required to + enable Dependency Scanning. For more details, see [Enable Dependency Scanning via an automatic merge request](../dependency_scanning/index.md#enable-dependency-scanning-via-an-automatic-merge-request). ## Enable or disable UI redesign **(FREE SELF)** diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index 33d6104998c..a1604b25edc 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -110,6 +110,31 @@ The results are saved as a that you can later download and analyze. Due to implementation limitations, we always take the latest dependency scanning artifact available. +### Enable Dependency Scanning via an automatic merge request + +> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4908) in GitLab 14.1. +> - [Deployed behind a feature flag](../../../user/feature_flags.md), enabled by default. +> - Enabled on GitLab.com. +> - Recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-configure-dependency-scanning-via-a-merge-request). **(ULTIMATE SELF)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +There can be +[risks when disabling released features](../../../user/feature_flags.md#risks-when-disabling-released-features). +Refer to this feature's version history for more details. + +To enable Dependency Scanning in a project, you can create a merge request +from the Security Configuration page. + +1. In the project where you want to enable Dependency Scanning, navigate to + **Security & Compliance > Configuration**. +1. In the **Dependency Scanning** row, select **Configure via Merge Request**. + +This automatically creates a merge request with the changes necessary to enable Dependency Scanning +that you can review and merge to complete the configuration. + ### Customizing the dependency scanning settings The dependency scanning settings can be changed through [CI/CD variables](#available-cicd-variables) by using the @@ -656,3 +681,22 @@ with a dependency on this version of Python should use `retire.js` version 2.10. ### Error: `dependency_scanning is used for configuration only, and its script should not be executed` For information on this, see the [GitLab Secure troubleshooting section](../index.md#error-job-is-used-for-configuration-only-and-its-script-should-not-be-executed). + +### Enable or disable Configure Dependency Scanning via a Merge Request + +Configure Dependency Scanning via a Merge Request is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) +can opt to disable it. + +To disable it: + +```ruby +Feature.disable(:sec_dependency_scanning_ui_enable) +``` + +To enable it: + +```ruby +Feature.enable(:sec_dependency_scanning_ui_enable) +``` diff --git a/doc/user/search/index.md b/doc/user/search/index.md index babe13969ce..d90841fae88 100644 --- a/doc/user/search/index.md +++ b/doc/user/search/index.md @@ -39,9 +39,9 @@ in the search field in the upper right corner: ### Filtering issue and merge request lists -> - Filtering by Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. -> - Filtering by child Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. -> - Filtering by Iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9. +> - Filtering by Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab Ultimate 12.9. +> - Filtering by child Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in GitLab Ultimate 13.0. +> - Filtering by Iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in GitLab 13.6. Moved to GitLab Premium in 13.9. Follow these steps to filter the **Issues** and **Merge Requests** list pages in projects and groups: @@ -107,7 +107,7 @@ You can filter the **Issues** list to individual instances by their ID. For exam ### Filtering merge requests by approvers **(PREMIUM)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9468) in GitLab 11.9. -> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9. +> - Moved to GitLab Premium in 13.9. To filter merge requests by an individual approver, you can type (or select from the dropdown) **Approver** and select the user. @@ -117,7 +117,7 @@ the dropdown) **Approver** and select the user. ### Filtering merge requests by "approved by" **(PREMIUM)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30335) in GitLab 13.0. -> - [Moved](../../subscriptions/bronze_starter.md) to GitLab Premium in 13.9. +> - Moved to GitLab Premium in 13.9. To filter merge requests already approved by a specific individual, you can type (or select from the dropdown) **Approved-By** and select the user. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0c23d0efbf6..59bb021d0a4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -18514,6 +18514,9 @@ msgstr "" msgid "Iteration|Dates cannot overlap with other existing Iterations within this group" msgstr "" +msgid "Iteration|Dates cannot overlap with other existing Iterations within this iterations cadence" +msgstr "" + msgid "Iteration|cannot be more than 500 years in the future" msgstr "" diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js index e4f145ae81b..6a24b76abc8 100644 --- a/spec/frontend/blob/viewer/index_spec.js +++ b/spec/frontend/blob/viewer/index_spec.js @@ -6,6 +6,10 @@ import { setTestTimeout } from 'helpers/timeout'; import BlobViewer from '~/blob/viewer/index'; import axios from '~/lib/utils/axios_utils'; +const execImmediately = (callback) => { + callback(); +}; + describe('Blob viewer', () => { let blob; let mock; @@ -17,6 +21,7 @@ describe('Blob viewer', () => { setTestTimeout(2000); beforeEach(() => { + jest.spyOn(window, 'requestIdleCallback').mockImplementation(execImmediately); $.fn.extend(jQueryMock); mock = new MockAdapter(axios); diff --git a/spec/frontend/issues_list/components/issues_list_app_spec.js b/spec/frontend/issues_list/components/issues_list_app_spec.js index 75aa5eff7b2..846236e1fb5 100644 --- a/spec/frontend/issues_list/components/issues_list_app_spec.js +++ b/spec/frontend/issues_list/components/issues_list_app_spec.js @@ -78,7 +78,7 @@ describe('IssuesListApp component', () => { let defaultQueryResponse = getIssuesQueryResponse; if (IS_EE) { defaultQueryResponse = cloneDeep(getIssuesQueryResponse); - defaultQueryResponse.data.project.issues.nodes[0].blockedByCount = 1; + defaultQueryResponse.data.project.issues.nodes[0].blockingCount = 1; defaultQueryResponse.data.project.issues.nodes[0].healthStatus = null; defaultQueryResponse.data.project.issues.nodes[0].weight = 5; } |