diff --git a/.eslintrc.yml b/.eslintrc.yml index 4a7197e3bd5..75dc079cf6e 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -117,6 +117,10 @@ rules: message: 'Migrate to GlSkeletonLoader, or import GlDeprecatedSkeletonLoading.' - selector: ImportSpecifier[imported.name='GlSafeHtmlDirective'] message: 'Use directive at ~/vue_shared/directives/safe_html.js instead.' + # TODO: Remove this rule once GitLab UI no longer exports the deprecated alias. + # See https://gitlab.com/gitlab-org/gitlab/-/issues/382424. + - selector: ImportSpecifier[imported.name='GlListbox'] + message: 'Import GlCollapsibleListbox instead. The GlListbox name is deprecated.' # See https://gitlab.com/gitlab-org/gitlab/-/issues/360551 vue/multi-word-component-names: off unicorn/prefer-dom-node-dataset: diff --git a/.gitlab/ci/as-if-jh.gitlab-ci.yml b/.gitlab/ci/as-if-jh.gitlab-ci.yml index 6bd46bee770..73247984589 100644 --- a/.gitlab/ci/as-if-jh.gitlab-ci.yml +++ b/.gitlab/ci/as-if-jh.gitlab-ci.yml @@ -35,12 +35,11 @@ prepare-as-if-jh-branch: - .shared-as-if-jh - .as-if-jh:rules:prepare-as-if-jh stage: prepare + variables: + GIT_DEPTH: "0" # clone the full history so we can push needs: - add-jh-files script: - # Fetch for the history of the branch so it does not cause the following error: - # ! [remote rejected] ref -> ref (shallow update not allowed) - - git fetch --unshallow --filter=tree:0 origin "${CI_COMMIT_SHA}" - git checkout -b "${AS_IF_JH_BRANCH}" - git add ${JH_FILES_TO_COMMIT} - git commit -m 'Add JH files' # TODO: Mark which SHA we add diff --git a/.gitlab/ci/package-and-test/main.gitlab-ci.yml b/.gitlab/ci/package-and-test/main.gitlab-ci.yml index 62907acfd57..ff96b077d8d 100644 --- a/.gitlab/ci/package-and-test/main.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test/main.gitlab-ci.yml @@ -125,6 +125,7 @@ trigger-omnibus-env: echo "OMNIBUS_GITLAB_RUBY2_BUILD=${OMNIBUS_GITLAB_RUBY2_BUILD:-false}" >> $BUILD_ENV echo "OMNIBUS_GITLAB_CACHE_EDITION=${OMNIBUS_GITLAB_CACHE_EDITION:-GITLAB}" >> $BUILD_ENV echo "GITLAB_ASSETS_TAG=$(assets_image_tag)" >> $BUILD_ENV + echo "EE=$([[ $FOSS_ONLY == 'true' ]] && echo 'false' || echo 'true')" >> $BUILD_ENV echo "Built environment file for omnibus build:" cat $BUILD_ENV artifacts: @@ -156,7 +157,7 @@ trigger-omnibus: RUBY2_BUILD: $OMNIBUS_GITLAB_RUBY2_BUILD CACHE_EDITION: $OMNIBUS_GITLAB_CACHE_EDITION SKIP_QA_TEST: "true" - ee: "true" + ee: $EE trigger: project: gitlab-org/build/omnibus-gitlab-mirror strategy: depend @@ -203,7 +204,7 @@ cache-gems: # Run manual quarantine job # this job requires passing QA_SCENARIO variable # and optionally QA_TESTS to run specific quarantined tests -_ee:quarantine: +_quarantine: extends: - .qa - .rules:test:manual @@ -216,7 +217,7 @@ _ee:quarantine: # Temporary test job to support the effort of migrating to Super Sidebar # https://gitlab.com/groups/gitlab-org/-/epics/9044 -_ee:super-sidebar-nav: +_super-sidebar-nav: extends: - .qa - .parallel @@ -239,7 +240,7 @@ _ee:super-sidebar-nav: # ------------------------------------------ # Run specs with feature flags set to the opposite of the default state -ee:instance-ff-inverse: +instance-ff-inverse: extends: - .qa - .parallel @@ -253,23 +254,23 @@ ee:instance-ff-inverse: # ------------------------------------------ # Jobs with parallel variant # ------------------------------------------ -ee:instance-selective: +instance-selective: extends: .qa variables: QA_SCENARIO: Test::Instance::Image rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:instance: +instance: extends: - .parallel - - ee:instance-selective + - instance-selective rules: - - !reference [.rules:test:feature-flags-set, rules] # always run ee:instance to validate ff change + - !reference [.rules:test:feature-flags-set, rules] # always run instance to validate ff change - !reference [.rules:test:qa-parallel, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:praefect-selective: +praefect-selective: extends: .qa variables: QA_SCENARIO: Test::Integration::Praefect @@ -277,30 +278,30 @@ ee:praefect-selective: rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:praefect: +praefect: extends: - .parallel - - ee:praefect-selective + - praefect-selective rules: - !reference [.rules:test:qa-parallel, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:relative-url-selective: +relative-url-selective: extends: .qa variables: QA_SCENARIO: Test::Instance::RelativeUrl rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:relative-url: +relative-url: extends: - .parallel - - ee:relative-url-selective + - relative-url-selective rules: - !reference [.rules:test:qa-parallel, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:decomposition-single-db-selective: +decomposition-single-db-selective: extends: .qa variables: QA_SCENARIO: Test::Instance::Image @@ -308,15 +309,15 @@ ee:decomposition-single-db-selective: rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:decomposition-single-db: +decomposition-single-db: extends: - .parallel - - ee:decomposition-single-db-selective + - decomposition-single-db-selective rules: - !reference [.rules:test:qa-parallel, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:decomposition-multiple-db-selective: +decomposition-multiple-db-selective: extends: .qa variables: QA_SCENARIO: Test::Instance::Image @@ -325,15 +326,15 @@ ee:decomposition-multiple-db-selective: rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:decomposition-multiple-db: +decomposition-multiple-db: extends: - .parallel - - ee:decomposition-multiple-db-selective + - decomposition-multiple-db-selective rules: - !reference [.rules:test:qa-parallel, rules] - if: $QA_SUITES =~ /Test::Instance::All/ -ee:object-storage-selective: +object-storage-selective: extends: .qa variables: QA_SCENARIO: Test::Instance::Image @@ -342,42 +343,42 @@ ee:object-storage-selective: rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::ObjectStorage/ -ee:object-storage: - extends: ee:object-storage-selective +object-storage: + extends: object-storage-selective parallel: 2 rules: - !reference [.rules:test:qa-parallel, rules] - if: $QA_SUITES =~ /Test::Instance::ObjectStorage/ -ee:object-storage-aws-selective: - extends: ee:object-storage-selective +object-storage-aws-selective: + extends: object-storage-selective variables: AWS_S3_ACCESS_KEY: $QA_AWS_S3_ACCESS_KEY AWS_S3_BUCKET_NAME: $QA_AWS_S3_BUCKET_NAME AWS_S3_KEY_ID: $QA_AWS_S3_KEY_ID AWS_S3_REGION: $QA_AWS_S3_REGION GITLAB_QA_OPTS: --omnibus-config object_storage_aws -ee:object-storage-aws: - extends: ee:object-storage-aws-selective +object-storage-aws: + extends: object-storage-aws-selective parallel: 2 rules: - - !reference [ee:object-storage, rules] + - !reference [object-storage, rules] -ee:object-storage-gcs-selective: - extends: ee:object-storage-selective +object-storage-gcs-selective: + extends: object-storage-selective variables: GCS_BUCKET_NAME: $QA_GCS_BUCKET_NAME GOOGLE_PROJECT: $QA_GOOGLE_PROJECT GOOGLE_JSON_KEY: $QA_GOOGLE_JSON_KEY GOOGLE_CLIENT_EMAIL: $QA_GOOGLE_CLIENT_EMAIL GITLAB_QA_OPTS: --omnibus-config object_storage_gcs -ee:object-storage-gcs: - extends: ee:object-storage-gcs-selective +object-storage-gcs: + extends: object-storage-gcs-selective parallel: 2 rules: - - !reference [ee:object-storage, rules] + - !reference [object-storage, rules] -ee:packages-selective: +packages-selective: extends: .qa variables: QA_SCENARIO: Test::Instance::Image @@ -386,8 +387,8 @@ ee:packages-selective: rules: - !reference [.rules:test:qa-selective, rules] - if: $QA_SUITES =~ /Test::Instance::Packages/ -ee:packages: - extends: ee:packages-selective +packages: + extends: packages-selective parallel: 2 rules: - !reference [.rules:test:qa-parallel, rules] @@ -396,7 +397,7 @@ ee:packages: # ------------------------------------------ # Non parallel jobs # ------------------------------------------ -ee:update-minor: +update-minor: extends: - .qa - .update-script @@ -404,11 +405,12 @@ ee:update-minor: UPDATE_TYPE: minor QA_RSPEC_TAGS: --tag smoke rules: + - !reference [.rules:test:ee-only, rules] - !reference [.rules:test:update, rules] - if: $QA_SUITES =~ /Test::Instance::Smoke/ - !reference [.rules:test:manual, rules] -ee:update-major: +update-major: extends: - .qa - .update-script @@ -416,11 +418,12 @@ ee:update-major: UPDATE_TYPE: major QA_RSPEC_TAGS: --tag smoke rules: + - !reference [.rules:test:ee-only, rules] - !reference [.rules:test:update, rules] - if: $QA_SUITES =~ /Test::Instance::Smoke/ - !reference [.rules:test:manual, rules] -ee:gitlab-pages: +gitlab-pages: extends: .qa variables: QA_SCENARIO: Test::Integration::GitlabPages @@ -429,7 +432,7 @@ ee:gitlab-pages: - if: $QA_SUITES =~ /Test::Instance::GitlabPages/ - !reference [.rules:test:manual, rules] -ee:gitaly-cluster: +gitaly-cluster: extends: .qa variables: QA_SCENARIO: Test::Integration::GitalyCluster @@ -438,16 +441,17 @@ ee:gitaly-cluster: - if: $QA_SUITES =~ /Test::Integration::GitalyCluster/ - !reference [.rules:test:manual, rules] -ee:group-saml: +group-saml: extends: .qa variables: QA_SCENARIO: Test::Integration::GroupSAML rules: + - !reference [.rules:test:ee-only, rules] - !reference [.rules:test:qa, rules] - if: $QA_SUITES =~ /Test::Integration::GroupSAML/ - !reference [.rules:test:manual, rules] -ee:instance-saml: +instance-saml: extends: .qa variables: QA_SCENARIO: Test::Integration::InstanceSAML @@ -456,7 +460,7 @@ ee:instance-saml: - if: $QA_SUITES =~ /Test::Integration::InstanceSAML/ - !reference [.rules:test:manual, rules] -ee:jira: +jira: extends: .qa variables: QA_SCENARIO: Test::Integration::Jira @@ -467,7 +471,7 @@ ee:jira: - if: $QA_SUITES =~ /Test::Integration::Jira/ - !reference [.rules:test:manual, rules] -ee:integrations: +integrations: extends: .qa variables: QA_SCENARIO: Test::Integration::Integrations @@ -476,7 +480,7 @@ ee:integrations: - if: $QA_SUITES =~ /Test::Integration::Integrations/ - !reference [.rules:test:manual, rules] -ee:ldap-no-server: +ldap-no-server: extends: .qa variables: QA_SCENARIO: Test::Integration::LDAPNoServer @@ -485,7 +489,7 @@ ee:ldap-no-server: - if: $QA_SUITES =~ /Test::Integration::LDAPNoServer/ - !reference [.rules:test:manual, rules] -ee:ldap-tls: +ldap-tls: extends: .qa variables: QA_SCENARIO: Test::Integration::LDAPTLS @@ -494,7 +498,7 @@ ee:ldap-tls: - if: $QA_SUITES =~ /Test::Integration::LDAPTLS/ - !reference [.rules:test:manual, rules] -ee:ldap-no-tls: +ldap-no-tls: extends: .qa variables: QA_SCENARIO: Test::Integration::LDAPNoTLS @@ -503,7 +507,7 @@ ee:ldap-no-tls: - if: $QA_SUITES =~ /Test::Integration::LDAPNoTLS/ - !reference [.rules:test:manual, rules] -ee:mtls: +mtls: extends: .qa variables: QA_SCENARIO: Test::Integration::MTLS @@ -512,7 +516,7 @@ ee:mtls: - if: $QA_SUITES =~ /Test::Integration::Mtls/ - !reference [.rules:test:manual, rules] -ee:mattermost: +mattermost: extends: .qa variables: QA_SCENARIO: Test::Integration::Mattermost @@ -521,7 +525,7 @@ ee:mattermost: - if: $QA_SUITES =~ /Test::Integration::Mattermost/ - !reference [.rules:test:manual, rules] -ee:registry: +registry: extends: .qa variables: QA_SCENARIO: Test::Integration::Registry @@ -530,7 +534,7 @@ ee:registry: - if: $QA_SUITES =~ /Test::Integration::Registry/ - !reference [.rules:test:manual, rules] -ee:registry-with-cdn: +registry-with-cdn: extends: .qa variables: QA_SCENARIO: Test::Integration::RegistryWithCDN @@ -547,7 +551,7 @@ ee:registry-with-cdn: - if: $QA_SUITES =~ /Test::Integration::RegistryWithCDN/ - !reference [.rules:test:manual, rules] -ee:repository-storage: +repository-storage: extends: .qa variables: QA_SCENARIO: Test::Instance::RepositoryStorage @@ -556,7 +560,7 @@ ee:repository-storage: - if: $QA_SUITES =~ /Test::Instance::RepositoryStorage/ - !reference [.rules:test:manual, rules] -ee:service-ping-disabled: +service-ping-disabled: extends: .qa variables: QA_SCENARIO: Test::Integration::ServicePingDisabled @@ -565,7 +569,7 @@ ee:service-ping-disabled: - if: $QA_SUITES =~ /Test::Integration::ServicePingDisabled/ - !reference [.rules:test:manual, rules] -ee:smtp: +smtp: extends: .qa variables: QA_SCENARIO: Test::Integration::SMTP @@ -574,7 +578,7 @@ ee:smtp: - if: $QA_SUITES =~ /Test::Integration::SMTP/ - !reference [.rules:test:manual, rules] -ee:cloud-activation: +cloud-activation: extends: .qa variables: QA_SCENARIO: Test::Instance::Image @@ -584,7 +588,7 @@ ee:cloud-activation: - if: $QA_SUITES =~ /Test::Instance::CloudActivation/ - !reference [.rules:test:manual, rules] -ee:large-setup: +large-setup: extends: .qa variables: QA_SCENARIO: Test::Instance::Image @@ -594,7 +598,7 @@ ee:large-setup: - if: $QA_SUITES =~ /Test::Instance::LargeSetup/ - !reference [.rules:test:manual, rules] -ee:metrics: +metrics: extends: .qa variables: QA_SCENARIO: Test::Integration::Metrics @@ -603,26 +607,27 @@ ee:metrics: - if: $QA_SUITES =~ /Test::Instance::Metrics/ - !reference [.rules:test:manual, rules] -ee:elasticsearch: +elasticsearch: extends: .qa variables: QA_SCENARIO: "Test::Integration::Elasticsearch" before_script: - !reference [.qa, before_script] rules: + - !reference [.rules:test:ee-only, rules] - !reference [.rules:test:qa, rules] - if: $QA_SUITES =~ /Test::Integration::Elasticsearch/ - !reference [.rules:test:manual, rules] -ee:registry-object-storage-tls: - extends: ee:object-storage-aws-selective +registry-object-storage-tls: + extends: object-storage-aws-selective variables: QA_SCENARIO: Test::Integration::RegistryTLS QA_RSPEC_TAGS: "" GITLAB_TLS_CERTIFICATE: $QA_GITLAB_TLS_CERTIFICATE GITLAB_QA_OPTS: --omnibus-config registry_object_storage -ee:importers: +importers: extends: .qa variables: QA_SCENARIO: Test::Integration::Import @@ -655,7 +660,7 @@ e2e-test-report-super-sidebar: - .generate-allure-report-base stage: report needs: - - _ee:super-sidebar-nav + - _super-sidebar-nav variables: ALLURE_JOB_NAME: e2e-super-sidebar ALLURE_RESULTS_GLOB: gitlab-qa-run-*/**/allure-results-super-sidebar diff --git a/.gitlab/ci/package-and-test/rules.gitlab-ci.yml b/.gitlab/ci/package-and-test/rules.gitlab-ci.yml index 50b07589040..a371939b536 100644 --- a/.gitlab/ci/package-and-test/rules.gitlab-ci.yml +++ b/.gitlab/ci/package-and-test/rules.gitlab-ci.yml @@ -123,6 +123,11 @@ when: never - !reference [.rules:test:qa, rules] +.rules:test:ee-only: + rules: + - if: $FOSS_ONLY == "true" + when: never + # ------------------------------------------ # Report # ------------------------------------------ diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index aea85dfd084..95ae215d134 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -65,7 +65,7 @@ qa:update-qa-cache: script: - echo "Cache has been updated and ready to be uploaded." -e2e:package-and-test: +e2e:package-and-test-ee: extends: - .production # this makes sure GITLAB_ALLOW_SEPARATE_CI_DATABASE is passed to the child pipeline - .qa:rules:package-and-test @@ -82,6 +82,8 @@ e2e:package-and-test: GITLAB_QA_IMAGE: "${CI_REGISTRY_IMAGE}/gitlab-ee-qa:${CI_COMMIT_SHA}" RUN_WITH_BUNDLE: "true" # instructs pipeline to install and run gitlab-qa gem via bundler QA_PATH: qa # sets the optional path for bundler to run from + ALLURE_JOB_NAME: e2e-package-and-test + QA_RUN_TYPE: e2e-package-and-test inherit: variables: - CHROME_VERSION diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index 146522c5e76..75b7808e17e 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -514,23 +514,6 @@ Layout/ArgumentAlignment: - 'app/graphql/types/work_items/widgets/start_and_due_date_update_input_type.rb' - 'app/graphql/types/x509_certificate_type.rb' - 'app/graphql/types/x509_issuer_type.rb' - - 'app/helpers/application_helper.rb' - - 'app/helpers/application_settings_helper.rb' - - 'app/helpers/blob_helper.rb' - - 'app/helpers/ci/status_helper.rb' - - 'app/helpers/commits_helper.rb' - - 'app/helpers/dashboard_helper.rb' - - 'app/helpers/events_helper.rb' - - 'app/helpers/feature_flags_helper.rb' - - 'app/helpers/issuables_helper.rb' - - 'app/helpers/mirror_helper.rb' - - 'app/helpers/notes_helper.rb' - - 'app/helpers/projects/error_tracking_helper.rb' - - 'app/helpers/snippets_helper.rb' - - 'app/helpers/todos_helper.rb' - - 'app/helpers/users/group_callouts_helper.rb' - - 'app/helpers/users_helper.rb' - - 'app/helpers/visibility_level_helper.rb' - 'app/mailers/emails/projects.rb' - 'app/mailers/notify.rb' - 'app/models/abuse_report.rb' @@ -1182,9 +1165,6 @@ Layout/ArgumentAlignment: - 'ee/app/graphql/types/work_items/widgets/status_filter_input_type.rb' - 'ee/app/graphql/types/work_items/widgets/status_input_type.rb' - 'ee/app/graphql/types/work_items/widgets/weight_input_type.rb' - - 'ee/app/helpers/billing_plans_helper.rb' - - 'ee/app/helpers/ee/feature_flags_helper.rb' - - 'ee/app/helpers/ee/search_helper.rb' - 'ee/app/mailers/ee/emails/projects.rb' - 'ee/app/mailers/emails/namespace_storage_usage_mailer.rb' - 'ee/app/models/approval_wrapped_rule.rb' diff --git a/.rubocop_todo/rake/require.yml b/.rubocop_todo/rake/require.yml index 04a474b5fe7..6dc5bfa7abc 100644 --- a/.rubocop_todo/rake/require.yml +++ b/.rubocop_todo/rake/require.yml @@ -2,11 +2,6 @@ Rake/Require: Details: grace period Exclude: - - 'lib/tasks/gitlab/docs/redirect.rake' - - 'lib/tasks/gitlab/graphql.rake' - - 'lib/tasks/gitlab/lfs/migrate.rake' - - 'lib/tasks/gitlab/metrics_exporter.rake' - - 'lib/tasks/gitlab/openapi.rake' - 'lib/tasks/gitlab/packages/events.rake' - 'lib/tasks/gitlab/refresh_project_statistics_build_artifacts_size.rake' - 'lib/tasks/tokens.rake' diff --git a/CHANGELOG.md b/CHANGELOG.md index feaf0e9997a..8d00761e265 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 15.9.3 (2023-03-09) + +### Fixed (4 changes) + +- [Fix foreign_key_exists? migration helper](gitlab-org/gitlab@7b51239b18779acfe9876fb9467f1231f56d47b4) ([merge request](gitlab-org/gitlab!114005)) +- [Enable Geo::RepositoryRegistrySyncWorker on Geo secondary site](gitlab-org/gitlab@57b542b4377bcc991b65f34a37397ac1d08846d9) ([merge request](gitlab-org/gitlab!114005)) **GitLab Enterprise Edition** +- [Guard against dropped columns when finalizing user details migration](gitlab-org/gitlab@939d646e2cbbbabf870e15fae384c0380d371111) ([merge request](gitlab-org/gitlab!114005)) +- [Fix object deletion not working with Azure Blob Storage](gitlab-org/gitlab@9515c7a334a43c0e580543029a8da5061bdc19ce) ([merge request](gitlab-org/gitlab!114005)) + ## 15.9.2 (2023-03-02) ### Security (12 changes) diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js index ee4721c3ee3..d865354881a 100644 --- a/app/assets/javascripts/filtered_search/filtered_search_manager.js +++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js @@ -2,6 +2,7 @@ import { last } from 'lodash'; import recentSearchesStorageKeys from 'ee_else_ce/filtered_search/recent_searches_storage_keys'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; import { createAlert } from '~/alert'; +import { WORKSPACE_PROJECT } from '~/issues/constants'; import { ENTER_KEY_CODE, BACKSPACE_KEY_CODE, @@ -82,7 +83,7 @@ export default class FilteredSearchManager { ); const fullPath = this.searchHistoryDropdownElement ? this.searchHistoryDropdownElement.dataset.fullPath - : 'project'; + : WORKSPACE_PROJECT; const recentSearchesKey = `${fullPath}-${recentSearchesStorageKeys[this.page]}`; this.recentSearchesService = new RecentSearchesService(recentSearchesKey); } diff --git a/app/assets/javascripts/groups/store/utils.js b/app/assets/javascripts/groups/store/utils.js index 371b3aa9d52..d4b583483bd 100644 --- a/app/assets/javascripts/groups/store/utils.js +++ b/app/assets/javascripts/groups/store/utils.js @@ -1,3 +1,5 @@ +import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; + export const getGroupItemMicrodata = ({ type }) => { const defaultMicrodata = { itemscope: true, @@ -9,14 +11,14 @@ export const getGroupItemMicrodata = ({ type }) => { }; switch (type) { - case 'group': + case WORKSPACE_GROUP: return { ...defaultMicrodata, itemtype: 'https://schema.org/Organization', itemprop: 'subOrganization', imageItemprop: 'logo', }; - case 'project': + case WORKSPACE_PROJECT: return { ...defaultMicrodata, itemtype: 'https://schema.org/SoftwareSourceCode', diff --git a/app/assets/javascripts/issuable/popover/components/mr_popover.vue b/app/assets/javascripts/issuable/popover/components/mr_popover.vue index 92994809362..af93430963e 100644 --- a/app/assets/javascripts/issuable/popover/components/mr_popover.vue +++ b/app/assets/javascripts/issuable/popover/components/mr_popover.vue @@ -1,14 +1,12 @@ @@ -51,7 +54,9 @@ export default { diff --git a/app/assets/javascripts/vue_shared/plugins/global_toast.js b/app/assets/javascripts/vue_shared/plugins/global_toast.js index fb52b31c2c8..bfea2bedd40 100644 --- a/app/assets/javascripts/vue_shared/plugins/global_toast.js +++ b/app/assets/javascripts/vue_shared/plugins/global_toast.js @@ -2,7 +2,7 @@ import { GlToast } from '@gitlab/ui'; import Vue from 'vue'; Vue.use(GlToast); -export const instance = new Vue(); +const instance = new Vue(); export default function showGlobalToast(...args) { return instance.$toast.show(...args); diff --git a/app/assets/stylesheets/page_bundles/incidents.scss b/app/assets/stylesheets/page_bundles/incidents.scss index 493add1ea0f..fde35ab3d39 100644 --- a/app/assets/stylesheets/page_bundles/incidents.scss +++ b/app/assets/stylesheets/page_bundles/incidents.scss @@ -57,8 +57,6 @@ } .timeline-entry:not(:last-child) { - @include gl-pb-0; - .timeline-event-border { @include gl-pb-3; @include gl-border-gray-50; diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 3639b7f1eea..0dbed262a75 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -1,4 +1,4 @@ -$system-note-icon-size: 2rem; +$system-note-icon-size: 1.5rem; $system-note-svg-size: 1rem; @mixin vertical-line($left) { @@ -36,6 +36,15 @@ $system-note-svg-size: 1rem; &.timeline > .timeline-entry { margin: $gl-padding 0; + &.system-note { + margin-top: $gl-spacing-scale-1; + margin-bottom: 0; + + .note-header-info { + padding-left: $gl-spacing-scale-4; + } + } + &.system-note, &.note-form { border: 0; @@ -447,7 +456,7 @@ $system-note-svg-size: 1rem; height: $system-note-icon-size; border: 1px solid $gray-50; border-radius: $system-note-icon-size; - margin: -6px 0 0; + margin: -$gl-spacing-scale-1 0 0 $gl-spacing-scale-2; svg { width: $system-note-svg-size; diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index d822a297856..d0602952f9a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -181,14 +181,14 @@ module ApplicationHelper css_classes << html_class unless html_class.blank? content_tag :time, l(time, format: "%b %d, %Y"), - class: css_classes.join(' '), - title: l(time.to_time.in_time_zone, format: :timeago_tooltip), - datetime: time.to_time.getutc.iso8601, - data: { - toggle: 'tooltip', - placement: placement, - container: 'body' - } + class: css_classes.join(' '), + title: l(time.to_time.in_time_zone, format: :timeago_tooltip), + datetime: time.to_time.getutc.iso8601, + data: { + toggle: 'tooltip', + placement: placement, + container: 'body' + } end def edited_time_ago_with_tooltip(object, placement: 'top', html_class: 'time_ago', exclude_author: false) diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index dd5f4f17ee2..fde3da77250 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -4,11 +4,11 @@ module ApplicationSettingsHelper extend self delegate :allow_signup?, - :gravatar_enabled?, - :password_authentication_enabled_for_web?, - :akismet_enabled?, - :spam_check_endpoint_enabled?, - to: :'Gitlab::CurrentSettings.current_application_settings' + :gravatar_enabled?, + :password_authentication_enabled_for_web?, + :akismet_enabled?, + :spam_check_endpoint_enabled?, + to: :'Gitlab::CurrentSettings.current_application_settings' def user_oauth_applications? Gitlab::CurrentSettings.user_oauth_applications diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 281d5c923d0..bb6fd6c3dad 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -2,9 +2,7 @@ module BlobHelper def edit_blob_path(project = @project, ref = @ref, path = @path, options = {}) - project_edit_blob_path(project, - tree_join(ref, path), - options[:link_opts]) + project_edit_blob_path(project, tree_join(ref, path), options[:link_opts]) end def ide_edit_path(project = @project, ref = @ref, path = @path) @@ -52,9 +50,11 @@ module BlobHelper def fork_path_for_current_user(project, path, with_notice: true) return unless current_user - project_forks_path(project, - namespace_key: current_user.namespace&.id, - continue: edit_blob_fork_params(path, with_notice: with_notice)) + project_forks_path( + project, + namespace_key: current_user.namespace&.id, + continue: edit_blob_fork_params(path, with_notice: with_notice) + ) end def encode_ide_path(path) @@ -66,12 +66,14 @@ module BlobHelper common_classes = "btn gl-button btn-confirm js-edit-blob gl-ml-3 #{options[:extra_class]}" - edit_button_tag(blob, - common_classes, - _('Edit'), - edit_blob_path(project, ref, path, options), - project, - ref) + edit_button_tag( + blob, + common_classes, + _('Edit'), + edit_blob_path(project, ref, path, options), + project, + ref + ) end def can_modify_blob?(blob, project = @project, ref = @ref) @@ -282,8 +284,8 @@ module BlobHelper fork_path = project_forks_path(project, namespace_key: current_user.namespace.id, continue: params) button_tag label, - class: "#{common_classes} js-edit-blob-link-fork-toggler", - data: { action: action, fork_path: fork_path } + class: "#{common_classes} js-edit-blob-link-fork-toggler", + data: { action: action, fork_path: fork_path } end def edit_disabled_button_tag(button_text, common_classes) diff --git a/app/helpers/ci/status_helper.rb b/app/helpers/ci/status_helper.rb index bca49324a19..ea5b613cb78 100644 --- a/app/helpers/ci/status_helper.rb +++ b/app/helpers/ci/status_helper.rb @@ -131,10 +131,10 @@ module Ci if path link_to ci_icon_for_status(status, size: icon_size), path, - class: klass, title: title, data: data + class: klass, title: title, data: data else content_tag :span, ci_icon_for_status(status, size: icon_size), - class: klass, title: title, data: data + class: klass, title: title, data: data end end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index f4893a83304..519508f1c02 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -27,12 +27,11 @@ module CommitsHelper end def commit_to_html(commit, ref, project) - render partial: 'projects/commits/commit', formats: :html, - locals: { - commit: commit, - ref: ref, - project: project - } + render partial: 'projects/commits/commit', formats: :html, locals: { + commit: commit, + ref: ref, + project: project + } end # Breadcrumb links for a Project and, if applicable, a tree path @@ -194,10 +193,12 @@ module CommitsHelper entity = mode == 'raw' ? 'rawButton' : 'renderedButton' title = "Display #{mode} diff" - link_to("##{mode}-diff-#{file_hash}", - class: "btn gl-button btn-default btn-file-option has-tooltip btn-show-#{mode}-diff", - title: title, - data: { file_hash: file_hash, diff_toggle_entity: entity }) do + link_to( + "##{mode}-diff-#{file_hash}", + class: "btn gl-button btn-default btn-file-option has-tooltip btn-show-#{mode}-diff", + title: title, + data: { file_hash: file_hash, diff_toggle_entity: entity } + ) do sprite_icon(icon) end end diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb index f0e1f252917..7bb382e14df 100644 --- a/app/helpers/dashboard_helper.rb +++ b/app/helpers/dashboard_helper.rb @@ -40,9 +40,14 @@ module DashboardHelper end) if doc_href.present? - link_to_doc = link_to(sprite_icon('question'), doc_href, - class: 'gl-ml-2', title: _('Documentation'), - target: '_blank', rel: 'noopener noreferrer') + link_to_doc = link_to( + sprite_icon('question'), + doc_href, + class: 'gl-ml-2', + title: _('Documentation'), + target: '_blank', + rel: 'noopener noreferrer' + ) concat(link_to_doc) end diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index bef2da495b0..795d35ec81f 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -29,10 +29,11 @@ module EventsHelper opened: s_('Event|opened'), updated: s_('Event|updated'), 'removed due to membership expiration from': s_('Event|removed due to membership expiration from') - }.merge(localized_push_action_name_map, - localized_created_project_action_name_map, - localized_design_action_names - ).freeze + }.merge( + localized_push_action_name_map, + localized_created_project_action_name_map, + localized_design_action_names + ).freeze end def localized_push_action_name_map @@ -183,13 +184,11 @@ module EventsHelper def event_feed_url(event) if event.issue? - project_issue_url(event.project, - event.issue) + project_issue_url(event.project, event.issue) elsif event.merge_request? project_merge_request_url(event.project, event.merge_request) elsif event.commit_note? - project_commit_url(event.project, - event.note_target) + project_commit_url(event.project, event.note_target) elsif event.note? if event.note_target event_note_target_url(event) @@ -204,16 +203,12 @@ module EventsHelper def push_event_feed_url(event) if event.push_with_commits? && event.md_ref? if event.commits_count > 1 - project_compare_url(event.project, - from: event.commit_from, to: - event.commit_to) + project_compare_url(event.project, from: event.commit_from, to: event.commit_to) else - project_commit_url(event.project, - id: event.commit_to) + project_commit_url(event.project, id: event.commit_to) end elsif event.ref_name - project_commits_url(event.project, - event.ref_name) + project_commits_url(event.project, event.ref_name) end end @@ -241,26 +236,31 @@ module EventsHelper elsif event.design_note? design_url(event.note_target, anchor: dom_id(event.note)) else - polymorphic_url([event.project, event.note_target], - anchor: dom_id(event.target)) + polymorphic_url([event.project, event.note_target], anchor: dom_id(event.target)) end end def event_wiki_title_html(event) capture do concat content_tag(:span, _('wiki page'), class: "event-target-type gl-mr-2") - concat link_to(event.target_title, event_wiki_page_target_url(event), - title: event.target_title, - class: 'has-tooltip event-target-link gl-mr-2') + concat link_to( + event.target_title, + event_wiki_page_target_url(event), + title: event.target_title, + class: 'has-tooltip event-target-link gl-mr-2' + ) end end def event_design_title_html(event) capture do concat content_tag(:span, _('design'), class: "event-target-type gl-mr-2") - concat link_to(event.design.reference_link_text, design_url(event.design), - title: event.target_title, - class: 'has-tooltip event-design event-target-link gl-mr-2') + concat link_to( + event.design.reference_link_text, + design_url(event.design), + title: event.target_title, + class: 'has-tooltip event-design event-target-link gl-mr-2' + ) end end diff --git a/app/helpers/feature_flags_helper.rb b/app/helpers/feature_flags_helper.rb index 3dde29dce91..fe8d8e6b5d9 100644 --- a/app/helpers/feature_flags_helper.rb +++ b/app/helpers/feature_flags_helper.rb @@ -18,8 +18,10 @@ module FeatureFlagsHelper feature_flags_path: project_feature_flags_path(@project), environments_endpoint: search_project_environments_path(@project, format: :json), strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'), - environments_scope_docs_path: help_page_path('ci/environments/index.md', - anchor: 'limit-the-environment-scope-of-a-cicd-variable') + environments_scope_docs_path: help_page_path( + 'ci/environments/index.md', + anchor: 'limit-the-environment-scope-of-a-cicd-variable' + ) } end end diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb index 0d93aff2bae..9c68f54f42e 100644 --- a/app/helpers/issuables_helper.rb +++ b/app/helpers/issuables_helper.rb @@ -380,8 +380,10 @@ module IssuablesHelper end def hidden_issuable_icon(issuable) - title = format(_('This %{issuable} is hidden because its author has been banned'), - issuable: issuable.is_a?(Issue) ? _('issue') : _('merge request')) + title = format( + _('This %{issuable} is hidden because its author has been banned'), + issuable: issuable.is_a?(Issue) ? _('issue') : _('merge request') + ) content_tag(:span, class: 'has-tooltip', title: title) do sprite_icon('spam', css_class: 'gl-vertical-align-text-bottom') end diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb index 3dfd30f07db..06deaeb5e9e 100644 --- a/app/helpers/mirror_helper.rb +++ b/app/helpers/mirror_helper.rb @@ -13,7 +13,7 @@ module MirrorHelper docs_link_start = ''.html_safe % { url: docs_link_url } html_escape(_('Git LFS objects will be synced if LFS is %{docs_link_start}enabled for the project%{docs_link_end}. Push mirrors will %{strong_open}not%{strong_close} sync LFS objects over SSH.')) % - { docs_link_start: docs_link_start, docs_link_end: ''.html_safe, strong_open: ''.html_safe, strong_close: ''.html_safe } + { docs_link_start: docs_link_start, docs_link_end: ''.html_safe, strong_open: ''.html_safe, strong_close: ''.html_safe } end end diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index b47f4633348..3df9d68b03e 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -77,8 +77,10 @@ module NotesHelper line_type: line_type } - button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button', - data: data, title: 'Add a reply' + button_tag 'Reply...', + class: 'btn btn-text-field js-discussion-reply-button', + data: data, + title: 'Add a reply' end def note_max_access_for_user(note) diff --git a/app/helpers/projects/error_tracking_helper.rb b/app/helpers/projects/error_tracking_helper.rb index 471565d162c..fc4ad10db21 100644 --- a/app/helpers/projects/error_tracking_helper.rb +++ b/app/helpers/projects/error_tracking_helper.rb @@ -5,8 +5,7 @@ module Projects::ErrorTrackingHelper error_tracking_enabled = !!project.error_tracking_setting&.enabled? { - 'index-path' => project_error_tracking_index_path(project, - format: :json), + 'index-path' => project_error_tracking_index_path(project, format: :json), 'user-can-enable-error-tracking' => can?(current_user, :admin_operations, project).to_s, 'enable-error-tracking-link' => project_settings_operations_path(project), 'error-tracking-enabled' => error_tracking_enabled.to_s, diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb index 8558c664977..2f9117a74be 100644 --- a/app/helpers/snippets_helper.rb +++ b/app/helpers/snippets_helper.rb @@ -45,30 +45,35 @@ module SnippetsHelper def embedded_raw_snippet_button(snippet, blob) return if blob.empty? || blob.binary? || blob.stored_externally? - link_to(external_snippet_icon('doc-code'), - gitlab_raw_snippet_blob_url(snippet, blob.path), - class: 'gl-button btn btn-default', - target: '_blank', - rel: 'noopener noreferrer', - title: 'Open raw') + link_to( + external_snippet_icon('doc-code'), + gitlab_raw_snippet_blob_url(snippet, blob.path), + class: 'gl-button btn btn-default', + target: '_blank', + rel: 'noopener noreferrer', + title: 'Open raw' + ) end def embedded_snippet_download_button(snippet, blob) - link_to(external_snippet_icon('download'), - gitlab_raw_snippet_blob_url(snippet, blob.path, nil, inline: false), - class: 'gl-button btn btn-default', - target: '_blank', - title: 'Download', - rel: 'noopener noreferrer') + link_to( + external_snippet_icon('download'), + gitlab_raw_snippet_blob_url(snippet, blob.path, nil, inline: false), + class: 'gl-button btn btn-default', + target: '_blank', + title: 'Download', + rel: 'noopener noreferrer' + ) end def embedded_copy_snippet_button(blob) return unless blob.rendered_as_text?(ignore_errors: false) - content_tag(:button, - class: 'gl-button btn btn-default copy-to-clipboard-btn', - title: 'Copy snippet contents', - onclick: "copyToClipboard('.blob-content[data-blob-id=\"#{blob.id}\"] > pre')" + content_tag( + :button, + class: 'gl-button btn btn-default copy-to-clipboard-btn', + title: 'Copy snippet contents', + onclick: "copyToClipboard('.blob-content[data-blob-id=\"#{blob.id}\"] > pre')" ) do external_snippet_icon('copy-to-clipboard') end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 4a9dd30a5a2..9b0810f3d17 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -232,13 +232,15 @@ module TodosHelper '' end + due_date = + if is_due_today + _("today") + else + l(todo.target.due_date, format: Date::DATE_FORMATS[:medium]) + end + content = content_tag(:span, class: css_class) do - format(s_("Todos|Due %{due_date}"), due_date: if is_due_today - _("today") - else - l(todo.target.due_date, - format: Date::DATE_FORMATS[:medium]) - end) + format(s_("Todos|Due %{due_date}"), due_date: due_date) end "#{content} ·".html_safe diff --git a/app/helpers/users/group_callouts_helper.rb b/app/helpers/users/group_callouts_helper.rb index 0aa4eb89499..92cf41400e7 100644 --- a/app/helpers/users/group_callouts_helper.rb +++ b/app/helpers/users/group_callouts_helper.rb @@ -17,9 +17,11 @@ module Users def user_dismissed_for_group(feature_name, group, ignore_dismissal_earlier_than = nil) return false unless current_user - current_user.dismissed_callout_for_group?(feature_name: feature_name, - group: group, - ignore_dismissal_earlier_than: ignore_dismissal_earlier_than) + current_user.dismissed_callout_for_group?( + feature_name: feature_name, + group: group, + ignore_dismissal_earlier_than: ignore_dismissal_earlier_than + ) end def just_created? diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 4c8765618d0..e0cf7aa61ee 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -16,9 +16,7 @@ module UsersHelper end def user_link(user) - link_to(user.name, user_path(user), - title: user.email, - class: 'has-tooltip commit-committer-link') + link_to(user.name, user_path(user), title: user.email, class: 'has-tooltip commit-committer-link') end def user_email_help_text(user) @@ -86,9 +84,9 @@ module UsersHelper return unless user.status content_tag :span, - class: 'user-status-emoji has-tooltip', - title: user.status.message_html, - data: { html: true, placement: 'top' } do + class: 'user-status-emoji has-tooltip', + title: user.status.message_html, + data: { html: true, placement: 'top' } do emoji_icon user.status.emoji end end diff --git a/app/helpers/visibility_level_helper.rb b/app/helpers/visibility_level_helper.rb index 5ed341ee5e5..c577e2da1bb 100644 --- a/app/helpers/visibility_level_helper.rb +++ b/app/helpers/visibility_level_helper.rb @@ -44,9 +44,8 @@ module VisibilityLevelHelper Gitlab::CurrentSettings.restricted_visibility_levels || [] end - delegate :default_project_visibility, - :default_group_visibility, - to: :'Gitlab::CurrentSettings.current_application_settings' + delegate :default_project_visibility, :default_group_visibility, + to: :'Gitlab::CurrentSettings.current_application_settings' def disallowed_visibility_level?(form_model, level) return false unless form_model.respond_to?(:visibility_level_allowed?) diff --git a/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml b/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml deleted file mode 100644 index 25e193aa590..00000000000 --- a/config/feature_flags/development/enforce_max_attachment_size_upload_api.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: enforce_max_attachment_size_upload_api -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57250 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325787 -milestone: '13.11' -type: development -group: group::source code -default_enabled: true diff --git a/config/webpack.config.js b/config/webpack.config.js index 426fd50b98b..ac0c3ea7201 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -331,8 +331,21 @@ module.exports = { test: /\.(js|cjs)$/, exclude: (modulePath) => /node_modules|vendor[\\/]assets/.test(modulePath) && !/\.vue\.js/.test(modulePath), - loader: 'babel-loader', - options: defaultJsOptions, + use: [ + { + loader: 'thread-loader', + options: { + workerParallelJobs: 20, + poolRespawn: false, + poolParallelJobs: 200, + poolTimeout: DEV_SERVER_LIVERELOAD ? Infinity : 5000, + }, + }, + { + loader: 'babel-loader', + options: defaultJsOptions, + }, + ], }, WEBPACK_USE_ESBUILD_LOADER && { test: /\.(js|cjs)$/, diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md index ff0b8ecf178..c4e2c352e9b 100644 --- a/doc/administration/uploads.md +++ b/doc/administration/uploads.md @@ -8,6 +8,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w Uploads represent all user data that may be sent to GitLab as a single file. For example, avatars and note attachments are uploads. Uploads are integral to GitLab functionality and therefore cannot be disabled. +NOTE: +Attachments added to comments or descriptions are deleted **only** when the parent project or group +is deleted. Attachments remain in file storage even when the comment or resource (like issue, merge +request, epic) where they were uploaded is deleted. + ## Using local storage This is the default configuration. To change the location where the uploads are diff --git a/doc/api/projects.md b/doc/api/projects.md index c8755e020a7..24d06caf84b 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -2245,9 +2245,12 @@ POST /projects/:id/restore ## Upload a file +> - Maximum attachment size enforcement [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57250) in GitLab 13.11 [with a flag](../administration/feature_flags.md) named `enforce_max_attachment_size_upload_api`. Disabled by default. +> - Maximum attachment size [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62542) in GitLab 13.11. +> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/112450) in GitLab 15.10. Feature flag `enforce_max_attachment_size_upload_api` removed. + Uploads a file to the specified project to be used in an issue or merge request -description, or a comment. GitLab versions 14.0 and later -[enforce](#max-attachment-size-enforcement) this limit. +description, or a comment. ```plaintext POST /projects/:id/uploads @@ -2283,42 +2286,6 @@ The returned `url` is relative to the project path. The returned `full_path` is the absolute path to the file. In Markdown contexts, the link is expanded when the format in `markdown` is used. -### Max attachment size enforcement - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57250) in GitLab 13.11. - -GitLab 13.11 added enforcement of the [maximum attachment size limit](../user/admin_area/settings/account_and_limit_settings.md#max-attachment-size) behind the `enforce_max_attachment_size_upload_api` feature flag. GitLab 14.0 enables this by default. -To disable this enforcement: - -**In Omnibus installations:** - -1. Enter the Rails console: - - ```shell - sudo gitlab-rails console - ``` - -1. Disable the feature flag: - - ```ruby - Feature.disable(:enforce_max_attachment_size_upload_api) - ``` - -**In installations from source:** - -1. Enter the Rails console: - - ```shell - cd /home/git/gitlab - sudo -u git -H bundle exec rails console -e production - ``` - -1. Disable the feature flag: - - ```ruby - Feature.disable(:enforce_max_attachment_size_upload_api) - ``` - ## Upload a project avatar Uploads an avatar to the specified project. diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md index a17d9cb090b..71931639b0b 100644 --- a/doc/user/analytics/value_streams_dashboard.md +++ b/doc/user/analytics/value_streams_dashboard.md @@ -51,7 +51,7 @@ that are the largest value contributors, overperforming, or underperforming. You can also drill down the metrics for further analysis. When you hover over a metric, a tooltip displays an explanation of the metric and a link to the related documentation page. -## Customize the dashboard widgets +## Customize the dashboard panels You can customize the Value Streams Dashboard and configure what subgroups and projects to include in the page. @@ -59,7 +59,7 @@ A view can display maximum four subgroups or projects. To display multiple subgroups and projects, specify their path as a URL parameter. -For example, the parameter `query=gitlab-org/gitlab-foss,gitlab-org/gitlab,gitlab-org/gitlab-design,gitlab-org/gitlab-docs` displays three separate widgets, one each for the: +For example, the parameter `query=gitlab-org/gitlab-foss,gitlab-org/gitlab,gitlab-org/gitlab-design,gitlab-org/gitlab-docs` displays three separate panels, one each for the: - `gitlab-org` group - `gitlab-ui` project diff --git a/doc/user/clusters/agent/gitops/flux_tutorial.md b/doc/user/clusters/agent/gitops/flux_tutorial.md index 3c30e466110..b3ef9d174d9 100644 --- a/doc/user/clusters/agent/gitops/flux_tutorial.md +++ b/doc/user/clusters/agent/gitops/flux_tutorial.md @@ -64,31 +64,31 @@ Next, create a repository for your Kubernetes manifests: 1. In GitLab, create a new repository called `web-app-manifests`. 1. Add a file to `web-app-manifests` named `nginx-deployment.yaml` with the following contents: -```yaml -apiVersion: apps/v1 + ```yaml + apiVersion: apps/v1 -kind: Deployment + kind: Deployment -metadata: - name: nginx-deployment - labels: - app: nginx -spec: - replicas: 3 - selector: - matchLabels: - app: nginx - template: - metadata: - labels: - app: nginx - spec: - containers: - - name: nginx - image: nginx:1.14.2 - ports: - - containerPort: 80 -``` + metadata: + name: nginx-deployment + labels: + app: nginx + spec: + replicas: 3 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 + ``` 1. In the new repository, [create a deploy token](../../../project/deploy_tokens/index.md#create-a-deploy-token) with only the **read_repository** scope. 1. Store your deploy token username and password somewhere safe. diff --git a/doc/user/img/observability_copy_shortened_link.png b/doc/user/img/observability_copy_shortened_link.png new file mode 100644 index 00000000000..217e56972cc Binary files /dev/null and b/doc/user/img/observability_copy_shortened_link.png differ diff --git a/doc/user/markdown.md b/doc/user/markdown.md index 057e080dff0..00eec78e896 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -673,11 +673,23 @@ For example, a reference like `#123+s` is rendered as URL references like `https://gitlab.com/gitlab-org/gitlab/-/issues/1234+s` are also expanded. -### Embedding metrics in GitLab Flavored Markdown +### Embedding metrics Metric charts can be embedded in GitLab Flavored Markdown. Read [Embedding Metrics in GitLab flavored Markdown](../operations/metrics/embed.md) for more details. +### Embedding Observability dashboards + +You can embed GitLab Observability UI dashboards descriptions and comments, for example in epics, issues, and MRs. + +To embed an Observability dashboard URL: + +1. In GitLab Observability UI, in the upper-right corner, select **Copy shortened link**. + + ![Generate and copy Observability shortened link](img/observability_copy_shortened_link.png) + +1. Paste your link wherever you want to embed your dashboard. GitLab Flavored Markdown recognizes the URL and displays the source. + ## Features extended from standard Markdown All standard Markdown formatting should work as expected in GitLab. Some standard diff --git a/lib/api/projects.rb b/lib/api/projects.rb index b39444f642f..c32f61c6704 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -80,9 +80,8 @@ module API # Temporarily introduced for upload API: https://gitlab.com/gitlab-org/gitlab/-/issues/325788 def project_attachment_size(user_project) return PROJECT_ATTACHMENT_SIZE_EXEMPT if exempt_from_global_attachment_size?(user_project) - return user_project.max_attachment_size if Feature.enabled?(:enforce_max_attachment_size_upload_api, user_project) - PROJECT_ATTACHMENT_SIZE_EXEMPT + user_project.max_attachment_size end # This is to help determine which projects to use in https://gitlab.com/gitlab-org/gitlab/-/issues/325788 diff --git a/lib/tasks/gitlab/docs/redirect.rake b/lib/tasks/gitlab/docs/redirect.rake index 2d234fcdb36..35e0d083210 100644 --- a/lib/tasks/gitlab/docs/redirect.rake +++ b/lib/tasks/gitlab/docs/redirect.rake @@ -1,12 +1,13 @@ # frozen_string_literal: true -require 'date' -require 'pathname' -require "yaml" # # https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page # namespace :gitlab do + require 'date' + require 'pathname' + require 'yaml' + namespace :docs do desc 'GitLab | Docs | Create a doc redirect' task :redirect, [:old_path, :new_path] do |_, args| diff --git a/lib/tasks/gitlab/graphql.rake b/lib/tasks/gitlab/graphql.rake index a05b749a60e..f54579bd939 100644 --- a/lib/tasks/gitlab/graphql.rake +++ b/lib/tasks/gitlab/graphql.rake @@ -2,10 +2,10 @@ return if Rails.env.production? -require 'graphql/rake_task' -require_relative '../../../tooling/graphql/docs/renderer' - namespace :gitlab do + require 'graphql/rake_task' + require_relative '../../../tooling/graphql/docs/renderer' + OUTPUT_DIR = Rails.root.join("doc/api/graphql/reference") TEMP_SCHEMA_DIR = Rails.root.join('tmp/tests/graphql') TEMPLATES_DIR = 'tooling/graphql/docs/templates/' diff --git a/lib/tasks/gitlab/lfs/migrate.rake b/lib/tasks/gitlab/lfs/migrate.rake index 47f9e1dfb32..19de45dca17 100644 --- a/lib/tasks/gitlab/lfs/migrate.rake +++ b/lib/tasks/gitlab/lfs/migrate.rake @@ -1,9 +1,9 @@ # frozen_string_literal: true -require 'logger' - desc "GitLab | LFS | Migrate LFS objects to remote storage" namespace :gitlab do + require 'logger' + namespace :lfs do task migrate: :environment do logger = Logger.new($stdout) diff --git a/lib/tasks/gitlab/metrics_exporter.rake b/lib/tasks/gitlab/metrics_exporter.rake index d9dd80b8eeb..70719648fc5 100644 --- a/lib/tasks/gitlab/metrics_exporter.rake +++ b/lib/tasks/gitlab/metrics_exporter.rake @@ -1,8 +1,9 @@ # frozen_string_literal: true -require_relative Rails.root.join('metrics_server', 'dependencies') -require_relative Rails.root.join('metrics_server', 'metrics_server') namespace :gitlab do + require_relative Rails.root.join('metrics_server', 'dependencies') + require_relative Rails.root.join('metrics_server', 'metrics_server') + namespace :metrics_exporter do REPO = 'https://gitlab.com/gitlab-org/gitlab-metrics-exporter.git' diff --git a/lib/tasks/gitlab/openapi.rake b/lib/tasks/gitlab/openapi.rake index dee365de11c..c9aec6a112a 100644 --- a/lib/tasks/gitlab/openapi.rake +++ b/lib/tasks/gitlab/openapi.rake @@ -1,13 +1,13 @@ # frozen_string_literal: true -require 'logger' - if Rails.env.development? require 'grape-swagger/rake/oapi_tasks' GrapeSwagger::Rake::OapiTasks.new('::API::API') end namespace :gitlab do + require 'logger' + namespace :openapi do task :validate do raise 'This task can only be run in the development environment' unless Rails.env.development? diff --git a/locale/gitlab.pot b/locale/gitlab.pot index ff18f75eafe..26759e42d64 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -15961,6 +15961,9 @@ msgstr "" msgid "Enter Admin Mode" msgstr "" +msgid "Enter a name for your saved reply" +msgstr "" + msgid "Enter a number" msgstr "" diff --git a/package.json b/package.json index c4d738429d3..dc30f13cfc4 100644 --- a/package.json +++ b/package.json @@ -178,6 +178,7 @@ "string-hash": "1.1.3", "style-loader": "^2.0.0", "swagger-ui-dist": "4.12.0", + "thread-loader": "^3.0.4", "three": "^0.143.0", "timeago.js": "^4.0.2", "tippy.js": "^6.3.7", diff --git a/qa/qa/runtime/allure_report.rb b/qa/qa/runtime/allure_report.rb index f92bdf74695..e726f7a316f 100644 --- a/qa/qa/runtime/allure_report.rb +++ b/qa/qa/runtime/allure_report.rb @@ -25,9 +25,6 @@ module QA # # @return [void] def configure_allure - # Match job names like ee:relative, ce:update etc. and set as execution environment - env_matcher = /^(?\w{2}:\S+)/ - AllureRspec.configure do |config| config.results_directory = ENV['QA_ALLURE_RESULTS_DIRECTORY'] || 'tmp/allure-results' config.clean_results_directory = true @@ -38,11 +35,11 @@ module QA config.issue_tag = :issue config.link_issue_pattern = '{}' - config.environment_properties = environment_info if Env.running_in_ci? - - # Set custom environment name to separate same specs executed on different environments - if Env.running_in_ci? && Env.ci_job_name.match?(env_matcher) - config.environment = Env.ci_job_name.match(env_matcher).named_captures['env'] + if Env.running_in_ci? + config.environment_properties = environment_info + # Set custom environment name to separate same specs executed in different jobs + # Drop number postfixes from parallel jobs by only matching non whitespace characters + config.environment = Env.ci_job_name.match(/^\S+/)[0] end end end diff --git a/scripts/generate-e2e-pipeline b/scripts/generate-e2e-pipeline index ab9c432f459..1d4ecf6619d 100755 --- a/scripts/generate-e2e-pipeline +++ b/scripts/generate-e2e-pipeline @@ -44,8 +44,6 @@ echo "$variables" >>"$REVIEW_PIPELINE_YML" cp .gitlab/ci/package-and-test/main.gitlab-ci.yml "$OMNIBUS_PIPELINE_YML" echo "$variables" >>"$OMNIBUS_PIPELINE_YML" -echo " ALLURE_JOB_NAME: e2e-package-and-test" >>"$OMNIBUS_PIPELINE_YML" -echo " QA_RUN_TYPE: e2e-package-and-test" >>"$OMNIBUS_PIPELINE_YML" echo "Successfully generated review-app and package-and-test pipeline with following variables section:" echo "$variables" diff --git a/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js b/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js index bec9e6947f3..60ace483712 100644 --- a/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js +++ b/spec/frontend/ci/pipeline_new/components/refs_dropdown_spec.js @@ -1,4 +1,4 @@ -import { GlListbox, GlListboxItem } from '@gitlab/ui'; +import { GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; @@ -19,7 +19,7 @@ describe('Pipeline New Form', () => { let wrapper; let mock; - const findDropdown = () => wrapper.findComponent(GlListbox); + const findDropdown = () => wrapper.findComponent(GlCollapsibleListbox); const findRefsDropdownItems = () => wrapper.findAllComponents(GlListboxItem); const findSearchBox = () => wrapper.findByTestId('listbox-search-input'); const findListboxGroups = () => wrapper.findAll('ul[role="group"]'); diff --git a/spec/frontend/issues/show/components/fields/type_spec.js b/spec/frontend/issues/show/components/fields/type_spec.js index cb1be142f75..e655cf3b37d 100644 --- a/spec/frontend/issues/show/components/fields/type_spec.js +++ b/spec/frontend/issues/show/components/fields/type_spec.js @@ -1,4 +1,4 @@ -import { GlFormGroup, GlListbox, GlIcon } from '@gitlab/ui'; +import { GlFormGroup, GlCollapsibleListbox, GlIcon } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; @@ -32,7 +32,7 @@ describe('Issue type field component', () => { }, }; - const findListBox = () => wrapper.findComponent(GlListbox); + const findListBox = () => wrapper.findComponent(GlCollapsibleListbox); const findFormGroup = () => wrapper.findComponent(GlFormGroup); const findAllIssueItems = () => wrapper.findAll('[data-testid="issue-type-list-item"]'); const findIssueItemAt = (at) => findAllIssueItems().at(at); diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js index 058fed302c9..51445942eaa 100644 --- a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js +++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js @@ -4,13 +4,13 @@ import Vue from 'vue'; import { last } from 'lodash'; import Vuex from 'vuex'; import stubChildren from 'helpers/stub_children'; +import { mockTracking, unmockTracking } from 'helpers/tracking_helper'; import PackagesList from '~/packages_and_registries/infrastructure_registry/list/components/packages_list.vue'; import PackagesListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue'; import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue'; import DeletePackageModal from '~/packages_and_registries/shared/components/delete_package_modal.vue'; import { TRACKING_ACTIONS } from '~/packages_and_registries/shared/constants'; import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registry/shared/constants'; -import Tracking from '~/tracking'; import { packageList } from '../../mock_data'; Vue.use(Vuex); @@ -174,23 +174,23 @@ describe('packages_list', () => { }); describe('tracking', () => { - let eventSpy; + let trackingSpy = null; beforeEach(() => { mountComponent(); - eventSpy = jest.spyOn(Tracking, 'event'); - // setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details - // eslint-disable-next-line no-restricted-syntax - wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } }); + trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); }); - it('deleteItemConfirmation calls event', () => { - wrapper.vm.deleteItemConfirmation(); - expect(eventSpy).toHaveBeenCalledWith( - TRACK_CATEGORY, - TRACKING_ACTIONS.DELETE_PACKAGE, - expect.any(Object), - ); + afterEach(() => { + unmockTracking(); + }); + + it('deleteItemConfirmation calls event', async () => { + await findPackageListDeleteModal().vm.$emit('ok'); + + expect(trackingSpy).toHaveBeenCalledWith(TRACK_CATEGORY, TRACKING_ACTIONS.DELETE_PACKAGE, { + category: TRACK_CATEGORY, + }); }); }); }); diff --git a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js index 75a9770d5dd..60bb055b1db 100644 --- a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js @@ -4,14 +4,13 @@ import VueApollo from 'vue-apollo'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; +import { WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants'; import ListPage from '~/packages_and_registries/package_registry/pages/list.vue'; import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue'; import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue'; import OriginalPackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue'; import DeletePackages from '~/packages_and_registries/package_registry/components/functional/delete_packages.vue'; import { - PROJECT_RESOURCE_TYPE, - GROUP_RESOURCE_TYPE, GRAPHQL_PAGE_SIZE, EMPTY_LIST_HELP_URL, PACKAGE_HELP_URL, @@ -167,14 +166,14 @@ describe('PackagesListApp', () => { }); describe.each` - type | sortType - ${PROJECT_RESOURCE_TYPE} | ${'sort'} - ${GROUP_RESOURCE_TYPE} | ${'groupSort'} + type | sortType + ${WORKSPACE_PROJECT} | ${'sort'} + ${WORKSPACE_GROUP} | ${'groupSort'} `('$type query', ({ type, sortType }) => { let provide; let resolver; - const isGroupPage = type === GROUP_RESOURCE_TYPE; + const isGroupPage = type === WORKSPACE_GROUP; beforeEach(() => { provide = { ...defaultProvide, isGroupPage }; diff --git a/spec/frontend/pages/projects/graphs/code_coverage_spec.js b/spec/frontend/pages/projects/graphs/code_coverage_spec.js index ecf88dbed08..882730d90ae 100644 --- a/spec/frontend/pages/projects/graphs/code_coverage_spec.js +++ b/spec/frontend/pages/projects/graphs/code_coverage_spec.js @@ -1,4 +1,4 @@ -import { GlAlert, GlListbox, GlListboxItem } from '@gitlab/ui'; +import { GlAlert, GlCollapsibleListbox, GlListboxItem } from '@gitlab/ui'; import { GlAreaChart } from '@gitlab/ui/dist/charts'; import { shallowMount } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; @@ -22,7 +22,7 @@ describe('Code Coverage', () => { const findAlert = () => wrapper.findComponent(GlAlert); const findAreaChart = () => wrapper.findComponent(GlAreaChart); - const findListBox = () => wrapper.findComponent(GlListbox); + const findListBox = () => wrapper.findComponent(GlCollapsibleListbox); const findListBoxItems = () => wrapper.findAllComponents(GlListboxItem); const findFirstListBoxItem = () => findListBoxItems().at(0); const findSecondListBoxItem = () => findListBoxItems().at(1); @@ -37,7 +37,7 @@ describe('Code Coverage', () => { graphRef, graphCsvPath, }, - stubs: { GlListbox }, + stubs: { GlCollapsibleListbox }, }); }; diff --git a/spec/frontend/pipelines/nav_controls_spec.js b/spec/frontend/pipelines/nav_controls_spec.js index f789df74f92..15de7dc51f1 100644 --- a/spec/frontend/pipelines/nav_controls_spec.js +++ b/spec/frontend/pipelines/nav_controls_spec.js @@ -1,19 +1,20 @@ -import { shallowMount } from '@vue/test-utils'; -import { nextTick } from 'vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import NavControls from '~/pipelines/components/pipelines_list/nav_controls.vue'; describe('Pipelines Nav Controls', () => { let wrapper; const createComponent = (props) => { - wrapper = shallowMount(NavControls, { + wrapper = shallowMountExtended(NavControls, { propsData: { ...props, }, }); }; - const findRunPipeline = () => wrapper.find('.js-run-pipeline'); + const findRunPipelineButton = () => wrapper.findByTestId('run-pipeline-button'); + const findCiLintButton = () => wrapper.findByTestId('ci-lint-button'); + const findClearCacheButton = () => wrapper.findByTestId('clear-cache-button'); it('should render link to create a new pipeline', () => { const mockData = { @@ -24,9 +25,9 @@ describe('Pipelines Nav Controls', () => { createComponent(mockData); - const runPipeline = findRunPipeline(); - expect(runPipeline.text()).toContain('Run pipeline'); - expect(runPipeline.attributes('href')).toBe(mockData.newPipelinePath); + const runPipelineButton = findRunPipelineButton(); + expect(runPipelineButton.text()).toContain('Run pipeline'); + expect(runPipelineButton.attributes('href')).toBe(mockData.newPipelinePath); }); it('should not render link to create pipeline if no path is provided', () => { @@ -38,7 +39,7 @@ describe('Pipelines Nav Controls', () => { createComponent(mockData); - expect(findRunPipeline().exists()).toBe(false); + expect(findRunPipelineButton().exists()).toBe(false); }); it('should render link for CI lint', () => { @@ -50,9 +51,10 @@ describe('Pipelines Nav Controls', () => { }; createComponent(mockData); + const ciLintButton = findCiLintButton(); - expect(wrapper.find('.js-ci-lint').text().trim()).toContain('CI lint'); - expect(wrapper.find('.js-ci-lint').attributes('href')).toBe(mockData.ciLintPath); + expect(ciLintButton.text()).toContain('CI lint'); + expect(ciLintButton.attributes('href')).toBe(mockData.ciLintPath); }); describe('Reset Runners Cache', () => { @@ -66,16 +68,13 @@ describe('Pipelines Nav Controls', () => { }); it('should render button for resetting runner caches', () => { - expect(wrapper.find('.js-clear-cache').text().trim()).toContain('Clear runner caches'); + expect(findClearCacheButton().text()).toContain('Clear runner caches'); }); - it('should emit postAction event when reset runner cache button is clicked', async () => { - jest.spyOn(wrapper.vm, '$emit').mockImplementation(() => {}); + it('should emit postAction event when reset runner cache button is clicked', () => { + findClearCacheButton().vm.$emit('click'); - wrapper.find('.js-clear-cache').vm.$emit('click'); - await nextTick(); - - expect(wrapper.vm.$emit).toHaveBeenCalledWith('resetRunnersCache', 'foo'); + expect(wrapper.emitted('resetRunnersCache')).toEqual([['foo']]); }); }); }); diff --git a/spec/frontend/token_access/token_projects_table_spec.js b/spec/frontend/token_access/token_projects_table_spec.js index b51d8b3ccea..7654aa09b0a 100644 --- a/spec/frontend/token_access/token_projects_table_spec.js +++ b/spec/frontend/token_access/token_projects_table_spec.js @@ -6,14 +6,19 @@ import { mockProjects, mockFields } from './mock_data'; describe('Token projects table', () => { let wrapper; - const createComponent = () => { + const defaultProps = { + tableFields: mockFields, + projects: mockProjects, + }; + + const createComponent = (props) => { wrapper = mountExtended(TokenProjectsTable, { provide: { fullPath: 'root/ci-project', }, propsData: { - tableFields: mockFields, - projects: mockProjects, + ...defaultProps, + ...props, }, }); }; @@ -25,31 +30,52 @@ describe('Token projects table', () => { const findProjectNameCell = () => wrapper.findByTestId('token-access-project-name'); const findProjectNamespaceCell = () => wrapper.findByTestId('token-access-project-namespace'); - beforeEach(() => { - createComponent(); - }); - it('displays a table', () => { + createComponent(); + expect(findTable().exists()).toBe(true); }); it('displays the correct amount of table rows', () => { + createComponent(); + expect(findAllTableRows()).toHaveLength(mockProjects.length); }); it('delete project button emits event with correct project to delete', async () => { + createComponent(); + await findDeleteProjectBtn().trigger('click'); expect(wrapper.emitted('removeProject')).toEqual([[mockProjects[0].fullPath]]); }); it('does not show the remove icon if the project is locked', () => { + createComponent(); + // currently two mock projects with one being a locked project expect(findAllDeleteProjectBtn()).toHaveLength(1); }); it('displays project and namespace cells', () => { + createComponent(); + expect(findProjectNameCell().text()).toBe('merge-train-stuff'); expect(findProjectNamespaceCell().text()).toBe('root'); }); + + it('displays empty string for namespace when namespace is null', () => { + const nullNamespace = { + id: '1', + name: 'merge-train-stuff', + namespace: null, + fullPath: 'root/merge-train-stuff', + isLocked: false, + __typename: 'Project', + }; + + createComponent({ projects: [nullNamespace] }); + + expect(findProjectNamespaceCell().text()).toBe(''); + }); }); diff --git a/spec/frontend/vue_shared/components/listbox_input/listbox_input_spec.js b/spec/frontend/vue_shared/components/listbox_input/listbox_input_spec.js index 7ed6a59c844..4e83f3e1c06 100644 --- a/spec/frontend/vue_shared/components/listbox_input/listbox_input_spec.js +++ b/spec/frontend/vue_shared/components/listbox_input/listbox_input_spec.js @@ -1,5 +1,5 @@ import { shallowMount } from '@vue/test-utils'; -import { GlFormGroup, GlListbox } from '@gitlab/ui'; +import { GlFormGroup, GlCollapsibleListbox } from '@gitlab/ui'; import ListboxInput from '~/vue_shared/components/listbox_input/listbox_input.vue'; describe('ListboxInput', () => { @@ -27,7 +27,7 @@ describe('ListboxInput', () => { // Finders const findGlFormGroup = () => wrapper.findComponent(GlFormGroup); - const findGlListbox = () => wrapper.findComponent(GlListbox); + const findGlListbox = () => wrapper.findComponent(GlCollapsibleListbox); const findInput = () => wrapper.find('input'); const createComponent = (propsData) => { @@ -153,7 +153,7 @@ describe('ListboxInput', () => { expect(findGlListbox().props('searchable')).toBe(true); }); - it('passes all items to GlListbox by default', () => { + it('passes all items to GlCollapsibleListbox by default', () => { createComponent(); expect(findGlListbox().props('items')).toStrictEqual(items); diff --git a/spec/frontend/vue_shared/plugins/global_toast_spec.js b/spec/frontend/vue_shared/plugins/global_toast_spec.js index 322586a772c..0bf2737fb2b 100644 --- a/spec/frontend/vue_shared/plugins/global_toast_spec.js +++ b/spec/frontend/vue_shared/plugins/global_toast_spec.js @@ -1,14 +1,16 @@ -import toast, { instance } from '~/vue_shared/plugins/global_toast'; +import toast from '~/vue_shared/plugins/global_toast'; + +const mockSpy = jest.fn(); +jest.mock('@gitlab/ui', () => ({ + GlToast: (Vue) => { + // eslint-disable-next-line no-param-reassign + Vue.prototype.$toast = { show: (...args) => mockSpy(...args) }; + }, +})); describe('Global toast', () => { - let spyFunc; - - beforeEach(() => { - spyFunc = jest.spyOn(instance.$toast, 'show').mockImplementation(() => {}); - }); - afterEach(() => { - spyFunc.mockRestore(); + mockSpy.mockRestore(); }); it("should call GitLab UI's toast method", () => { @@ -17,7 +19,7 @@ describe('Global toast', () => { toast(arg1, arg2); - expect(instance.$toast.show).toHaveBeenCalledTimes(1); - expect(instance.$toast.show).toHaveBeenCalledWith(arg1, arg2); + expect(mockSpy).toHaveBeenCalledTimes(1); + expect(mockSpy).toHaveBeenCalledWith(arg1, arg2); }); }); diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 615fe08f5a2..d755a4231da 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -2066,19 +2066,6 @@ RSpec.describe API::Projects, feature_category: :projects do end end - context 'with upload size enforcement disabled' do - before do - stub_feature_flags(enforce_max_attachment_size_upload_api: false) - end - - it "returns 200" do - post api("/projects/#{project.id}/uploads/authorize", user), headers: headers - - expect(response).to have_gitlab_http_status(:ok) - expect(json_response['MaximumSize']).to eq(1.gigabyte) - end - end - context 'with no Workhorse headers' do it "returns 403" do post api("/projects/#{project.id}/uploads/authorize", user) @@ -2155,14 +2142,6 @@ RSpec.describe API::Projects, feature_category: :projects do it_behaves_like 'capped upload attachments', true end - - context 'with upload size enforcement disabled' do - before do - stub_feature_flags(enforce_max_attachment_size_upload_api: false) - end - - it_behaves_like 'capped upload attachments', false - end end describe "GET /projects/:id/groups" do diff --git a/vendor/gems/cloud_profiler_agent/cloud_profiler_agent.gemspec b/vendor/gems/cloud_profiler_agent/cloud_profiler_agent.gemspec index cf84c100fc3..82e5041491d 100644 --- a/vendor/gems/cloud_profiler_agent/cloud_profiler_agent.gemspec +++ b/vendor/gems/cloud_profiler_agent/cloud_profiler_agent.gemspec @@ -13,8 +13,6 @@ Gem::Specification.new do |spec| spec.homepage = 'https://github.com/remind101/ruby-cloud-profiler' spec.license = 'BSD-2-Clause' - spec.required_ruby_version = '>= 3.0.0' - spec.files = ['lib/profile_pb.rb', 'lib/cloud_profiler_agent.rb', 'lib/cloud_profiler_agent/agent.rb', diff --git a/yarn.lock b/yarn.lock index b02d803a9a3..51b1723bd28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8158,6 +8158,11 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== +loader-runner@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" @@ -9378,7 +9383,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.5.0, neo-async@^2.6.1: +neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -11808,6 +11813,17 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +thread-loader@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/thread-loader/-/thread-loader-3.0.4.tgz#c392e4c0241fbc80430eb680e4886819b504a31b" + integrity sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA== + dependencies: + json-parse-better-errors "^1.0.2" + loader-runner "^4.1.0" + loader-utils "^2.0.0" + neo-async "^2.6.2" + schema-utils "^3.0.0" + three@^0.143.0: version "0.143.0" resolved "https://registry.yarnpkg.com/three/-/three-0.143.0.tgz#1455bca132cc2b20beb7f41d313e10c29e5ed9df"