From 842ac3526cba09feb4b9ccefd0aeeb6edc02035d Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Fri, 8 Apr 2022 18:08:29 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/CODEOWNERS | 48 ++++++------- GITLAB_KAS_VERSION | 2 +- .../code_navigation/components/app.vue | 6 ++ .../code_navigation/store/actions.js | 6 +- .../code_navigation/store/mutations.js | 3 +- .../code_navigation/store/state.js | 1 + .../code_navigation/utils/dom_utils.js | 31 ++++++++ .../code_navigation/utils/index.js | 17 ++++- .../incidents/components/incidents_list.vue | 2 +- .../components/table/cells/actions_cell.vue | 6 ++ .../confirm_via_gl_modal/confirm_modal.vue | 1 + .../notes/components/noteable_note.vue | 8 ++- .../releases/components/app_edit_new.vue | 2 +- .../releases/components/app_index.vue | 2 +- .../components/blob_content_viewer.vue | 1 + .../user_lists/components/user_list_form.vue | 2 +- .../source_viewer/source_viewer.vue | 4 ++ app/models/note.rb | 38 +++++++++- app/models/user_custom_attribute.rb | 4 +- .../destroy_all_expired_service.rb | 10 ++- .../application_settings/_ci_cd.html.haml | 40 +++-------- .../application_settings/general.html.haml | 12 ++-- app/views/admin/users/show.html.haml | 4 +- ...artifact_fast_removal_large_loop_limit.yml | 8 --- .../dependency_scanning/index.md | 28 ++++---- .../test_coverage_visualization.md | 23 +++--- lib/gitlab/data_builder/deployment.rb | 2 +- locale/gitlab.pot | 23 ++++-- .../pipeline/multi-project_pipelines_spec.rb | 2 +- ...d_pipelines_dependent_relationship_spec.rb | 2 +- ...pipelines_independent_relationship_spec.rb | 2 +- qa/qa/support/loglinking.rb | 2 +- qa/spec/support/loglinking_spec.rb | 2 +- scripts/verify-tff-mapping | 2 +- .../projects/notes_controller_spec.rb | 16 ++++- spec/factories/ci/job_artifacts.rb | 50 +++++++++++++ .../merge_request/user_posts_notes_spec.rb | 2 +- .../master/gl-sast-report-bandit.json | 43 +++++++++++ .../master/gl-sast-report-gosec.json | 68 ++++++++++++++++++ .../gl-sast-report-semgrep-for-bandit.json | 71 ++++++++++++++++++ .../gl-sast-report-semgrep-for-gosec.json | 70 ++++++++++++++++++ .../code_navigation/components/app_spec.js | 7 +- .../code_navigation/store/actions_spec.js | 29 +++++--- .../code_navigation/store/mutations_spec.js | 2 + .../code_navigation/utils/index_spec.js | 30 +++++++- .../components/blob_content_viewer_spec.js | 1 + .../source_viewer/source_viewer_spec.js | 10 ++- spec/models/note_spec.rb | 72 ++++++++++++++++++- spec/policies/note_policy_spec.rb | 33 --------- .../mutations/notes/create/note_spec.rb | 23 +++++- .../api/issues/get_project_issues_spec.rb | 30 ++++++++ spec/requests/api/notes_spec.rb | 2 +- .../destroy_all_expired_service_spec.rb | 7 +- spec/services/notes/create_service_spec.rb | 17 +++-- spec/support/helpers/login_helpers.rb | 2 +- .../graphql/notes_creation_shared_examples.rb | 11 +++ .../api/issuable_participants_examples.rb | 30 -------- .../requests/api/notes_shared_examples.rb | 52 ++++++++------ 58 files changed, 775 insertions(+), 249 deletions(-) create mode 100644 app/assets/javascripts/code_navigation/utils/dom_utils.js delete mode 100644 config/feature_flags/development/ci_artifact_fast_removal_large_loop_limit.yml create mode 100644 spec/fixtures/security_reports/master/gl-sast-report-bandit.json create mode 100644 spec/fixtures/security_reports/master/gl-sast-report-gosec.json create mode 100644 spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-bandit.json create mode 100644 spec/fixtures/security_reports/master/gl-sast-report-semgrep-for-gosec.json diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index b76d5a2f675..40a59eaabe4 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -805,29 +805,29 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab /doc/user/workspace/index.md @fneill [Authentication and Authorization] -app/**/*password* @gitlab-org/manage/authentication-and-authorization -ee/app/**/*password* @gitlab-org/manage/authentication-and-authorization -config/**/*password* @gitlab-org/manage/authentication-and-authorization -ee/config/**/*password* @gitlab-org/manage/authentication-and-authorization -lib/**/*password* @gitlab-org/manage/authentication-and-authorization -ee/lib/**/*password* @gitlab-org/manage/authentication-and-authorization -app/controllers/**/*password* @gitlab-org/manage/authentication-and-authorization -ee/app/controllers/**/*password* @gitlab-org/manage/authentication-and-authorization +/app/**/*password* @gitlab-org/manage/authentication-and-authorization +/ee/app/**/*password* @gitlab-org/manage/authentication-and-authorization +/config/**/*password* @gitlab-org/manage/authentication-and-authorization +/ee/config/**/*password* @gitlab-org/manage/authentication-and-authorization +/lib/**/*password* @gitlab-org/manage/authentication-and-authorization +/ee/lib/**/*password* @gitlab-org/manage/authentication-and-authorization +/app/controllers/**/*password* @gitlab-org/manage/authentication-and-authorization +/ee/app/controllers/**/*password* @gitlab-org/manage/authentication-and-authorization -app/**/*auth* @gitlab-org/manage/authentication-and-authorization -ee/app/**/*auth* @gitlab-org/manage/authentication-and-authorization -config/**/*auth* @gitlab-org/manage/authentication-and-authorization -ee/config/**/*auth* @gitlab-org/manage/authentication-and-authorization -lib/**/*auth* @gitlab-org/manage/authentication-and-authorization -ee/lib/**/*auth* @gitlab-org/manage/authentication-and-authorization -app/controllers/**/*auth* @gitlab-org/manage/authentication-and-authorization -ee/app/controllers/**/*auth* @gitlab-org/manage/authentication-and-authorization +/app/**/*auth* @gitlab-org/manage/authentication-and-authorization +/ee/app/**/*auth* @gitlab-org/manage/authentication-and-authorization +/config/**/*auth* @gitlab-org/manage/authentication-and-authorization +/ee/config/**/*auth* @gitlab-org/manage/authentication-and-authorization +/lib/**/*auth* @gitlab-org/manage/authentication-and-authorization +/ee/lib/**/*auth* @gitlab-org/manage/authentication-and-authorization +/app/controllers/**/*auth* @gitlab-org/manage/authentication-and-authorization +/ee/app/controllers/**/*auth* @gitlab-org/manage/authentication-and-authorization -app/**/*token* @gitlab-org/manage/authentication-and-authorization -ee/app/**/*token* @gitlab-org/manage/authentication-and-authorization -config/**/*token* @gitlab-org/manage/authentication-and-authorization -ee/config/**/*token* @gitlab-org/manage/authentication-and-authorization -lib/**/*token* @gitlab-org/manage/authentication-and-authorization -ee/lib/**/*token* @gitlab-org/manage/authentication-and-authorization -app/controllers/**/*token* @gitlab-org/manage/authentication-and-authorization -ee/app/controllers/**/*token* @gitlab-org/manage/authentication-and-authorization +/app/**/*token* @gitlab-org/manage/authentication-and-authorization +/ee/app/**/*token* @gitlab-org/manage/authentication-and-authorization +/config/**/*token* @gitlab-org/manage/authentication-and-authorization +/ee/config/**/*token* @gitlab-org/manage/authentication-and-authorization +/lib/**/*token* @gitlab-org/manage/authentication-and-authorization +/ee/lib/**/*token* @gitlab-org/manage/authentication-and-authorization +/app/controllers/**/*token* @gitlab-org/manage/authentication-and-authorization +/ee/app/controllers/**/*token* @gitlab-org/manage/authentication-and-authorization diff --git a/GITLAB_KAS_VERSION b/GITLAB_KAS_VERSION index 44a5e718d50..3b112e6c2c1 100644 --- a/GITLAB_KAS_VERSION +++ b/GITLAB_KAS_VERSION @@ -1 +1 @@ -14.9.0 +14.10.0-rc2 diff --git a/app/assets/javascripts/code_navigation/components/app.vue b/app/assets/javascripts/code_navigation/components/app.vue index d65b9a71288..81edbb4182e 100644 --- a/app/assets/javascripts/code_navigation/components/app.vue +++ b/app/assets/javascripts/code_navigation/components/app.vue @@ -23,6 +23,11 @@ export default { required: false, default: null, }, + wrapTextNodes: { + type: Boolean, + required: false, + default: false, + }, }, computed: { ...mapState([ @@ -37,6 +42,7 @@ export default { const initialData = { blobs: [{ path: this.blobPath, codeNavigationPath: this.codeNavigationPath }], definitionPathPrefix: this.pathPrefix, + wrapTextNodes: this.wrapTextNodes, }; this.setInitialData(initialData); } diff --git a/app/assets/javascripts/code_navigation/store/actions.js b/app/assets/javascripts/code_navigation/store/actions.js index 0b6b8437db5..562b78a891a 100644 --- a/app/assets/javascripts/code_navigation/store/actions.js +++ b/app/assets/javascripts/code_navigation/store/actions.js @@ -22,7 +22,7 @@ export default { ...d, definitionLineNumber: parseInt(d.definition_path?.split('#L').pop() || 0, 10), }; - addInteractionClass(path, d); + addInteractionClass({ path, d, wrapTextNodes: state.wrapTextNodes }); } return acc; }, {}); @@ -34,7 +34,9 @@ export default { }, showBlobInteractionZones({ state }, path) { if (state.data && state.data[path]) { - Object.values(state.data[path]).forEach((d) => addInteractionClass(path, d)); + Object.values(state.data[path]).forEach((d) => + addInteractionClass({ path, d, wrapTextNodes: state.wrapTextNodes }), + ); } }, showDefinition({ commit, state }, { target: el }) { diff --git a/app/assets/javascripts/code_navigation/store/mutations.js b/app/assets/javascripts/code_navigation/store/mutations.js index 07b190c7476..98beffe231c 100644 --- a/app/assets/javascripts/code_navigation/store/mutations.js +++ b/app/assets/javascripts/code_navigation/store/mutations.js @@ -1,9 +1,10 @@ import * as types from './mutation_types'; export default { - [types.SET_INITIAL_DATA](state, { blobs, definitionPathPrefix }) { + [types.SET_INITIAL_DATA](state, { blobs, definitionPathPrefix, wrapTextNodes }) { state.blobs = blobs; state.definitionPathPrefix = definitionPathPrefix; + state.wrapTextNodes = wrapTextNodes; }, [types.REQUEST_DATA](state) { state.loading = true; diff --git a/app/assets/javascripts/code_navigation/store/state.js b/app/assets/javascripts/code_navigation/store/state.js index 569d2f7b319..17505b8392c 100644 --- a/app/assets/javascripts/code_navigation/store/state.js +++ b/app/assets/javascripts/code_navigation/store/state.js @@ -2,6 +2,7 @@ export default () => ({ blobs: [], loading: false, data: null, + wrapTextNodes: false, currentDefinition: null, currentDefinitionPosition: null, currentBlobPath: null, diff --git a/app/assets/javascripts/code_navigation/utils/dom_utils.js b/app/assets/javascripts/code_navigation/utils/dom_utils.js new file mode 100644 index 00000000000..1a65c1a64a2 --- /dev/null +++ b/app/assets/javascripts/code_navigation/utils/dom_utils.js @@ -0,0 +1,31 @@ +const TEXT_NODE = 3; + +const isTextNode = ({ nodeType }) => nodeType === TEXT_NODE; + +const isBlank = (str) => !str || /^\s*$/.test(str); + +const isMatch = (s1, s2) => !isBlank(s1) && s1.trim() === s2.trim(); + +const createSpan = (content) => { + const span = document.createElement('span'); + span.innerText = content; + return span; +}; + +const wrapSpacesWithSpans = (text) => text.replace(/ /g, createSpan(' ').outerHTML); + +const wrapTextWithSpan = (el, text) => { + if (isTextNode(el) && isMatch(el.textContent, text)) { + const newEl = createSpan(text.trim()); + el.replaceWith(newEl); + } +}; + +const wrapNodes = (text) => { + const wrapper = createSpan(); + wrapper.innerHTML = wrapSpacesWithSpans(text); + wrapper.childNodes.forEach((el) => wrapTextWithSpan(el, text)); + return wrapper.childNodes; +}; + +export { wrapNodes, isTextNode }; diff --git a/app/assets/javascripts/code_navigation/utils/index.js b/app/assets/javascripts/code_navigation/utils/index.js index 6c078891ed4..0d72153d8fe 100644 --- a/app/assets/javascripts/code_navigation/utils/index.js +++ b/app/assets/javascripts/code_navigation/utils/index.js @@ -1,9 +1,11 @@ +import { wrapNodes, isTextNode } from './dom_utils'; + export const cachedData = new Map(); export const getCurrentHoverElement = () => cachedData.get('current'); export const setCurrentHoverElement = (el) => cachedData.set('current', el); -export const addInteractionClass = (path, d) => { +export const addInteractionClass = ({ path, d, wrapTextNodes }) => { const lineNumber = d.start_line + 1; const lines = document .querySelector(`[data-path="${path}"]`) @@ -12,13 +14,24 @@ export const addInteractionClass = (path, d) => { lines.forEach((line) => { let charCount = 0; + + if (wrapTextNodes) { + line.childNodes.forEach((elm) => { + if (isTextNode(elm)) { + // Highlight.js does not wrap all text nodes by default + // We need all text nodes to be wrapped in order to append code nav attributes + elm.replaceWith(...wrapNodes(elm.textContent)); + } + }); + } + const el = [...line.childNodes].find(({ textContent }) => { if (charCount === d.start_char) return true; charCount += textContent.length; return false; }); - if (el) { + if (el && !isTextNode(el)) { el.setAttribute('data-char-index', d.start_char); el.setAttribute('data-line-index', d.start_line); el.classList.add('cursor-pointer', 'code-navigation', 'js-code-navigation'); diff --git a/app/assets/javascripts/incidents/components/incidents_list.vue b/app/assets/javascripts/incidents/components/incidents_list.vue index b55cd406adc..9e0c31e29e5 100644 --- a/app/assets/javascripts/incidents/components/incidents_list.vue +++ b/app/assets/javascripts/incidents/components/incidents_list.vue @@ -358,7 +358,7 @@ export default { :loading="redirecting" :disabled="redirecting" category="primary" - variant="success" + variant="confirm" :href="newIncidentPath" @click="navigateToCreateNewIncident" > diff --git a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue index 753a15871ab..f16e0287d5d 100644 --- a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue +++ b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue @@ -171,6 +171,7 @@ export default { data-testid="cancel-button" icon="cancel" :title="$options.CANCEL" + :aria-label="$options.CANCEL" :disabled="cancelBtnDisabled" @click="cancelJob()" /> @@ -182,6 +183,7 @@ export default { v-gl-modal-directive="$options.playJobModalId" icon="play" :title="$options.ACTIONS_START_NOW" + :aria-label="$options.ACTIONS_START_NOW" data-testid="play-scheduled" /> {{ $options.i18n.newRelease }} diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue index 85652301f4d..7aadc00ccea 100644 --- a/app/assets/javascripts/repository/components/blob_content_viewer.vue +++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue @@ -301,6 +301,7 @@ export default { :code-navigation-path="blobInfo.codeNavigationPath" :blob-path="blobInfo.path" :path-prefix="blobInfo.projectBlobPathRoot" + :wrap-text-nodes="glFeatures.highlightJs" /> diff --git a/app/assets/javascripts/user_lists/components/user_list_form.vue b/app/assets/javascripts/user_lists/components/user_list_form.vue index b53aaf46ace..44aa2d9a5b4 100644 --- a/app/assets/javascripts/user_lists/components/user_list_form.vue +++ b/app/assets/javascripts/user_lists/components/user_list_form.vue @@ -84,7 +84,7 @@ export default {
- + {{ saveButtonLabel }} diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue index 15411e8d17e..edf2229a9a1 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue @@ -1,6 +1,7 @@