From e0d7577e29dcab90623e1f38cf11b351c665ee23 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 12 Apr 2023 12:08:27 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .gitlab/ci/frontend.gitlab-ci.yml | 25 ++--- .gitlab/ci/review-apps/dast.gitlab-ci.yml | 10 +- .../javascripts/diffs/components/app.vue | 106 ++++++++++++------ .../diffs/components/diff_file.vue | 6 +- .../diffs/components/tree_list.vue | 6 +- app/assets/javascripts/diffs/store/actions.js | 15 ++- .../details_page/details_header.vue | 15 +-- .../explorer/constants/details.js | 2 +- ...container_repository_details.query.graphql | 1 - .../super_sidebar/components/groups_list.vue | 2 +- .../components/projects_list.vue | 2 +- .../components/work_item_detail.vue | 15 ++- app/assets/stylesheets/page_bundles/wiki.scss | 11 +- app/controllers/projects/blame_controller.rb | 11 +- .../projects/merge_requests_controller.rb | 1 + app/finders/group_members_finder.rb | 54 +++++++-- app/helpers/blame_helper.rb | 4 +- app/helpers/merge_requests_helper.rb | 4 + app/models/packages/event.rb | 1 + app/services/projects/blame_service.rb | 35 ++---- app/views/projects/blame/show.html.haml | 12 +- .../projects/merge_requests/_page.html.haml | 2 +- ...1223_API__NpmProjectPackages_list_tags.yml | 25 +++++ ...524_API__NpmProjectPackages_create_tag.yml | 25 +++++ ...627_API__NpmProjectPackages_delete_tag.yml | 25 +++++ ...004_API__NpmInstancePackages_list_tags.yml | 25 +++++ ...51_API__NpmInstancePackages_create_tag.yml | 25 +++++ ...37_API__NpmInstancePackages_delete_tag.yml | 25 +++++ .../development/ai_experimentation_api.yml | 8 ++ .../members_with_shared_group_access.yml | 8 ++ .../development/single_file_file_by_file.yml | 8 ++ doc/.vale/gitlab/Uppercase.yml | 1 + .../geo/replication/single_sign_on.md | 9 ++ doc/ci/cloud_services/google_cloud/index.md | 5 +- doc/ci/cloud_services/index.md | 6 +- .../index.md | 8 +- doc/ci/secrets/index.md | 11 +- doc/ci/variables/index.md | 3 +- doc/ci/variables/predefined_variables.md | 6 +- doc/development/application_secrets.md | 2 +- doc/development/fe_guide/style/vue.md | 12 ++ doc/integration/jira/configure.md | 13 ++- doc/integration/jira/development_panel.md | 4 +- jest.config.base.js | 5 +- lib/api/concerns/packages/npm_endpoints.rb | 6 + lib/gitlab/git/blame_mode.rb | 37 ++++++ locale/gitlab.pot | 28 ++++- spec/finders/group_members_finder_spec.rb | 97 ++++++++++------ spec/frontend/__helpers__/assert_props.js | 24 ++++ spec/frontend/blob/sketch/index_spec.js | 5 +- .../components/ci_variable_shared_spec.js | 42 +++---- .../runner_filtered_search_bar_spec.js | 14 ++- .../components/runner_type_badge_spec.js | 3 +- spec/frontend/diffs/components/app_spec.js | 35 ++++-- spec/frontend/diffs/store/actions_spec.js | 97 ++++++++++------ spec/frontend/environment.js | 11 +- .../monitoring/pages/dashboard_page_spec.js | 3 +- .../details_page/details_header_spec.js | 42 +++---- .../container_registry/explorer/mock_data.js | 1 - .../releases/components/releases_sort_spec.js | 3 +- .../components/groups_list_spec.js | 2 +- .../components/projects_list_spec.js | 2 +- .../components/widget/widget_spec.js | 5 +- .../markdown/markdown_editor_spec.js | 36 +++--- .../vue_shared/components/slot_switch_spec.js | 5 +- .../components/split_button_spec.js | 5 +- .../components/work_item_detail_spec.js | 3 +- spec/lib/gitlab/git/blame_mode_spec.rb | 84 ++++++++++++++ spec/services/projects/blame_service_spec.rb | 3 +- .../api/npm_packages_tags_shared_examples.rb | 21 ++++ 70 files changed, 865 insertions(+), 348 deletions(-) create mode 100644 config/events/20230327141223_API__NpmProjectPackages_list_tags.yml create mode 100644 config/events/20230327141524_API__NpmProjectPackages_create_tag.yml create mode 100644 config/events/20230327141627_API__NpmProjectPackages_delete_tag.yml create mode 100644 config/events/20230327142004_API__NpmInstancePackages_list_tags.yml create mode 100644 config/events/20230327142151_API__NpmInstancePackages_create_tag.yml create mode 100644 config/events/20230327142237_API__NpmInstancePackages_delete_tag.yml create mode 100644 config/feature_flags/development/ai_experimentation_api.yml create mode 100644 config/feature_flags/development/members_with_shared_group_access.yml create mode 100644 config/feature_flags/development/single_file_file_by_file.yml create mode 100644 lib/gitlab/git/blame_mode.rb create mode 100644 spec/frontend/__helpers__/assert_props.js create mode 100644 spec/lib/gitlab/git/blame_mode_spec.rb diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index ad7f4552ae3..97bd121e1aa 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -131,17 +131,21 @@ retrieve-frontend-fixtures: - .rails-cache - .use-pg13 stage: fixtures - needs: ["setup-test-env", "retrieve-tests-metadata"] + needs: ["setup-test-env", "retrieve-tests-metadata", "retrieve-frontend-fixtures"] variables: CRYSTALBALL: "false" WEBPACK_VENDOR_DLL: "true" script: - source scripts/utils.sh - source scripts/gitlab_component_helpers.sh - - install_gitlab_gem - - export_fixtures_sha_for_download - | - if check_fixtures_download; then + if [[ -d "tmp/tests/frontend" ]]; then + # Remove tmp/tests/frontend/ except on the first parallelized job so that depending + # jobs don't download the exact same artifact multiple times. + if [[ -n "${CI_NODE_INDEX}" ]] && [[ "${CI_NODE_INDEX}" -ne 1 ]]; then + echoinfo "INFO: Removing 'tmp/tests/frontend' as we're on node ${CI_NODE_INDEX}."; + rm -rf "tmp/tests/frontend"; + fi exit 0 else echo "No frontend fixtures directory, generating frontend fixtures." @@ -250,7 +254,7 @@ jest: extends: - .jest-base - .frontend:rules:jest - needs: ["rspec-all frontend_fixture", "retrieve-frontend-fixtures"] + needs: ["rspec-all frontend_fixture"] artifacts: name: coverage-frontend expire_in: 31d @@ -298,10 +302,7 @@ jest-integration: - .frontend:rules:default-frontend-jobs script: - run_timed_command "yarn jest:integration --ci" - needs: - - job: "rspec-all frontend_fixture" - - job: "retrieve-frontend-fixtures" - - job: "graphql-schema-dump" + needs: ["rspec-all frontend_fixture", "graphql-schema-dump"] coverage-frontend: extends: @@ -384,10 +385,7 @@ startup-css-check: extends: - .startup-css-check-base - .frontend:rules:default-frontend-jobs - needs: - - job: "compile-test-assets" - - job: "rspec-all frontend_fixture" - - job: "retrieve-frontend-fixtures" + needs: ["compile-test-assets", "rspec-all frontend_fixture"] startup-css-check as-if-foss: extends: @@ -414,7 +412,6 @@ compile-storybook: needs: - !reference [.compile-storybook-base, needs] - job: "rspec-all frontend_fixture" - - job: "retrieve-frontend-fixtures" artifacts: name: storybook expire_in: 31d diff --git a/.gitlab/ci/review-apps/dast.gitlab-ci.yml b/.gitlab/ci/review-apps/dast.gitlab-ci.yml index 8f0c6b60190..d3019577ab4 100644 --- a/.gitlab/ci/review-apps/dast.gitlab-ci.yml +++ b/.gitlab/ci/review-apps/dast.gitlab-ci.yml @@ -5,14 +5,14 @@ extends: - .reports:rules:schedule-dast image: - name: "${REGISTRY_HOST}/security-products/dast:$DAST_VERSION" + name: "${CI_TEMPLATE_REGISTRY_HOST}/security-products/dast:$DAST_VERSION" resource_group: dast_scan variables: - DAST_USERNAME_FIELD: "user[login]" - DAST_PASSWORD_FIELD: "user[password]" - DAST_SUBMIT_FIELD: "name:button" + DAST_USERNAME_FIELD: "name:user[login]" + DAST_PASSWORD_FIELD: "name:user[password]" + DAST_SUBMIT_FIELD: "css:.js-sign-in-button" DAST_FULL_SCAN_ENABLED: "true" - DAST_VERSION: 2 + DAST_VERSION: 3 GIT_STRATEGY: none # -Xmx is used to set the JVM memory to 6GB to prevent DAST OutOfMemoryError. DAST_ZAP_CLI_OPTIONS: "-Xmx6144m" diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 99bc3780b55..9b3db78724d 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -253,6 +253,9 @@ export default { renderDiffFiles() { return this.flatBlobsList.length > 0; }, + diffsIncomplete() { + return this.flatBlobsList.length !== this.diffFiles.length; + }, renderFileTree() { return this.renderDiffFiles && this.showTreeList; }, @@ -313,6 +316,11 @@ export default { diffViewType() { this.adjustView(); }, + viewDiffsFileByFile(newViewFileByFile) { + if (!newViewFileByFile && this.diffsIncomplete && this.glFeatures.singleFileFileByFile) { + this.refetchDiffData({ refetchMeta: false }); + } + }, shouldShow() { // When the shouldShow property changed to true, the route is rendered for the first time // and if we have the isLoading as true this means we didn't fetch the data @@ -429,13 +437,15 @@ export default { 'setCodequalityEndpoint', 'fetchDiffFilesMeta', 'fetchDiffFilesBatch', + 'fetchFileByFile', 'fetchCoverageFiles', 'fetchCodequality', + 'rereadNoteHash', 'startRenderDiffsQueue', 'assignDiscussionsToDiff', 'setHighlightedRow', 'cacheTreeListWidth', - 'scrollToFile', + 'goToFile', 'setShowTreeList', 'navigateToDiffFileIndex', 'setFileByFile', @@ -448,16 +458,27 @@ export default { subscribeToEvents() { notesEventHub.$once('fetchDiffData', this.fetchData); notesEventHub.$on('refetchDiffData', this.refetchDiffData); + if (this.glFeatures.singleFileFileByFile) { + diffsEventHub.$on('diffFilesModified', this.setDiscussions); + notesEventHub.$on('fetchedNotesData', this.rereadNoteHash); + } }, unsubscribeFromEvents() { + if (this.glFeatures.singleFileFileByFile) { + notesEventHub.$off('fetchedNotesData', this.rereadNoteHash); + diffsEventHub.$off('diffFilesModified', this.setDiscussions); + } notesEventHub.$off('refetchDiffData', this.refetchDiffData); notesEventHub.$off('fetchDiffData', this.fetchData); }, navigateToDiffFileNumber(number) { - this.navigateToDiffFileIndex(number - 1); + this.navigateToDiffFileIndex({ + index: number - 1, + singleFile: this.glFeatures.singleFileFileByFile, + }); }, - refetchDiffData() { - this.fetchData(false); + refetchDiffData({ refetchMeta = true } = {}) { + this.fetchData({ toggleTree: false, fetchMeta: refetchMeta }); }, needsReload() { return this.diffFiles.length && isSingleViewStyle(this.diffFiles[0]); @@ -465,44 +486,52 @@ export default { needsFirstLoad() { return !this.diffFiles.length; }, - fetchData(toggleTree = true) { - this.fetchDiffFilesMeta() - .then((data) => { - let realSize = 0; + fetchData({ toggleTree = true, fetchMeta = true } = {}) { + if (fetchMeta) { + this.fetchDiffFilesMeta() + .then((data) => { + let realSize = 0; - if (data) { - realSize = data.real_size; - } + if (data) { + realSize = data.real_size; - this.diffFilesLength = parseInt(realSize, 10) || 0; - if (toggleTree) { - this.setTreeDisplay(); - } + if (this.viewDiffsFileByFile && this.glFeatures.singleFileFileByFile) { + this.fetchFileByFile(); + } + } - updateChangesTabCount({ - count: this.diffFilesLength, + this.diffFilesLength = parseInt(realSize, 10) || 0; + if (toggleTree) { + this.setTreeDisplay(); + } + + updateChangesTabCount({ + count: this.diffFilesLength, + }); + }) + .catch(() => { + createAlert({ + message: __('Something went wrong on our end. Please try again!'), + }); }); - }) - .catch(() => { - createAlert({ - message: __('Something went wrong on our end. Please try again!'), - }); - }); + } - this.fetchDiffFilesBatch() - .then(() => { - if (toggleTree) this.setTreeDisplay(); - // Guarantee the discussions are assigned after the batch finishes. - // Just watching the length of the discussions or the diff files - // isn't enough, because with split diff loading, neither will - // change when loading the other half of the diff files. - this.setDiscussions(); - }) - .catch(() => { - createAlert({ - message: __('Something went wrong on our end. Please try again!'), + if (!this.viewDiffsFileByFile || !this.glFeatures.singleFileFileByFile) { + this.fetchDiffFilesBatch() + .then(() => { + if (toggleTree) this.setTreeDisplay(); + // Guarantee the discussions are assigned after the batch finishes. + // Just watching the length of the discussions or the diff files + // isn't enough, because with split diff loading, neither will + // change when loading the other half of the diff files. + this.setDiscussions(); + }) + .catch(() => { + createAlert({ + message: __('Something went wrong on our end. Please try again!'), + }); }); - }); + } if (this.endpointCoverage) { this.fetchCoverageFiles(); @@ -578,7 +607,10 @@ export default { jumpToFile(step) { const targetIndex = this.currentDiffIndex + step; if (targetIndex >= 0 && targetIndex < this.flatBlobsList.length) { - this.scrollToFile({ path: this.flatBlobsList[targetIndex].path }); + this.goToFile({ + path: this.flatBlobsList[targetIndex].path, + singleFile: this.glFeatures.singleFileFileByFile, + }); } }, setTreeDisplay() { diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue index c19174dda8a..a58178eaef7 100644 --- a/app/assets/javascripts/diffs/components/diff_file.vue +++ b/app/assets/javascripts/diffs/components/diff_file.vue @@ -209,7 +209,11 @@ export default { if (this.hasDiff) { this.postRender(); - } else if (this.viewDiffsFileByFile && !this.isCollapsed) { + } else if ( + this.viewDiffsFileByFile && + !this.isCollapsed && + !this.glFeatures.singleFileFileByFile + ) { this.requestDiff(); } diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue index 2675099a2f5..4f1875e9175 100644 --- a/app/assets/javascripts/diffs/components/tree_list.vue +++ b/app/assets/javascripts/diffs/components/tree_list.vue @@ -5,6 +5,7 @@ import micromatch from 'micromatch'; import { debounce } from 'lodash'; import { getModifierKey } from '~/constants'; import { s__, sprintf } from '~/locale'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { RecycleScroller } from 'vendor/vue-virtual-scroller'; import DiffFileRow from './diff_file_row.vue'; @@ -19,6 +20,7 @@ export default { DiffFileRow, RecycleScroller, }, + mixins: [glFeatureFlagsMixin()], props: { hideFileStats: { type: Boolean, @@ -105,7 +107,7 @@ export default { this.resizeObserver.disconnect(); }, methods: { - ...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']), + ...mapActions('diffs', ['toggleTreeOpen', 'goToFile']), clearSearch() { this.search = ''; }, @@ -175,7 +177,7 @@ export default { :class="{ 'tree-list-parent': item.level > 0 }" class="gl-relative" @toggleTreeOpen="toggleTreeOpen" - @clickFile="(path) => scrollToFile({ path })" + @clickFile="(path) => goToFile({ singleFile: glFeatures.singleFileFileByFile, path })" />