diff options
83 files changed, 805 insertions, 587 deletions
diff --git a/.gitattributes b/.gitattributes index 720e5f62549..1f5d554ef25 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,4 @@ VERSION merge=ours Dangerfile gitlab-language=ruby -*.pdf filter=lfs diff=lfs merge=lfs -text *.rb diff=ruby workhorse/testdata/*.pdf -filter -diff -merge diff --git a/.gitlab/ci/caching.gitlab-ci.yml b/.gitlab/ci/caching.gitlab-ci.yml new file mode 100644 index 00000000000..c7b8d49e9d1 --- /dev/null +++ b/.gitlab/ci/caching.gitlab-ci.yml @@ -0,0 +1,55 @@ +cache-workhorse: + extends: + - .default-retry + - .default-before_script + - .rails-cache + - .setup-test-env-cache + - .caching:rules:cache-workhorse + stage: prepare + variables: + SETUP_DB: "false" + script: + - source scripts/gitlab_component_helpers.sh + - 'gitlab_workhorse_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }' + - run_timed_command "scripts/setup-test-env" + - run_timed_command "select_gitlab_workhorse_essentials" + - run_timed_command "create_gitlab_workhorse_package" + - run_timed_command "upload_gitlab_workhorse_package" + artifacts: + expire_in: 7d + paths: + - ${TMP_TEST_GITLAB_WORKHORSE_PATH}/ + +.cache-assets-base: + extends: + - .compile-assets-base + - .caching:rules:cache-assets + stage: prepare + variables: + WEBPACK_REPORT: "false" + script: + - !reference [.yarn-install, script] + - export GITLAB_ASSETS_HASH=$(bundle exec rake gitlab:assets:hash_sum | tee assets-hash.txt) + - source scripts/gitlab_component_helpers.sh + - 'gitlab_assets_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }' + # If we still use the legacy cache, we don't want to create a package from it as we don't check the sha sum in gitlab:assets:compile_with_new_strategy. + # This line can be removed once we stop downloading the legacy cache. + - rm -rf public/assets + - run_timed_command "bin/rake gitlab:assets:compile_with_new_strategy" + - run_timed_command "scripts/clean-old-cached-assets" + - run_timed_command "create_gitlab_assets_package" + - run_timed_command "upload_gitlab_assets_package" + +cache-assets:test: + extends: .cache-assets-base + +cache-assets:test as-if-foss: + extends: + - .cache-assets-base + - .as-if-foss + +cache-assets:production: + extends: .cache-assets-base + variables: + NODE_ENV: "production" + RAILS_ENV: "production" diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index 3bd65b565e4..fc2bf5540e4 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -1,10 +1,12 @@ -.yarn-install: &yarn-install - - source scripts/utils.sh - - run_timed_command "retry yarn install --frozen-lockfile" +.yarn-install: + script: + - source scripts/utils.sh + - run_timed_command "retry yarn install --frozen-lockfile" -.storybook-yarn-install: &storybook-yarn-install - - source scripts/utils.sh - - run_timed_command "retry yarn run storybook:install --frozen-lockfile" +.storybook-yarn-install: + script: + - source scripts/utils.sh + - run_timed_command "retry yarn run storybook:install --frozen-lockfile" .compile-assets-base: extends: @@ -21,8 +23,17 @@ WEBPACK_COMPILE_LOG_PATH: "tmp/webpack-output.log" stage: prepare script: - - *yarn-install - - run_timed_command "bin/rake gitlab:assets:compile" + - !reference [.yarn-install, script] + - | + # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable + if [[ "${CACHE_ASSETS_AS_PACKAGE}" == "true" ]]; then + export GITLAB_ASSETS_HASH=$(bundle exec rake gitlab:assets:hash_sum | tee assets-hash.txt) + source scripts/gitlab_component_helpers.sh + run_timed_command "download_and_extract_gitlab_assets" || true + run_timed_command "bin/rake gitlab:assets:compile_with_new_strategy" + else + run_timed_command "bin/rake gitlab:assets:compile" + fi - run_timed_command "scripts/clean-old-cached-assets" compile-production-assets: @@ -42,8 +53,6 @@ compile-production-assets: - public/assets/ - "${WEBPACK_COMPILE_LOG_PATH}" when: always - before_script: - - !reference [.default-before_script, before_script] after_script: - rm -f /etc/apt/sources.list.d/google*.list # We don't need to update Chrome here @@ -88,7 +97,7 @@ update-yarn-cache: - .shared:rules:update-cache stage: prepare script: - - *yarn-install + - !reference [.yarn-install, script] update-storybook-yarn-cache: extends: @@ -97,7 +106,7 @@ update-storybook-yarn-cache: - .shared:rules:update-cache stage: prepare script: - - *storybook-yarn-install + - !reference [.storybook-yarn-install, script] .frontend-fixtures-base: extends: @@ -180,7 +189,7 @@ graphql-schema-dump as-if-foss: SETUP_DB: "false" before_script: - !reference [.default-before_script, before_script] - - *yarn-install + - !reference [.yarn-install, script] stage: test .jest-base: @@ -256,7 +265,7 @@ coverage-frontend: optional: true stage: post-test before_script: - - *yarn-install + - !reference [.yarn-install, script] script: - run_timed_command "yarn node scripts/frontend/merge_coverage_frontend.js" # Removing the individual coverage results, as we just merged them. @@ -282,7 +291,7 @@ coverage-frontend: stage: test dependencies: [] script: - - *yarn-install + - !reference [.yarn-install, script] - run_timed_command "retry yarn run webpack-prod" qa-frontend-node:14: @@ -310,7 +319,7 @@ webpack-dev-server: WEBPACK_MEMORY_TEST: "true" WEBPACK_VENDOR_DLL: "true" script: - - *yarn-install + - !reference [.yarn-install, script] - run_timed_command "retry yarn webpack-vendor" - run_timed_command "node --expose-gc node_modules/.bin/webpack-dev-server --config config/webpack.config.js" artifacts: @@ -328,7 +337,7 @@ bundle-size-review: stage: test needs: [] script: - - *yarn-install + - !reference [.yarn-install, script] - scripts/bundle_size_review artifacts: when: always @@ -366,7 +375,7 @@ startup-css-check as-if-foss: - .frontend-test-base - .storybook-yarn-cache script: - - *storybook-yarn-install + - !reference [.storybook-yarn-install, script] - yarn run storybook:build needs: ["graphql-schema-dump"] diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index 7bdca62b68e..9418d2462d3 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -79,10 +79,12 @@ policy: push # We want to rebuild the cache from scratch to ensure stale dependencies are cleaned up. .assets-cache: &assets-cache - key: "assets-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v2" + key: "assets-debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_ENV}-v3" + # This list should match GITLAB_ASSETS_PATHS_LIST from scripts/gitlab_component_helpers.sh paths: - assets-hash.txt - - public/assets/webpack/ + - app/assets/javascripts/locale/**/app.js + - public/assets/ - tmp/cache/assets/sprockets/ - tmp/cache/babel-loader/ - tmp/cache/vue-loader/ diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml index b2ce4152918..be84cf904d7 100644 --- a/.gitlab/ci/rails.gitlab-ci.yml +++ b/.gitlab/ci/rails.gitlab-ci.yml @@ -168,7 +168,7 @@ setup-test-env: SETUP_DB: "false" script: - echo $CI_MERGE_REQUEST_APPROVED - - source scripts/gitlab_workhorse_component_helpers.sh + - source scripts/gitlab_component_helpers.sh - run_timed_command "download_and_extract_gitlab_workhorse_package" || true - run_timed_command "scripts/setup-test-env" - run_timed_command "select_gitlab_workhorse_essentials" @@ -197,22 +197,6 @@ setup-test-env: - ${TMP_TEST_GITLAB_WORKHORSE_PATH}/ when: always -build-components: - extends: - - setup-test-env - - .rails:rules:build-components - script: - - source scripts/gitlab_workhorse_component_helpers.sh - - 'gitlab_workhorse_archive_doesnt_exist || { echoinfo "INFO: Exiting early as package exists."; exit 0; }' - - run_timed_command "scripts/setup-test-env" - - run_timed_command "select_gitlab_workhorse_essentials" - - run_timed_command "create_gitlab_workhorse_package" - - run_timed_command "upload_gitlab_workhorse_package" - artifacts: - expire_in: 7d - paths: - - ${TMP_TEST_GITLAB_WORKHORSE_PATH}/ - update-setup-test-env-cache: extends: - setup-test-env diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 203aa779e5b..e2bf3e02eea 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -249,8 +249,21 @@ - "babel.config.js" - "config/webpack.config.js" - "config/**/*.js" + - "{,ee/,jh/}app/assets/**/*" - "vendor/assets/**/*" + +# This list should match the list in Tasks::Gitlab::Assets.assets_impacting_compilation +.assets-compilation-patterns: &assets-compilation-patterns + - "{package.json,yarn.lock}" + - ".browserslistrc" + - "babel.config.js" + - "config/webpack.config.js" + - "*.js" + - "config/**/*.js" + - "locale/**/gitlab.po" - "{,ee/,jh/}app/assets/**/*" + - "fixtures/emojis/**/*" + - "vendor/assets/**/*" .frontend-patterns-for-as-if-foss: &frontend-patterns-for-as-if-foss - "{package.json,yarn.lock}" @@ -652,6 +665,37 @@ - changes: *ci-build-images-patterns - changes: *code-qa-patterns +################# +# Caching rules # +################# +.caching:rules:cache-workhorse: + rules: + - <<: *if-dot-com-ee-schedule + - <<: *if-dot-com-gitlab-org-default-branch + changes: ["workhorse/**/*"] + - <<: *if-dot-com-gitlab-org-merge-request + changes: + - ".gitlab/ci/caching.gitlab-ci.yml" + - "scripts/gitlab_component_helpers.sh" + when: manual + allow_failure: true + +.caching:rules:cache-assets: + rules: + # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable + - if: '$CACHE_ASSETS_AS_PACKAGE != "true"' + when: never + - <<: *if-dot-com-ee-schedule + - <<: *if-dot-com-gitlab-org-default-branch + changes: *assets-compilation-patterns + - <<: *if-dot-com-gitlab-org-merge-request + changes: + - ".gitlab/ci/caching.gitlab-ci.yml" + - "scripts/gitlab_component_helpers.sh" + - "lib/tasks/gitlab/assets.rake" + when: manual + allow_failure: true + ###################### # CI Templates Rules # ###################### @@ -969,16 +1013,6 @@ ############### # Rails rules # ############### -.rails:rules:build-components: - rules: - - <<: *if-dot-com-ee-schedule - - <<: *if-dot-com-gitlab-org-default-branch - changes: - - "workhorse/**/*" - - <<: *if-dot-com-gitlab-org-merge-request - when: manual - allow_failure: true - .rails:rules:setup-test-env: rules: - changes: *setup-test-env-patterns diff --git a/.rubocop_todo/rails/helper_instance_variable.yml b/.rubocop_todo/rails/helper_instance_variable.yml index f43ca39f47c..8f9197c9223 100644 --- a/.rubocop_todo/rails/helper_instance_variable.yml +++ b/.rubocop_todo/rails/helper_instance_variable.yml @@ -1,8 +1,6 @@ --- Rails/HelperInstanceVariable: - # Offense count: 671 - # Temporarily disabled due to too many offenses - Enabled: false + Details: grace period Exclude: - 'app/helpers/admin/user_actions_helper.rb' - 'app/helpers/application_helper.rb' @@ -29,7 +27,6 @@ Rails/HelperInstanceVariable: - 'app/helpers/icons_helper.rb' - 'app/helpers/ide_helper.rb' - 'app/helpers/import_helper.rb' - - 'app/helpers/integrations_helper.rb' - 'app/helpers/issuables_description_templates_helper.rb' - 'app/helpers/issuables_helper.rb' - 'app/helpers/issues_helper.rb' @@ -40,6 +37,7 @@ Rails/HelperInstanceVariable: - 'app/helpers/nav_helper.rb' - 'app/helpers/notes_helper.rb' - 'app/helpers/operations_helper.rb' + - 'app/helpers/packages_helper.rb' - 'app/helpers/page_layout_helper.rb' - 'app/helpers/projects_helper.rb' - 'app/helpers/releases_helper.rb' @@ -59,11 +57,13 @@ Rails/HelperInstanceVariable: - 'app/helpers/webpack_helper.rb' - 'app/helpers/wiki_helper.rb' - 'ee/app/helpers/ee/application_helper.rb' + - 'ee/app/helpers/ee/application_settings_helper.rb' - 'ee/app/helpers/ee/boards_helper.rb' - 'ee/app/helpers/ee/feature_flags_helper.rb' - 'ee/app/helpers/ee/form_helper.rb' - 'ee/app/helpers/ee/graph_helper.rb' - 'ee/app/helpers/ee/groups/group_members_helper.rb' + - 'ee/app/helpers/ee/groups/settings_helper.rb' - 'ee/app/helpers/ee/groups_helper.rb' - 'ee/app/helpers/ee/integrations_helper.rb' - 'ee/app/helpers/ee/kerberos_helper.rb' @@ -77,7 +77,8 @@ Rails/HelperInstanceVariable: - 'ee/app/helpers/ee/projects_helper.rb' - 'ee/app/helpers/ee/search_helper.rb' - 'ee/app/helpers/ee/selects_helper.rb' + - 'ee/app/helpers/ee/sorting_helper.rb' - 'ee/app/helpers/ee/subscribable_banner_helper.rb' - 'ee/app/helpers/ee/wiki_helper.rb' - 'ee/app/helpers/path_locks_helper.rb' - - 'ee/app/helpers/projects/security/discover_helper.rb' + - 'ee/app/helpers/seat_count_alert_helper.rb' diff --git a/.rubocop_todo/style/string_literals_in_interpolation.yml b/.rubocop_todo/style/string_literals_in_interpolation.yml index cded81afa7f..fc90e1ce6a6 100644 --- a/.rubocop_todo/style/string_literals_in_interpolation.yml +++ b/.rubocop_todo/style/string_literals_in_interpolation.yml @@ -1,9 +1,7 @@ --- # Cop supports --auto-correct. Style/StringLiteralsInInterpolation: - # Offense count: 119 - # Temporarily disabled due to too many offenses - Enabled: false + Details: grace period Exclude: - 'app/graphql/mutations/base_mutation.rb' - 'app/helpers/colors_helper.rb' @@ -23,11 +21,16 @@ Style/StringLiteralsInInterpolation: - 'ee/app/helpers/ee/merge_requests_helper.rb' - 'ee/app/models/license.rb' - 'ee/app/services/epics/tree_reorder_service.rb' + - 'ee/lib/ee/api/helpers/issues_helpers.rb' - 'ee/lib/gitlab/elastic/helper.rb' + - 'ee/lib/tasks/gitlab/elastic.rake' - 'ee/spec/features/admin/admin_settings_spec.rb' + - 'ee/spec/features/subscriptions/expiring_subscription_message_spec.rb' + - 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb' - 'lib/api/helpers/snippets_helpers.rb' - 'lib/api/validations/validators/check_assignees_count.rb' - 'lib/banzai/filter/references/abstract_reference_filter.rb' + - 'lib/banzai/filter/syntax_highlight_filter.rb' - 'lib/generators/gitlab/usage_metric_definition_generator.rb' - 'lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb' - 'lib/gitlab/ci/config/entry/job.rb' @@ -36,6 +39,7 @@ Style/StringLiteralsInInterpolation: - 'lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb' - 'lib/gitlab/doctor/secrets.rb' - 'lib/gitlab/endpoint_attributes/config.rb' + - 'lib/gitlab/gitaly_client/ref_service.rb' - 'lib/gitlab/graphql/queries.rb' - 'lib/gitlab/quick_actions/extractor.rb' - 'lib/gitlab/sanitizers/exif.rb' @@ -43,13 +47,11 @@ Style/StringLiteralsInInterpolation: - 'lib/gitlab/tracking/destinations/snowplow.rb' - 'lib/tasks/gitlab/info.rake' - 'lib/tasks/gitlab/sidekiq.rake' - - 'lib/tasks/gitlab/tw/codeowners.rake' - 'qa/qa/ee/page/component/secure_report.rb' - 'qa/qa/ee/page/group/secure/show.rb' - 'qa/qa/resource/events/base.rb' - 'qa/qa/service/cluster_provider/base.rb' - 'qa/qa/service/cluster_provider/gcloud.rb' - - 'qa/qa/service/docker_run/gitlab_runner.rb' - 'qa/qa/specs/helpers/context_selector.rb' - 'qa/qa/tools/generate_perf_testdata.rb' - 'rubocop/cop/migration/prevent_index_creation.rb' @@ -59,9 +61,12 @@ Style/StringLiteralsInInterpolation: - 'spec/finders/serverless_domain_finder_spec.rb' - 'spec/lib/banzai/filter/references/commit_reference_filter_spec.rb' - 'spec/lib/banzai/filter/references/issue_reference_filter_spec.rb' + - 'spec/lib/gitlab/background_migration/batched_migration_job_spec.rb' - 'spec/lib/gitlab/ci/parsers/security/validators/schema_validator_spec.rb' - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb' + - 'spec/lib/gitlab/gitaly_client/ref_service_spec.rb' - 'spec/lib/object_storage/direct_upload_spec.rb' - 'spec/models/serverless/domain_spec.rb' - 'spec/requests/api/keys_spec.rb' - 'spec/support/database/prevent_cross_joins.rb' + - 'spec/views/notify/import_issues_csv_email.html.haml_spec.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 3587341c8c0..207b5d92e1e 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -5ee7c55528f5833aec37ba4a6bfb2b4c3f64dc80 +2ff0039f15ef06063925ff6c0406f6e092ad2435 diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json index 3b9d87134fd..afdf6b9eee5 100644 --- a/app/assets/javascripts/editor/schema/ci.json +++ b/app/assets/javascripts/editor/schema/ci.json @@ -585,30 +585,30 @@ } }, "globalVariables": { - "markdownDescription": "Defines environment variables globally. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. You can use the value and description keywords to define variables that are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).", - "anyOf": [ - {"type": "object"}, - { - "type": "array", - "items": { - "type": "string" - } - } - ], - "additionalProperties": { - "anyOf": [ - {"type": ["string", "integer", "array"]}, - { - "type": "object", - "properties": { - "value": { "type": "string" }, - "description": { - "type": "string", - "description": "Explains what the variable is used for, what the acceptable values are." - } + "markdownDescription": "Defines default variables for all jobs. Job level property overrides global variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).", + "type": "object", + "patternProperties": { + ".*": { + "oneOf": [ + { + "type": ["string", "number"] + }, + { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "description": { + "type": "string", + "markdownDescription": "Explains what the variable is used for, what the acceptable values are. Variables with `description` are prefilled when running a pipeline manually. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variablesdescription)." + } + }, + "additionalProperties": false } - } - ] + ] + }, + "additionalProperties": false } }, "if": { @@ -652,21 +652,14 @@ } }, "variables": { - "markdownDescription": "Defines environment variables for specific jobs. Job level property overrides global variables. If a job sets `variables: {}`, all global variables are turned off. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#rulesvariables).", - "anyOf": [ - { - "type": "object", - "additionalProperties": { - "type": ["string", "integer", "array"] - } + "markdownDescription": "Defines environment variables. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#variables).", + "type": "object", + "patternProperties": { + ".*": { + "type": ["string", "number"] }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] + "additionalProperties": false + } }, "timeout": { "type": "string", diff --git a/app/assets/javascripts/issuable/issuable_context.js b/app/assets/javascripts/issuable/issuable_context.js index 37001d00a27..8c2e2a5df67 100644 --- a/app/assets/javascripts/issuable/issuable_context.js +++ b/app/assets/javascripts/issuable/issuable_context.js @@ -1,7 +1,6 @@ import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import $ from 'jquery'; import { setCookie } from '~/lib/utils/common_utils'; -import { loadCSSFile } from '~/lib/utils/css_utils'; import UsersSelect from '~/users_select'; export default class IssuableContext { @@ -9,24 +8,6 @@ export default class IssuableContext { this.userSelect = new UsersSelect(currentUser); this.reviewersSelect = new UsersSelect(currentUser, '.js-reviewer-search'); - const $select2 = $('select.select2'); - - if ($select2.length) { - import(/* webpackChunkName: 'select2' */ 'select2/select2') - .then(() => { - // eslint-disable-next-line promise/no-nesting - loadCSSFile(gon.select2_css_path) - .then(() => { - $select2.select2({ - width: 'resolve', - dropdownAutoWidth: true, - }); - }) - .catch(() => {}); - }) - .catch(() => {}); - } - $('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() { return $(this).submit(); }); diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index bf35d5c3b25..56f9e0d1c25 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -5,7 +5,7 @@ import $ from 'jquery'; import { mapActions, mapGetters, mapState } from 'vuex'; import Autosave from '~/autosave'; import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { badgeState } from '~/issuable/components/status_box.vue'; import httpStatusCodes from '~/lib/utils/http_status'; import { @@ -276,7 +276,7 @@ export default { .then(() => badgeState.updateStatus && badgeState.updateStatus()) .then(refreshUserMergeRequestCounts) .catch(() => - createFlash({ + createAlert({ message: constants.toggleStateErrorMessage[this.noteableType][this.openState], }), ); diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue index 9806f8e5dc2..6fdafe34d67 100644 --- a/app/assets/javascripts/notes/components/note_actions.vue +++ b/app/assets/javascripts/notes/components/note_actions.vue @@ -3,7 +3,7 @@ import { GlTooltipDirective, GlIcon, GlButton, GlDropdownItem } from '@gitlab/ui import { mapActions, mapGetters, mapState } from 'vuex'; import Api from '~/api'; import resolvedStatusMixin from '~/batch_comments/mixins/resolved_status'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { __, sprintf } from '~/locale'; import eventHub from '~/sidebar/event_hub'; @@ -238,7 +238,7 @@ export default { }) .then(() => this.handleAssigneeUpdate(assignees)) .catch(() => - createFlash({ + createAlert({ message: __('Something went wrong while updating assignees'), }), ); diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue index 835750cc137..9d59994788e 100644 --- a/app/assets/javascripts/notes/components/note_awards_list.vue +++ b/app/assets/javascripts/notes/components/note_awards_list.vue @@ -1,6 +1,6 @@ <script> import { mapActions, mapGetters } from 'vuex'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { __ } from '~/locale'; import AwardsList from '~/vue_shared/components/awards_list.vue'; @@ -49,7 +49,7 @@ export default { }; this.toggleAwardRequest(data).catch(() => - createFlash({ + createAlert({ message: __('Something went wrong on our end.'), }), ); diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index afa5e39d8b0..50d166b6db5 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -2,7 +2,7 @@ import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { mapActions, mapGetters } from 'vuex'; import DraftNote from '~/batch_comments/components/draft_note.vue'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { clearDraft, getDiscussionReplyKey } from '~/lib/utils/autosave'; import { isLoggedIn } from '~/lib/utils/common_utils'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; @@ -247,7 +247,7 @@ export default { const msg = __( 'Your comment could not be submitted! Please check your network connection and try again.', ); - createFlash({ + createAlert({ message: msg, parent: this.$el, }); diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue index 45714541f80..86aa87b9add 100644 --- a/app/assets/javascripts/notes/components/noteable_note.vue +++ b/app/assets/javascripts/notes/components/noteable_note.vue @@ -5,7 +5,7 @@ import { escape, isEmpty } from 'lodash'; import { mapGetters, mapActions } from 'vuex'; import { confirmAction } from '~/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal'; import { INLINE_DIFF_LINES_KEY } from '~/diffs/constants'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import httpStatusCodes from '~/lib/utils/http_status'; import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending'; import { truncateSha } from '~/lib/utils/text_utility'; @@ -270,7 +270,7 @@ export default { this.isDeleting = false; }) .catch(() => { - createFlash({ + createAlert({ message: __('Something went wrong while deleting your note. Please try again.'), }); this.isDeleting = false; @@ -349,7 +349,7 @@ export default { }, handleUpdateError() { const msg = __('Something went wrong while editing your comment. Please try again.'); - createFlash({ + createAlert({ message: msg, parent: this.$el, }); diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index db04d60e6f2..3e29e438063 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -1,7 +1,7 @@ <script> import { mapGetters, mapActions } from 'vuex'; import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { __ } from '~/locale'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import OrderedLayout from '~/vue_shared/components/ordered_layout.vue'; @@ -221,7 +221,7 @@ export default { .catch(() => { this.setLoadingState(false); this.setNotesFetchedState(true); - createFlash({ + createAlert({ message: __('Something went wrong while fetching comments. Please try again.'), }); }); diff --git a/app/assets/javascripts/notes/mixins/diff_line_note_form.js b/app/assets/javascripts/notes/mixins/diff_line_note_form.js index 7b9c0959464..9a140029c07 100644 --- a/app/assets/javascripts/notes/mixins/diff_line_note_form.js +++ b/app/assets/javascripts/notes/mixins/diff_line_note_form.js @@ -1,7 +1,7 @@ import { mapActions, mapGetters, mapState } from 'vuex'; import { getDraftReplyFormData, getDraftFormData } from '~/batch_comments/utils'; import { TEXT_DIFF_POSITION_TYPE, IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { clearDraft } from '~/lib/utils/autosave'; import { s__ } from '~/locale'; import { formatLineRange } from '~/notes/components/multiline_comment_utils'; @@ -42,7 +42,7 @@ export default { this.handleClearForm(this.discussion.line_code); }) .catch(() => { - createFlash({ + createAlert({ message: s__('MergeRequests|An error occurred while saving the draft comment.'), }); }); @@ -82,7 +82,7 @@ export default { } }) .catch(() => { - createFlash({ + createAlert({ message: s__('MergeRequests|An error occurred while saving the draft comment.'), }); }); diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js index 9783def1b46..44751020173 100644 --- a/app/assets/javascripts/notes/mixins/resolvable.js +++ b/app/assets/javascripts/notes/mixins/resolvable.js @@ -1,4 +1,4 @@ -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import { __ } from '~/locale'; export default { @@ -46,7 +46,7 @@ export default { this.isResolving = false; const msg = __('Something went wrong while resolving this discussion. Please try again.'); - createFlash({ + createAlert({ message: msg, parent: this.$el, }); diff --git a/app/assets/javascripts/operation_settings/store/actions.js b/app/assets/javascripts/operation_settings/store/actions.js index 529eb7d207b..5f60cab8bdd 100644 --- a/app/assets/javascripts/operation_settings/store/actions.js +++ b/app/assets/javascripts/operation_settings/store/actions.js @@ -1,4 +1,4 @@ -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { refreshCurrentPage } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; @@ -35,7 +35,7 @@ export const receiveSaveChangesError = (_, error) => { const { response = {} } = error; const message = response.data && response.data.message ? response.data.message : ''; - createFlash({ + createAlert({ message: `${__('There was an error saving your changes.')} ${message}`, }); }; diff --git a/app/finders/packages/nuget/package_finder.rb b/app/finders/packages/nuget/package_finder.rb index 9ae52745bb2..23345f29198 100644 --- a/app/finders/packages/nuget/package_finder.rb +++ b/app/finders/packages/nuget/package_finder.rb @@ -15,7 +15,7 @@ module Packages result = base.nuget .has_version .with_name_like(@params[:package_name]) - result = result.with_version(@params[:package_version]) if @params[:package_version].present? + result = result.with_case_insensitive_version(@params[:package_version]) if @params[:package_version].present? result end end diff --git a/app/models/note.rb b/app/models/note.rb index daac489757b..b3c5a7a0ef7 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -693,7 +693,7 @@ class Note < ApplicationRecord # Method necesary while we transition into the new format for task system notes # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/369923 def note - return super unless system? && for_issue? && super.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN) + return super unless system? && for_issue? && super&.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN) super.sub!('task', 'checklist item') end @@ -701,7 +701,7 @@ class Note < ApplicationRecord # Method necesary while we transition into the new format for task system notes # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/369923 def note_html - return super unless system? && for_issue? && super.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN) + return super unless system? && for_issue? && super&.match?(ISSUE_TASK_SYSTEM_NOTE_PATTERN) super.sub!('task', 'checklist item') end diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb index b4c09d99bb0..b7c784d9351 100644 --- a/app/models/packages/package.rb +++ b/app/models/packages/package.rb @@ -114,6 +114,10 @@ class Packages::Package < ApplicationRecord ) end + scope :with_case_insensitive_version, ->(version) do + where('LOWER(version) = ?', version.downcase) + end + scope :search_by_name, ->(query) { fuzzy_search(query, [:name], use_minimum_char_limit: false) } scope :with_version, ->(version) { where(version: version) } scope :without_version_like, -> (version) { where.not(arel_table[:version].matches(version)) } diff --git a/app/services/ci/pipeline_artifacts/coverage_report_service.rb b/app/services/ci/pipeline_artifacts/coverage_report_service.rb index 99877603554..9c6fdb7a405 100644 --- a/app/services/ci/pipeline_artifacts/coverage_report_service.rb +++ b/app/services/ci/pipeline_artifacts/coverage_report_service.rb @@ -27,18 +27,13 @@ module Ci end def pipeline_artifact_params - attributes = { + { pipeline: pipeline, file_type: :code_coverage, file: carrierwave_file, - size: carrierwave_file['tempfile'].size + size: carrierwave_file['tempfile'].size, + locked: pipeline.locked } - - if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project) - attributes[:locked] = pipeline.locked - end - - attributes end def carrierwave_file diff --git a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb index aeb68a75f88..a0746ef32b2 100644 --- a/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb +++ b/app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb @@ -23,20 +23,15 @@ module Ci def artifact_attributes file = build_carrierwave_file! - attributes = { + { project_id: pipeline.project_id, file_type: :code_quality_mr_diff, file_format: Ci::PipelineArtifact::REPORT_TYPES.fetch(:code_quality_mr_diff), size: file["tempfile"].size, file: file, - expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now + expire_at: Ci::PipelineArtifact::EXPIRATION_DATE.from_now, + locked: pipeline.locked } - - if ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, pipeline.project) - attributes[:locked] = pipeline.locked - end - - attributes end def merge_requests diff --git a/app/services/ci/unlock_artifacts_service.rb b/app/services/ci/unlock_artifacts_service.rb index 1fee31da4fc..574cdae6480 100644 --- a/app/services/ci/unlock_artifacts_service.rb +++ b/app/services/ci/unlock_artifacts_service.rb @@ -11,8 +11,6 @@ module Ci unlocked_pipeline_artifacts: 0 } - unlock_pipeline_artifacts_enabled = ::Feature.enabled?(:ci_update_unlocked_pipeline_artifacts, ci_ref.project) - if ::Feature.enabled?(:ci_update_unlocked_job_artifacts, ci_ref.project) loop do unlocked_pipelines = [] @@ -22,9 +20,7 @@ module Ci unlocked_pipelines = unlock_pipelines(ci_ref, before_pipeline) unlocked_job_artifacts = unlock_job_artifacts(unlocked_pipelines) - if unlock_pipeline_artifacts_enabled - results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines) - end + results[:unlocked_pipeline_artifacts] += unlock_pipeline_artifacts(unlocked_pipelines) end break if unlocked_pipelines.empty? diff --git a/app/views/admin/application_settings/_gitaly.html.haml b/app/views/admin/application_settings/_gitaly.html.haml index ade6dac606a..f459ff5abc4 100644 --- a/app/views/admin/application_settings/_gitaly.html.haml +++ b/app/views/admin/application_settings/_gitaly.html.haml @@ -1,4 +1,4 @@ -= form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-gitaly-settings'), html: { class: 'fieldset-form' } do |f| += gitlab_ui_form_for @application_setting, url: preferences_admin_application_settings_path(anchor: 'js-gitaly-settings'), html: { class: 'fieldset-form' } do |f| = form_errors(@application_setting) %fieldset @@ -18,4 +18,4 @@ .form-text.text-muted = _('Timeout for moderately fast Gitaly operations (in seconds). Provide a value between Default timeout and Fast timeout.') - = f.submit _('Save changes'), class: "gl-button btn btn-confirm" + = f.submit _('Save changes'), pajamas_button: true diff --git a/app/views/admin/application_settings/_sentry.html.haml b/app/views/admin/application_settings/_sentry.html.haml index cfd34f6ca15..20164cfe88d 100644 --- a/app/views/admin/application_settings/_sentry.html.haml +++ b/app/views/admin/application_settings/_sentry.html.haml @@ -17,4 +17,4 @@ = f.label :sentry_environment, _('Environment'), class: 'label-light' = f.text_field :sentry_environment, class: 'form-control gl-form-input', placeholder: Rails.env - = f.submit _('Save changes'), class: 'gl-button btn btn-confirm' + = f.submit _('Save changes'), pajamas_button: true diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index 271f89a6b08..ccea1714973 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -35,7 +35,7 @@ = link_to(s_('AdminArea|New project'), new_project_path, class: "btn gl-button btn-default") = c.footer do .d-flex.align-items-center - = link_to(s_('AdminArea|View latest projects'), admin_projects_path) + = link_to(s_('AdminArea|View latest projects'), admin_projects_path(sort: 'created_desc')) = sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2') .col-md-4.gl-mb-6 = render Pajamas::CardComponent.new(**component_params) do |c| @@ -71,7 +71,7 @@ = link_to(s_('AdminArea|New group'), new_admin_group_path, class: "btn gl-button btn-default") = c.footer do .d-flex.align-items-center - = link_to(s_('AdminArea|View latest groups'), admin_groups_path) + = link_to(s_('AdminArea|View latest groups'), admin_groups_path(sort: 'created_desc')) = sprite_icon('chevron-right', size: 12, css_class: 'gl-text-gray-700 gl-ml-2') .row .col-md-4.gl-mb-6 diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml index 74882900756..a03d6cb5a94 100644 --- a/app/views/admin/deploy_keys/new.html.haml +++ b/app/views/admin/deploy_keys/new.html.haml @@ -3,8 +3,9 @@ %hr %div - = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f| + = gitlab_ui_form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f| = render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key } .form-actions - = f.submit 'Create', class: 'btn gl-button btn-confirm', data: { qa_selector: "add_deploy_key_button" } - = link_to _('Cancel'), admin_deploy_keys_path, class: 'btn gl-button btn-default btn-cancel' + = f.submit 'Create', data: { qa_selector: "add_deploy_key_button" }, pajamas_button: true + = render Pajamas::ButtonComponent.new(href: admin_deploy_keys_path) do + = _('Cancel') diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml index e81a5928983..76c4cf41a2d 100644 --- a/app/views/devise/shared/_tabs_ldap.html.haml +++ b/app/views/devise/shared/_tabs_ldap.html.haml @@ -1,7 +1,7 @@ - show_password_form = local_assigns.fetch(:show_password_form, password_authentication_enabled_for_web?) - render_signup_link = local_assigns.fetch(:render_signup_link, true) -%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: "#{"custom-provider-tabs" if any_form_based_providers_enabled?} #{"nav-links-unboxed" if Feature.enabled?(:restyle_login_page, @project)}" } +%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: "#{'custom-provider-tabs' if any_form_based_providers_enabled?} #{'nav-links-unboxed' if Feature.enabled?(:restyle_login_page, @project)}" } - if crowd_enabled? %li.nav-item = link_to _("Crowd"), "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab', role: 'tab' diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml index e5b03acbe3b..9801b0cc055 100644 --- a/app/views/layouts/header/_new_dropdown.html.haml +++ b/app/views/layouts/header/_new_dropdown.html.haml @@ -24,4 +24,4 @@ = menu_item.fetch(:title) - if menu_item.fetch(:emoji) -# We need to insert a space between the title and emoji - = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: "gl-font-base gl-vertical-align-baseline")}".html_safe + = " #{emoji_icon(menu_item.fetch(:emoji), 'aria-hidden': true, class: 'gl-font-base gl-vertical-align-baseline')}".html_safe diff --git a/app/views/layouts/notify.html.haml b/app/views/layouts/notify.html.haml index d05b6951fbf..c557dc36534 100644 --- a/app/views/layouts/notify.html.haml +++ b/app/views/layouts/notify.html.haml @@ -24,7 +24,7 @@ - if @reply_by_email = _('Reply to this email directly or %{view_it_on_gitlab}.').html_safe % { view_it_on_gitlab: link_to(_("view it on GitLab"), @target_url) } - else - #{link_to _("View it on GitLab"), @target_url}. + #{link_to _('View it on GitLab'), @target_url}. %br = notification_reason_text(reason: @reason, show_manage_notifications_link: !@labels_url, show_help_link: true, manage_label_subscriptions_url: @labels_url, unsubscribe_url: @unsubscribe_url, format: :html) diff --git a/app/views/notify/repository_push_email.text.haml b/app/views/notify/repository_push_email.text.haml index 895d8807e47..2ba0a2cf4ab 100644 --- a/app/views/notify/repository_push_email.text.haml +++ b/app/views/notify/repository_push_email.text.haml @@ -13,7 +13,7 @@ \- - - - - \ \ - #{pluralize @message.diffs_count, "changed file"}: + #{pluralize @message.diffs_count, 'changed file'}: \ - @message.diffs.each do |diff_file| - if diff_file.deleted_file? diff --git a/app/views/notify/send_unsubscribed_notification.html.haml b/app/views/notify/send_unsubscribed_notification.html.haml index 9f68feeaa31..ef1577dde97 100644 --- a/app/views/notify/send_unsubscribed_notification.html.haml +++ b/app/views/notify/send_unsubscribed_notification.html.haml @@ -1,2 +1,2 @@ %p - You have been unsubscribed from receiving GitLab administrator notifications. + = s_('Notify|You have been unsubscribed from receiving GitLab administrator notifications.') diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index c11ba093fa6..f4513d15a30 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -10,12 +10,12 @@ .col-lg-8 %h4.gl-mt-0 = _('Add email address') - = form_for 'email', url: profile_emails_path do |f| + = gitlab_ui_form_for 'email', url: profile_emails_path do |f| .form-group = f.label :email, _('Email'), class: 'label-bold' = f.text_field :email, class: 'form-control gl-form-input', data: { qa_selector: 'email_address_field' } .gl-mt-3 - = f.submit _('Add email address'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'add_email_address_button' } + = f.submit _('Add email address'), data: { qa_selector: 'add_email_address_button' }, pajamas_button: true %hr %h4.gl-mt-0 = _('Linked emails (%{email_count})') % { email_count: @emails.load.size } diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml index 9804a3b7735..ffd8bc3de27 100644 --- a/app/views/profiles/gpg_keys/_form.html.haml +++ b/app/views/profiles/gpg_keys/_form.html.haml @@ -1,5 +1,5 @@ %div - = form_for [:profile, @gpg_key], html: { class: 'js-requires-input' } do |f| + = gitlab_ui_form_for [:profile, @gpg_key], html: { class: 'js-requires-input' } do |f| = form_errors(@gpg_key) .form-group @@ -7,4 +7,4 @@ = f.text_area :key, class: "form-control gl-form-input", rows: 8, required: true, placeholder: _("Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'.") .gl-mt-3 - = f.submit s_('Profiles|Add key'), class: "gl-button btn btn-confirm" + = f.submit s_('Profiles|Add key'), pajamas_button: true diff --git a/app/views/projects/buttons/_download_links.html.haml b/app/views/projects/buttons/_download_links.html.haml index f6084cfcde8..d36aed44e18 100644 --- a/app/views/projects/buttons/_download_links.html.haml +++ b/app/views/projects/buttons/_download_links.html.haml @@ -1,4 +1,4 @@ .btn-group.ml-0.w-100 - Gitlab::Workhorse::ARCHIVE_FORMATS.each_with_index do |fmt, index| - archive_path = project_archive_path(project, id: tree_join(ref, archive_prefix), path: path, format: fmt) - = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? "btn-confirm" : "btn-default"}" + = link_to fmt, external_storage_url_or_path(archive_path), rel: 'nofollow', download: '', class: "gl-button btn btn-sm #{index == 0 ? 'btn-confirm' : 'btn-default'}" diff --git a/app/views/projects/commit/_signature.html.haml b/app/views/projects/commit/_signature.html.haml index fb31ac44118..978d83bf2b4 100644 --- a/app/views/projects/commit/_signature.html.haml +++ b/app/views/projects/commit/_signature.html.haml @@ -1,3 +1,3 @@ - if signature - - uri = "projects/commit/#{"x509/" if x509_signature?(signature)}" + - uri = "projects/commit/#{'x509/' if x509_signature?(signature)}" = render partial: "#{uri}#{signature.verification_status}_signature_badge", locals: { signature: signature } diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml index 7c896cd71ef..fb30bfc2953 100644 --- a/app/views/projects/commit/_signature_badge.html.haml +++ b/app/views/projects/commit/_signature_badge.html.haml @@ -17,7 +17,7 @@ - content = capture do - if show_user .clearfix - - uri_signature_badge_user = "projects/commit/#{"x509/" if x509_signature?(signature)}signature_badge_user" + - uri_signature_badge_user = "projects/commit/#{'x509/' if x509_signature?(signature)}signature_badge_user" = render partial: "#{uri_signature_badge_user}", locals: { signature: signature } - if x509_signature?(signature) diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 6f44c130603..511d017f023 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -29,7 +29,7 @@ - if view_details && merge_request = link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: ["commit-row-message item-title js-onboarding-commit-item", ("font-italic" if commit.message.empty?)] - else - = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{"font-italic" if commit.message.empty?}", data: link_data_attrs) + = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title js-onboarding-commit-item #{'font-italic' if commit.message.empty?}", data: link_data_attrs) %span.commit-row-message.d-inline.d-sm-none · = commit.short_id diff --git a/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml b/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml deleted file mode 100644 index ffcd5352751..00000000000 --- a/config/feature_flags/development/ci_update_unlocked_pipeline_artifacts.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: ci_update_unlocked_pipeline_artifacts -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97228 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372835 -milestone: '15.4' -type: development -group: group::pipeline insights -default_enabled: false diff --git a/config/initializers/load_balancing.rb b/config/initializers/load_balancing.rb index bcc62a6be5d..aa621602573 100644 --- a/config/initializers/load_balancing.rb +++ b/config/initializers/load_balancing.rb @@ -2,6 +2,15 @@ Gitlab::Application.configure do |config| config.middleware.use(Gitlab::Database::LoadBalancing::RackMiddleware) + + # We need re-rerun the setup when code reloads in development + config.reloader.to_prepare do + if Gitlab.dev_or_test_env? + Gitlab::Database::LoadBalancing.base_models.each do |model| + Gitlab::Database::LoadBalancing::Setup.new(model).setup + end + end + end end Gitlab::Database::LoadBalancing.base_models.each do |model| @@ -14,13 +23,6 @@ Gitlab::Database::LoadBalancing.base_models.each do |model| # information. Gitlab::Database::LoadBalancing::Setup.new(model).setup - # We need re-rerun the setup when code reloads in development - Rails.application.reloader.to_prepare do - if Rails.env.development? || Rails.env.test? - Gitlab::Database::LoadBalancing::Setup.new(model).setup - end - end - # Database queries may be run before we fork, so we must set up the load # balancer as early as possible. When we do fork, we need to make sure all the # hosts are disconnected. diff --git a/db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb b/db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb new file mode 100644 index 00000000000..23b58522639 --- /dev/null +++ b/db/migrate/20220919225631_add_index_packages_packages_on_project_id_and_lower_version_to_packages.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddIndexPackagesPackagesOnProjectIdAndLowerVersionToPackages < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + INDEX_NAME = 'index_packages_packages_on_project_id_and_lower_version' + NUGET_PACKAGE_TYPE = 4 + + def up + add_concurrent_index( + :packages_packages, + 'project_id, LOWER(version)', + name: INDEX_NAME, + where: "package_type = #{NUGET_PACKAGE_TYPE}" + ) + end + + def down + remove_concurrent_index_by_name(:packages_packages, INDEX_NAME) + end +end diff --git a/db/schema_migrations/20220919225631 b/db/schema_migrations/20220919225631 new file mode 100644 index 00000000000..e30af0fd9f7 --- /dev/null +++ b/db/schema_migrations/20220919225631 @@ -0,0 +1 @@ +03accc241b8955f0ccfa3b40168e9f194360704d8937cd531683191b8fe4f8c8
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 73245d379c2..5a4b23dee0d 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -29667,6 +29667,8 @@ CREATE INDEX index_packages_packages_on_name_trigram ON packages_packages USING CREATE INDEX index_packages_packages_on_project_id_and_created_at ON packages_packages USING btree (project_id, created_at); +CREATE INDEX index_packages_packages_on_project_id_and_lower_version ON packages_packages USING btree (project_id, lower((version)::text)) WHERE (package_type = 4); + CREATE INDEX index_packages_packages_on_project_id_and_package_type ON packages_packages USING btree (project_id, package_type); CREATE INDEX index_packages_packages_on_project_id_and_status_and_id ON packages_packages USING btree (project_id, status, id); diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md index 9c58b27a101..667e4bf19ce 100644 --- a/doc/administration/reference_architectures/10k_users.md +++ b/doc/administration/reference_architectures/10k_users.md @@ -17,6 +17,7 @@ full list of reference architectures, see > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Service | Nodes | Configuration | GCP | AWS | Azure | |------------------------------------------|-------|-------------------------|------------------|----------------|-----------| diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md index f6c2beeee44..8b72425d479 100644 --- a/doc/administration/reference_architectures/1k_users.md +++ b/doc/administration/reference_architectures/1k_users.md @@ -12,7 +12,7 @@ full list of reference architectures, see If you are serving up to 1,000 users and you don't have strict availability requirements, a single-node solution with -[frequent backups](index.md#automated-backups) is appropriate for +[frequent backups](index.md#backups) is appropriate for many organizations. > - **Supported users (approximate):** 1,000 @@ -24,6 +24,7 @@ many organizations. > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 20 RPS, Web: 2 RPS, Git (Pull): 2 RPS, Git (Push): 1 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Users | Configuration | GCP | AWS | Azure | |--------------|-------------------------|----------------|--------------|----------| diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md index 5958fba6013..6431a1240dd 100644 --- a/doc/administration/reference_architectures/25k_users.md +++ b/doc/administration/reference_architectures/25k_users.md @@ -17,6 +17,7 @@ full list of reference architectures, see > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Service | Nodes | Configuration | GCP | AWS | Azure | |------------------------------------------|-------|-------------------------|------------------|--------------|-----------| diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md index b745731955a..6f911c679b0 100644 --- a/doc/administration/reference_architectures/2k_users.md +++ b/doc/administration/reference_architectures/2k_users.md @@ -18,6 +18,7 @@ For a full list of reference architectures, see > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Service | Nodes | Configuration | GCP | AWS | Azure | |----------------------------|-------|------------------------|-----------------|--------------|----------| diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md index 446716aca5d..7f112303110 100644 --- a/doc/administration/reference_architectures/3k_users.md +++ b/doc/administration/reference_architectures/3k_users.md @@ -27,6 +27,7 @@ For a full list of reference architectures, see > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Service | Nodes | Configuration | GCP | AWS | Azure | |-------------------------------------------|-------|-----------------------|-----------------|--------------|----------| diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md index 1272423a7f1..c6b4a3eff96 100644 --- a/doc/administration/reference_architectures/50k_users.md +++ b/doc/administration/reference_architectures/50k_users.md @@ -17,6 +17,7 @@ full list of reference architectures, see > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Service | Nodes | Configuration | GCP | AWS | Azure | |------------------------------------------|-------|-------------------------|------------------|---------------|-----------| diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md index 4653bbd2189..51c8d37e050 100644 --- a/doc/administration/reference_architectures/5k_users.md +++ b/doc/administration/reference_architectures/5k_users.md @@ -24,6 +24,7 @@ costly-to-operate environment by using the > - **Validation and test results:** The Quality Engineering team does [regular smoke and performance tests](index.md#validation-and-test-results) to ensure the reference architectures remain compliant > - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS > - **[Latest Results](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)** +> - **Unsure which Reference Architecture to use?** [Go to this guide for more info](index.md#deciding-which-architecture-to-use). | Service | Nodes | Configuration | GCP | AWS | Azure | |-------------------------------------------|-------|-------------------------|-----------------|--------------|----------| diff --git a/doc/administration/reference_architectures/img/reference-architectures.png b/doc/administration/reference_architectures/img/reference-architectures.png Binary files differdeleted file mode 100644 index 0f8e663b57b..00000000000 --- a/doc/administration/reference_architectures/img/reference-architectures.png +++ /dev/null diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md index d9863b2c16b..b1ce6a8299b 100644 --- a/doc/administration/reference_architectures/index.md +++ b/doc/administration/reference_architectures/index.md @@ -7,39 +7,15 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Reference architectures **(FREE SELF)** -You can set up GitLab on a single server or scale it up to serve many users. -This page details the recommended Reference Architectures that were built and -verified by the GitLab Quality and Support teams. - -Below is a chart representing each architecture tier and the number of users -they can handle. As your number of users grow with time, it's recommended that -you scale GitLab accordingly. - -![Reference Architectures](img/reference-architectures.png) -<!-- Internal link: https://docs.google.com/spreadsheets/d/1obYP4fLKkVVDOljaI3-ozhmCiPtEeMblbBKkf2OADKs/edit#gid=1403207183 --> - -For GitLab instances with less than 2,000 users, it's recommended that you use -the [default setup](#automated-backups) by -[installing GitLab](../../install/index.md) on a single machine to minimize -maintenance and resource costs. - -If your organization has more than 2,000 users, the recommendation is to scale the -GitLab components to multiple machine nodes. The machine nodes are grouped by -components. The addition of these nodes increases the performance and -scalability of to your GitLab instance. - -When scaling GitLab, there are several factors to consider: - -- Multiple application nodes to handle frontend traffic. -- A load balancer is added in front to distribute traffic across the application nodes. -- The application nodes connects to a shared file server and PostgreSQL and Redis services on the backend. +The GitLab Reference Architectures have been designed and tested by the +GitLab Quality and Support teams to provide recommended deployments at scale. ## Available reference architectures Depending on your workflow, the following recommended reference architectures may need to be adapted accordingly. Your workload is influenced by factors including how active your users are, how much automation you use, mirroring, -and repository/change size. Additionally the displayed memory values are +and repository/change size. Additionally, the displayed memory values are provided by [GCP machine types](https://cloud.google.com/compute/docs/machine-types). For different cloud vendors, attempt to select options that best match the provided architecture. @@ -72,6 +48,169 @@ to get assistance from Support with troubleshooting the [2,000 users](2k_users.m and higher reference architectures. [Read more about our definition of scaled architectures](https://about.gitlab.com/support/#definition-of-scaled-architecture). +## Deciding which architecture to use + +The Reference Architectures are designed to strike a balance between two important factors--performance and resilience. + +While they are designed to make it easier to set up GitLab at scale, it can still be a challenge to know which one will meet your requirements. + +As a general guide, **the more performant and/or resilient you want your environment to be, the more involved it will be**. + +This section explains the designs you can choose from. It begins with the least complexity, goes to the most, and ends with a decision tree. + +### Backups + +For environments serving 2,000 or fewer users we generally recommend that an [automated backup](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups) strategy is used instead of HA. + +Backups can provide a good level of RPO / RTO while avoiding the complexities that come with HA. + +### High Availability (HA) + +High Availability ensures every component in the GitLab setup can handle failures through various mechanisms. To achieve this however is involved, and the environments required can be sizable. + +For environments serving 3,000 or more users we generally recommend that a HA strategy is used as at this level outages will have a bigger impact against more users. All the architectures in this range have HA built in by design for this reason. + +For users who still need to have HA for a lower number of users this can also be achieved with an [adjusted 3K architecture as detailed here](3k_users.md#supported-modifications-for-lower-user-counts-ha). + +#### Do you need High Availability (HA)? + +As mentioned above, achieving HA does come at a cost. The environment's required are sizable as each component needs to be multiplied, which comes with additional actual and maintenance costs. + +For a lot of our customers with fewer than 3,000 users, we've found a backup strategy is sufficient and even preferable. While this does have a slower recovery time, it also means you have a much smaller architecture and less maintenance costs as a result. + +In general then, we'd only recommend you employ HA in the following scenarios: + +- When you have 3,000 or more users. +- When GitLab being down would critically impact your workflow. + +#### Zero Downtime Upgrades + +[Zero Downtime Upgrades](../../update/zero_downtime.md) are available for standard Reference Architecture environments with HA (Cloud Native Hybrid is not supported at this time). This allows for an environment to stay up during an upgrade, but the process is more involved as a result and has some limitations as detailed in the documentation. + +When going through this process it's worth noting that there may still be brief moments of downtime when the HA mechanisms tale effect. + +In most cases the downtime required for doing an upgrade in general shouldn't be substantial, so this is only recommended if it's a key requirement for you. + +### Cloud Native Hybrid (Kubernetes HA) + +As an additional layer of HA resilience you can deploy select components in Kubernetes, known as a Cloud Native Hybrid Reference Architecture. + +Note that this is an alternative and more **advanced** setup compared to a standard Reference Architecture. Running services in Kubernetes is well known to be complex. **This setup is only recommended** if you have strong working knowledge and experience in Kubernetes. + +### GitLab Geo (Cross Regional Distribution / Disaster Recovery) + +With [GitLab Geo](../geo/index.md) you can have both distributed environments in different regions and a full Disaster Recovery (DR) setup in place. With this setup you would have 2 or more separate environments, with one being a primary that gets replicated to the others. In the rare event the primary site went down completely you could fail over to one of the other environments. + +This is an **advanced and involved** setup and should only be undertaken if you have DR as a key requirement. Decisions then on how each environment are configured would also need to be taken, such as if each environment itself would be the full size and / or have HA. + +### Decision Tree + +Below you can find the above guidance in the form of a decision tree. It's recommended you read through the above guidance in full first before though. + +```mermaid +%%{init: { 'theme': 'base' } }%% +graph TD + L1A(<b>What Reference Architecture should I use?</b>) --> L2A(More than 3000 users?) + L2A -->|No| L3A("<a href=#do-you-need-high-availability-ha>Do you need HA?</a><br>(or Zero-Downtime Upgrades)") --> |Yes| L4A><b>Recommendation</b><br><br>3K architecture with HA<br>including supported modifications] + L3A -->|No| L4B><b>Recommendation</b><br><br>Architecture closest to user<br>count with Backups] + L2A -->|Yes| L3B[Do you have experience with<br/>and want additional resilience<br/>with select components in Kubernetes?] + L3B -->|No| L4C><b>Recommendation</b><br><br>Architecture closest to user<br>count with HA] + L3B -->|Yes| L4D><b>Recommendation</b><br><br>Cloud Native Hybrid architecture<br>closest to user count] + + L5A("<a href=#gitlab-geo-cross-regional-distribution-disaster-recovery>Do you need cross regional distribution or disaster recovery?"</a>) --> |Yes| L6A><b>Additional Recommendation</b><br><br> GitLab Geo] + L4A -.- L5A + L4B -.- L5A + L4C -.- L5A + L4D -.- L5A + +classDef default fill:#FCA326 +linkStyle default fill:none,stroke:#7759C2 +``` + +## Recommended cloud providers and services + +NOTE: +The following lists are non-exhaustive. Generally, other cloud providers not listed +here likely work with the same specs, but this hasn't been validated. +Additionally, when it comes to other cloud provider services not listed here, +it's advised to be cautious as each implementation can be notably different +and should be tested thoroughly before production use. + +Through testing and real life usage, the Reference Architectures are validated and supported on the following cloud providers: + +<table> +<thead> + <tr> + <th>Reference Architecture</th> + <th>GCP</th> + <th>AWS</th> + <th>Azure</th> + <th>Bare Metal</th> + </tr> +</thead> +<tbody> + <tr> + <td>Omnibus</td> + <td>✅</td> + <td>✅</td> + <td>✅</td> + <td>✅</td> + </tr> + <tr> + <td>Cloud Native Hybrid</td> + <td>✅</td> + <td>✅</td> + <td></td> + <td></td> + </tr> +</tbody> +</table> + +Additionally, the following cloud provider services are validated and supported for use as part of the Reference Architectures: + +<table> +<thead> + <tr> + <th>Cloud Service</th> + <th>GCP</th> + <th>AWS</th> + <th>Bare Metal</th> + </tr> +</thead> +<tbody> + <tr> + <td>Object Storage</td> + <td>✅ <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td> + <td>✅ <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td> + <td>✅ <a href="https://min.io/" target="_blank">MinIO</a></td> + </tr> + <tr> + <td>Database</td> + <td>✅ <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td> + <td>✅ <a href="https://aws.amazon.com/rds/" target="_blank" rel="noopener noreferrer">RDS</a></td> + <td></td> + </tr> + <tr> + <td>Redis</td> + <td></td> + <td>✅ <a href="https://aws.amazon.com/elasticache/" target="_blank" rel="noopener noreferrer">ElastiCache</a></td> + <td></td> + </tr> +</tbody> +</table> + +The following specific cloud provider services have been found to have issues in terms of either functionality or performance. As such, they either have caveats that should be considered or are not recommended: + +- [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo. +- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details. +- [Azure Blob Storage](https://azure.microsoft.com/en-gb/services/storage/blobs/) has been found to have performance limits that can impact production use at certain times. For larger Reference Architectures the service may not be sufficient for production use and an alternative is recommended for use instead. +- [Azure Database for PostgreSQL Server](https://azure.microsoft.com/en-gb/services/postgresql/#overview) (Single / Flexible) is not recommended for use due to notable performance issues or missing functionality. + +NOTE: +As a general rule we unfortunately don't recommend Azure Services at this time. +If required, we advise thorough testing is done at your intended scale +over a sustained period to validate if the service is suitable. + ## Validation and test results The [Quality Engineering team](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/) @@ -97,7 +236,7 @@ Network latency on the test environments between components on all Cloud Provide We aim to have a "test smart" approach where architectures tested have a good range that can also apply to others. Testing focuses on 10k Omnibus on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers as well as Cloud Native Hybrids. -The Standard Reference Architectures are designed to be platform agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal). +The Standard Reference Architectures are designed to be platform-agnostic, with everything being run on VMs via [Omnibus GitLab](https://docs.gitlab.com/omnibus/). While testing occurs primarily on GCP, ad-hoc testing has shown that they perform similarly on equivalently specced hardware on other Cloud Providers or if run on premises (bare-metal). Testing on these reference architectures is performed with the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) @@ -111,14 +250,14 @@ per 1,000 users: - API: 20 RPS - Web: 2 RPS - Git (Pull): 2 RPS -- Git (Push): 0.4 RPS (rounded to nearest integer) +- Git (Push): 0.4 RPS (rounded to the nearest integer) ### How to interpret the results NOTE: Read our blog post on [how our QA team leverages GitLab performance testing tool](https://about.gitlab.com/blog/2020/02/18/how-were-building-up-performance-testing-of-gitlab/). -Testing is done publicly and all results are shared. +Testing is done publicly, and all results are shared. The following table details the testing done against the reference architectures along with the frequency and results. Additional testing is continuously evaluated, and the table is updated accordingly. @@ -292,171 +431,6 @@ The following table details the cost to run the different reference architecture </tr> </table> -## Recommended cloud providers and services - -NOTE: -The following lists are non exhaustive. Generally, other cloud providers not listed -here likely work with the same specs, but this hasn't been validated. -Additionally, when it comes to other cloud provider services not listed here, -it's advised to be cautious as each implementation can be notably different -and should be tested thoroughly before production use. - -Through testing and real life usage, the Reference Architectures are validated and supported on the following cloud providers: - -<table> -<thead> - <tr> - <th>Reference Architecture</th> - <th>GCP</th> - <th>AWS</th> - <th>Azure</th> - <th>Bare Metal</th> - </tr> -</thead> -<tbody> - <tr> - <td>Omnibus</td> - <td>✅</td> - <td>✅</td> - <td>✅</td> - <td>✅</td> - </tr> - <tr> - <td>Cloud Native Hybrid</td> - <td>✅</td> - <td>✅</td> - <td></td> - <td></td> - </tr> -</tbody> -</table> - -Additionally, the following cloud provider services are validated and supported for use as part of the Reference Architectures: - -<table> -<thead> - <tr> - <th>Cloud Service</th> - <th>GCP</th> - <th>AWS</th> - <th>Bare Metal</th> - </tr> -</thead> -<tbody> - <tr> - <td>Object Storage</td> - <td>✅ <a href="https://cloud.google.com/storage" target="_blank">Cloud Storage</a></td> - <td>✅ <a href="https://aws.amazon.com/s3/" target="_blank">S3</a></td> - <td>✅ <a href="https://min.io/" target="_blank">MinIO</a></td> - </tr> - <tr> - <td>Database</td> - <td>✅ <a href="https://cloud.google.com/sql" target="_blank" rel="noopener noreferrer">Cloud SQL</a></td> - <td>✅ <a href="https://aws.amazon.com/rds/" target="_blank" rel="noopener noreferrer">RDS</a></td> - <td></td> - </tr> - <tr> - <td>Redis</td> - <td></td> - <td>✅ <a href="https://aws.amazon.com/elasticache/" target="_blank" rel="noopener noreferrer">ElastiCache</a></td> - <td></td> - </tr> -</tbody> -</table> - -The following specific cloud provider services have been found to have issues in terms of either functionality or performance. As such, they either have caveats that should be considered or are not recommended: - -- [Google AlloyDB](https://cloud.google.com/alloydb) and [Amazon RDS Multi-AZ DB clusters](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html) have not been tested and are not recommended. Both solutions are specifically not expected to work with GitLab Geo. -- [Amazon Aurora](https://aws.amazon.com/rds/aurora/) is incompatible. See [14.4.0](../../update/index.md#1440) for more details. -- [Azure Blob Storage](https://azure.microsoft.com/en-gb/services/storage/blobs/) has been found to have performance limits that can impact production use at certain times. For larger Reference Architectures the service may not be sufficient for production use and an alternative is recommended for use instead. -- [Azure Database for PostgreSQL Server](https://azure.microsoft.com/en-gb/services/postgresql/#overview) (Single / Flexible) is not recommended for use due to notable performance issues or missing functionality. - -NOTE: -As a general rule we unfortunately don't recommend Azure Services at this time. -If required, we advise thorough testing is done at your intended scale -over a sustained period to validate if the service is suitable. - -## Availability Components - -GitLab comes with the following components for your use, listed from least to -most complex: - -- [Automated backups](#automated-backups) -- [Traffic load balancer](#traffic-load-balancer) -- [Zero downtime updates](#zero-downtime-updates) -- [Automated database failover](#automated-database-failover) -- [Instance level replication with GitLab Geo](#instance-level-replication-with-gitlab-geo) - -As you implement these components, begin with a single server and then do -backups. Only after completing the first server should you proceed to the next. - -Also, not implementing extra servers for GitLab doesn't necessarily mean that you have -more downtime. Depending on your needs and experience level, single servers can -have more actual perceived uptime for your users. - -### Automated backups - -> - Level of complexity: **Low** -> - Required domain knowledge: PostgreSQL, GitLab configurations, Git - -This solution is appropriate for many teams that have the default GitLab installation. -With automatic backups of the GitLab repositories, configuration, and the database, -this can be an optimal solution if you don't have strict requirements. -[Automated backups](../../raketasks/backup_gitlab.md#configuring-cron-to-make-daily-backups) -is the least complex to setup. This provides a point-in-time recovery of a predetermined schedule. - -### Traffic load balancer **(PREMIUM SELF)** - -> - Level of complexity: **Medium** -> - Required domain knowledge: HAProxy, shared storage, distributed systems - -This requires separating out GitLab into multiple application nodes with an added -[load balancer](../load_balancer.md). The load balancer distributes traffic -across GitLab application nodes. Meanwhile, each application node connects to a -shared file server and database systems on the back end. This way, if one of the -application servers fails, the workflow is not interrupted. -[HAProxy](https://www.haproxy.org/) is recommended as the load balancer. - -With this added component you have a number of advantages compared -to the default installation: - -- Increase the number of users. -- Enable zero-downtime upgrades. -- Increase availability. - -For more details on how to configure a traffic load balancer with GitLab, you can refer -to any of the [available reference architectures](#available-reference-architectures) with more than 1,000 users. - -### Zero downtime updates **(PREMIUM SELF)** - -> - Level of complexity: **Medium** -> - Required domain knowledge: PostgreSQL, HAProxy, shared storage, distributed systems - -GitLab supports [zero-downtime upgrades](../../update/zero_downtime.md). -Single GitLab nodes can be updated with only a [few minutes of downtime](../../update/index.md#upgrade-based-on-installation-method). -To avoid this, we recommend to separate GitLab into several application nodes. -As long as at least one of each component is online and capable of handling the instance's usage load, your team's productivity is not interrupted during the update. - -### Automated database failover **(PREMIUM SELF)** - -> - Level of complexity: **High** -> - Required domain knowledge: PgBouncer, Patroni, shared storage, distributed systems - -By adding automatic failover for database systems, you can enable higher uptime -with additional database nodes. This extends the default database with -cluster management and failover policies. -[PgBouncer in conjunction with Patroni](../postgresql/replication_and_failover.md) -is recommended. - -### Instance level replication with GitLab Geo **(PREMIUM SELF)** - -> - Level of complexity: **Very High** -> - Required domain knowledge: Storage replication - -[GitLab Geo](../geo/index.md) allows you to replicate your GitLab -instance to other geographical locations as a read-only fully operational instance -that can also be promoted in case of disaster. - ## Deviating from the suggested reference architectures As a general guideline, the further away you move from the Reference Architectures, @@ -476,11 +450,3 @@ However, it is still an additional layer and may still add some support complexi Other technologies, like [Docker swarm](https://docs.docker.com/engine/swarm/) are not officially supported, but can be implemented at your own risk. In that case, GitLab Support is not able to help you. - -## Supported modifications for lower user count HA reference architectures - -The reference architectures for user counts [3,000](3k_users.md) and up support High Availability (HA). - -In the specific case you have the requirement to achieve HA but have a lower user count, select modifications to the [3,000 user](3k_users.md) architecture are supported. - -For more details, [refer to this section in the architecture's documentation](3k_users.md#supported-modifications-for-lower-user-counts-ha). diff --git a/doc/ci/services/index.md b/doc/ci/services/index.md index 602a3307dfe..fca5eac47ac 100644 --- a/doc/ci/services/index.md +++ b/doc/ci/services/index.md @@ -370,8 +370,11 @@ access-service: curlimages/curl:7.74.0 curl "http://tutum-wordpress" ``` -For this solution to work, you must use -[the networking mode that creates a new network for each job](https://docs.gitlab.com/runner/executors/docker.html#create-a-network-for-each-job). +For this solution to work, you must: + +- Use [the networking mode that creates a new network for each job](https://docs.gitlab.com/runner/executors/docker.html#create-a-network-for-each-job). +- [Not use the Docker executor with Docker socket binding](../docker/using_docker_build.md#use-the-docker-executor-with-docker-socket-binding). + If you must, then in the above example, instead of `host`, use the dynamic network name created for this job. ## How Docker integration works diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md index d0df6387116..cb3c2d4f6e7 100644 --- a/doc/development/integrations/secure.md +++ b/doc/development/integrations/secure.md @@ -358,6 +358,10 @@ analyzer to use the latest available schemas. After the deprecation period for a schema version, the file is removed from GitLab. Reports that declare removed versions are rejected, and an error message displays on the corresponding pipeline. +If a report uses a `PATCH` version that doesn't match any vendored schema version, it is validated against +the latest vendored `PATCH` version. For example, if a report version is 14.0.23 and the latest vendored +version is 14.0.6, the report is validated against version 14.0.6. + GitLab uses the [`json_schemer`](https://www.rubydoc.info/gems/json_schemer) gem to perform validation. diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index 05e952fb31a..f91219a46f9 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -755,30 +755,65 @@ We limit the artifacts that are saved and retrieved by jobs to the minimum in or ### Components caching -Some external components (currently only GitLab Workhorse) of GitLab need to be built from source as a preliminary step for running tests. +Some external components (GitLab Workhorse and frontend assets) of GitLab need to be built from source as a preliminary step for running tests. -In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), we introduced a new `build-components` job that: +#### `cache-workhorse` + +In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/79766), and then +[this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96297), +we introduced a new `cache-workhorse` job that: - runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines - runs automatically for any `master` commit that touches the `workhorse/` folder -- is manual for GitLab.com's `gitlab-org`'s MRs +- is manual for GitLab.com's `gitlab-org`'s MRs that touches caching-related files This job tries to download a generic package that contains GitLab Workhorse binaries needed in the GitLab test suite (under `tmp/tests/gitlab-workhorse`). - If the package URL returns a 404: 1. It runs `scripts/setup-test-env`, so that the GitLab Workhorse binaries are built. 1. It then creates an archive which contains the binaries and upload it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/). -- Otherwise, if the package already exists, it exit the job successfully. +- Otherwise, if the package already exists, it exits the job successfully. We also changed the `setup-test-env` job to: -1. First download the GitLab Workhorse generic package build and uploaded by `build-components`. +1. First download the GitLab Workhorse generic package build and uploaded by `cache-workhorse`. 1. If the package is retrieved successfully, its content is placed in the right folder (for example, `tmp/tests/gitlab-workhorse`), preventing the building of the binaries when `scripts/setup-test-env` is run later on. 1. If the package URL returns a 404, the behavior doesn't change compared to the current one: the GitLab Workhorse binaries are built as part of `scripts/setup-test-env`. NOTE: The version of the package is the workhorse tree SHA (for example, `git rev-parse HEAD:workhorse`). +#### `cache-assets` + +In [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96297), +we introduced three new `cache-assets:test`, `cache-assets:test as-if-foss`, +and `cache-assets:production` jobs that: + +- never run unless `$CACHE_ASSETS_AS_PACKAGE == "true"` +- runs automatically for all GitLab.com `gitlab-org/gitlab` scheduled pipelines +- runs automatically for any `master` commit that touches the assets-related folders +- is manual for GitLab.com's `gitlab-org`'s MRs that touches caching-related files + +This job tries to download a generic package that contains GitLab compiled assets +needed in the GitLab test suite (under `app/assets/javascripts/locale/**/app.js`, +`public/assets`, `tmp/cache/assets/sprockets/`, `tmp/cache/babel-loader/`, +and `tmp/cache/vue-loader/`). + +- If the package URL returns a 404: + 1. It runs `bin/rake gitlab:assets:compile_with_new_strategy`, so that the GitLab assets are compiled. + 1. It then creates an archive which contains the assets and upload it [as a generic package](https://gitlab.com/gitlab-org/gitlab/-/packages/). +- Otherwise, if the package already exists, it exits the job successfully. + +We also changed the `compile-test-assets`, `compile-test-assets as-if-foss`, +and `compile-production-assets` jobs to: + +1. First download the GitLab assets generic package build and uploaded by `cache-assets:*`. +1. If the package is retrieved successfully, assets aren't compiled. +1. If the package URL returns a 404, the behavior doesn't change compared to the current one: the GitLab assets are compiled as part of `bin/rake gitlab:assets:compile_with_new_strategy`. + +NOTE: +The version of the package is the assets folders hash sum. + ### Pre-clone step NOTE: diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md index 55d284b3ee5..ec932f2384b 100644 --- a/doc/subscriptions/bronze_starter.md +++ b/doc/subscriptions/bronze_starter.md @@ -82,8 +82,7 @@ the tiers are no longer mentioned in GitLab documentation: - Rake tasks: - [Displaying GitLab license information](../administration/raketasks/maintenance.md#show-gitlab-license-information) - Reference Architecture information: - - [Traffic load balancers](../administration/reference_architectures/index.md#traffic-load-balancer) - - [Zero downtime updates](../administration/reference_architectures/index.md#zero-downtime-updates) + - [Zero downtime upgrades](../administration/reference_architectures/index.md#zero-downtime-upgrades) - Repositories: - [Repository size limit](../user/admin_area/settings/account_and_limit_settings.md#repository-size-limit) - Repository mirroring: diff --git a/lib/tasks/gitlab/assets.rake b/lib/tasks/gitlab/assets.rake index 76ee5379213..3b1ba30acf9 100644 --- a/lib/tasks/gitlab/assets.rake +++ b/lib/tasks/gitlab/assets.rake @@ -5,28 +5,37 @@ require 'fileutils' module Tasks module Gitlab module Assets - FOSS_ASSET_FOLDERS = %w[app/assets fixtures/emojis vendor/assets/javascripts].freeze + FOSS_ASSET_FOLDERS = %w[app/assets fixtures/emojis vendor/assets].freeze EE_ASSET_FOLDERS = %w[ee/app/assets].freeze JH_ASSET_FOLDERS = %w[jh/app/assets].freeze - JS_ASSET_PATTERNS = %w[*.js config/**/*.js].freeze - JS_ASSET_FILES = %w[package.json yarn.lock].freeze + # In the new caching strategy, we check the assets hash sum *before* compiling + # the app/assets/javascripts/locale/**/app.js files. That means the hash sum + # must depend on locale/**/gitlab.po. + JS_ASSET_PATTERNS = %w[*.js config/**/*.js locale/**/gitlab.po].freeze + JS_ASSET_FILES = %w[ + package.json + yarn.lock + babel.config.js + config/webpack.config.js + ].freeze + EXCLUDE_PATTERNS = %w[ + app/assets/javascripts/locale/**/app.js + ].freeze MASTER_SHA256_HASH_FILE = 'master-assets-hash.txt' HEAD_SHA256_HASH_FILE = 'assets-hash.txt' - PUBLIC_ASSETS_WEBPACK_DIR = 'public/assets/webpack' + PUBLIC_ASSETS_DIR = 'public/assets' - def self.sha256_of_assets_impacting_webpack_compilation + def self.sha256_of_assets_impacting_compilation(verbose: true) start_time = Time.now - asset_files = assets_impacting_webpack_compilation - puts "Generating the SHA256 hash for #{assets_impacting_webpack_compilation.size} Webpack-related assets..." + asset_files = assets_impacting_compilation + puts "Generating the SHA256 hash for #{asset_files.size} Webpack-related assets..." if verbose - asset_file_sha256s = asset_files.map do |asset_file| - Digest::SHA256.file(asset_file).hexdigest - end + assets_sha256 = asset_files.map { |asset_file| Digest::SHA256.file(asset_file).hexdigest }.join - Digest::SHA256.hexdigest(asset_file_sha256s.join).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" } + Digest::SHA256.hexdigest(assets_sha256).tap { |sha256| puts "=> SHA256 generated in #{Time.now - start_time}: #{sha256}" if verbose } end - def self.assets_impacting_webpack_compilation + def self.assets_impacting_compilation assets_folders = FOSS_ASSET_FOLDERS assets_folders += EE_ASSET_FOLDERS if ::Gitlab.ee? assets_folders += JH_ASSET_FOLDERS if ::Gitlab.jh? @@ -38,32 +47,35 @@ module Tasks asset_files.concat(Dir.glob(["#{folder}/**/*.*"])) end - asset_files + asset_files - Dir.glob(EXCLUDE_PATTERNS) end - - private_class_method :assets_impacting_webpack_compilation + private_class_method :assets_impacting_compilation end end end namespace :gitlab do namespace :assets do + desc 'GitLab | Assets | Return the hash sum of all frontend assets' + task :hash_sum do + head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_compilation(verbose: false) + puts head_assets_sha256 + end + desc 'GitLab | Assets | Compile all frontend assets' task :compile do require_dependency 'gitlab/task_helpers' %w[ - yarn:check - gettext:po_to_json - rake:assets:precompile - gitlab:assets:compile_webpack_if_needed + gitlab:assets:compile_if_needed_with_old_strategy gitlab:assets:fix_urls gitlab:assets:check_page_bundle_mixins_css_for_sideeffects ].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task)) end - desc 'GitLab | Assets | Compile all Webpack assets' - task :compile_webpack_if_needed do + desc 'GitLab | Assets | Compile all assets' + task :compile_if_needed_with_old_strategy do + # The hash file is stored as assets-hash.txt in the cache, so we rename it before generating the one for HEAD. FileUtils.mv(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, Tasks::Gitlab::Assets::MASTER_SHA256_HASH_FILE, force: true) master_assets_sha256 = @@ -73,17 +85,20 @@ namespace :gitlab do 'missing!' end - head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_webpack_compilation.tap do |sha256| + head_assets_sha256 = Tasks::Gitlab::Assets.sha256_of_assets_impacting_compilation.tap do |sha256| File.write(Tasks::Gitlab::Assets::HEAD_SHA256_HASH_FILE, sha256) end - puts "Webpack assets SHA256 for `master`: #{master_assets_sha256}" - puts "Webpack assets SHA256 for `HEAD`: #{head_assets_sha256}" + puts "Assets SHA256 for `master`: #{master_assets_sha256}" + puts "Assets SHA256 for `HEAD`: #{head_assets_sha256}" + + public_assets_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR) - public_assets_webpack_dir_exists = Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) + if head_assets_sha256 != master_assets_sha256 || !public_assets_dir_exists + FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR) if public_assets_dir_exists - if head_assets_sha256 != master_assets_sha256 || !public_assets_webpack_dir_exists - FileUtils.rm_r(Tasks::Gitlab::Assets::PUBLIC_ASSETS_WEBPACK_DIR) if public_assets_webpack_dir_exists + Gitlab::TaskHelpers.invoke_and_time_task('gettext:po_to_json') + Gitlab::TaskHelpers.invoke_and_time_task('rake:assets:precompile') log_path = ENV['WEBPACK_COMPILE_LOG_PATH'] @@ -99,6 +114,31 @@ namespace :gitlab do end end + # With this new strategy, we don't have to run `gettext:po_to_json` prior to check the assets hash sum + desc 'GitLab | Assets | Compile all frontend assets' + task :compile_with_new_strategy do + require_dependency 'gitlab/task_helpers' + + %w[ + gitlab:assets:compile_if_needed_with_new_strategy + gitlab:assets:check_page_bundle_mixins_css_for_sideeffects + ].each(&::Gitlab::TaskHelpers.method(:invoke_and_time_task)) + end + + desc 'GitLab | Assets | Compile all assets' + task :compile_if_needed_with_new_strategy do + unless Dir.exist?(Tasks::Gitlab::Assets::PUBLIC_ASSETS_DIR) + Gitlab::TaskHelpers.invoke_and_time_task('gettext:po_to_json') + Gitlab::TaskHelpers.invoke_and_time_task('rake:assets:precompile') + + unless system('yarn webpack') + abort 'Error: Unable to compile webpack production bundle.'.color(:red) + end + + Gitlab::TaskHelpers.invoke_and_time_task('gitlab:assets:fix_urls') + end + end + desc 'GitLab | Assets | Clean up old compiled frontend assets' task clean: ['rake:assets:clean'] diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e23c9cd6dfd..56108695bf5 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -27399,6 +27399,9 @@ msgstr "" msgid "Notify|You have been mentioned in merge request %{mr_link}" msgstr "" +msgid "Notify|You have been unsubscribed from receiving GitLab administrator notifications." +msgstr "" + msgid "Notify|Your CSV import for project %{project_link} has been completed." msgstr "" @@ -27647,6 +27650,9 @@ msgstr "" msgid "OnCallSchedules|Route alerts directly to specific members of your team" msgstr "" +msgid "OnCallSchedules|Route alerts directly to specific members of your team. To access this feature, ask %{linkStart}a project Owner%{linkEnd} to grant you at least the Maintainer role." +msgstr "" + msgid "OnCallSchedules|Select participant" msgstr "" diff --git a/scripts/gitlab_component_helpers.sh b/scripts/gitlab_component_helpers.sh new file mode 100644 index 00000000000..75bc9b12347 --- /dev/null +++ b/scripts/gitlab_component_helpers.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash + +set -euo pipefail + +export CURL_TOKEN_HEADER="${CURL_TOKEN_HEADER:-"JOB-TOKEN"}" + +export GITLAB_COM_CANONICAL_PROJECT_ID="278964" # https://gitlab.com/gitlab-org/gitlab +export JIHULAB_COM_CANONICAL_PROJECT_ID="13953" # https://jihulab.com/gitlab-cn/gitlab +export CANONICAL_PROJECT_ID="${GITLAB_COM_CANONICAL_PROJECT_ID}" + +# By default, we only want to store/retrieve packages from GitLab.com... +export API_V4_URL="https://gitlab.com/api/v4" + +# Unless we're in the JiHu project, which needs to use its own package registry +if [[ "${CI_SERVER_HOST}" = "jihulab.com" ]]; then + export API_V4_URL="${CI_API_V4_URL}" + export CANONICAL_PROJECT_ID="${JIHULAB_COM_CANONICAL_PROJECT_ID}" +fi + +export API_PACKAGES_BASE_URL="${API_V4_URL}/projects/${CANONICAL_PROJECT_ID}/packages/generic" + +export UPLOAD_TO_CURRENT_SERVER="false" +# We only want to upload artifacts to https://gitlab.com and https://jihulab.com instances +if [[ "${CI_SERVER_HOST}" = "gitlab.com" ]] || [[ "${CI_SERVER_HOST}" = "jihulab.com" ]]; then + export UPLOAD_TO_CURRENT_SERVER="true" +fi + +export UPLOAD_PACKAGE_FLAG="false" +# And only if we're in a pipeline from the canonical project +if [[ "${UPLOAD_TO_CURRENT_SERVER}" = "true" ]] && [[ "${CI_PROJECT_ID}" = "${CANONICAL_PROJECT_ID}" ]]; then + export UPLOAD_PACKAGE_FLAG="true" +fi + +# Workhorse constants +export GITLAB_WORKHORSE_BINARIES_LIST="gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse" +export GITLAB_WORKHORSE_PACKAGE_FILES_LIST="${GITLAB_WORKHORSE_BINARIES_LIST} WORKHORSE_TREE" +export GITLAB_WORKHORSE_TREE=${GITLAB_WORKHORSE_TREE:-$(git rev-parse HEAD:workhorse)} +export GITLAB_WORKHORSE_PACKAGE="workhorse-${GITLAB_WORKHORSE_TREE}.tar.gz" +export GITLAB_WORKHORSE_PACKAGE_URL="${API_PACKAGES_BASE_URL}/${GITLAB_WORKHORSE_FOLDER}/${GITLAB_WORKHORSE_TREE}/${GITLAB_WORKHORSE_PACKAGE}" + +# Assets constants +export GITLAB_ASSETS_PATHS_LIST="assets-hash.txt app/assets/javascripts/locale/**/app.js public/assets/ tmp/cache/assets/sprockets/ tmp/cache/babel-loader/ tmp/cache/vue-loader/" + +export GITLAB_EDITION="ee" +if [[ "${FOSS_ONLY:-no}" = "1" ]] || [[ "${CI_PROJECT_NAME}" = "gitlab-foss" ]]; then + export GITLAB_EDITION="foss" +fi + +export GITLAB_ASSETS_HASH="${GITLAB_ASSETS_HASH:-"NO_HASH"}" +export GITLAB_ASSETS_PACKAGE="assets-${NODE_ENV}-${GITLAB_EDITION}-${GITLAB_ASSETS_HASH}.tar.gz" +export GITLAB_ASSETS_PACKAGE_URL="${API_PACKAGES_BASE_URL}/assets/${NODE_ENV}-${GITLAB_EDITION}-${GITLAB_ASSETS_HASH}/${GITLAB_ASSETS_PACKAGE}" + +# Generic helper functions +function archive_doesnt_exist() { + local package_url="${1}" + + status=$(curl -I --silent --retry 3 --output /dev/null -w "%{http_code}" "${package_url}") + + [[ "${status}" != "200" ]] +} + +function create_package() { + local archive_filename="${1}" + local paths_to_archive="${2}" + local tar_working_folder="${3:-.}" + + echoinfo "Running 'tar -czvf ${archive_filename} -C ${tar_working_folder} ${paths_to_archive}'" + tar -czf ${archive_filename} -C ${tar_working_folder} ${paths_to_archive} + du -h ${archive_filename} +} + +function upload_package() { + local archive_filename="${1}" + local package_url="${2}" + local token_header="${CURL_TOKEN_HEADER}" + local token="${CI_JOB_TOKEN}" + + if [[ "${UPLOAD_PACKAGE_FLAG}" = "false" ]]; then + echoerr "The archive ${archive_filename} isn't supposed to be uploaded for this instance (${CI_SERVER_HOST}) & project (${CI_PROJECT_PATH})!" + exit 1 + fi + + echoinfo "Uploading ${archive_filename} to ${package_url} ..." + curl --fail --silent --retry 3 --header "${token_header}: ${token}" --upload-file "${archive_filename}" "${package_url}" +} + +function read_curl_package() { + local package_url="${1}" + local token_header="${CURL_TOKEN_HEADER}" + local token="${CI_JOB_TOKEN}" + + echoinfo "Downloading from ${package_url} ..." + + curl --fail --silent --retry 3 --header "${token_header}: ${token}" "${package_url}" +} + +function extract_package() { + local tar_working_folder="${1:-.}" + mkdir -p "${tar_working_folder}" + + echoinfo "Extracting archive to ${tar_working_folder}" + + tar -xz -C ${tar_working_folder} < /dev/stdin +} + +# Workhorse functions +function gitlab_workhorse_archive_doesnt_exist() { + archive_doesnt_exist "${GITLAB_WORKHORSE_PACKAGE_URL}" +} + +function create_gitlab_workhorse_package() { + create_package "${GITLAB_WORKHORSE_PACKAGE}" "${GITLAB_WORKHORSE_FOLDER}" "${TMP_TEST_FOLDER}" +} + +function upload_gitlab_workhorse_package() { + upload_package "${GITLAB_WORKHORSE_PACKAGE}" "${GITLAB_WORKHORSE_PACKAGE_URL}" +} + +function download_and_extract_gitlab_workhorse_package() { + read_curl_package "${GITLAB_WORKHORSE_PACKAGE_URL}" | extract_package "${TMP_TEST_FOLDER}" +} + +function select_gitlab_workhorse_essentials() { + local tmp_path="${CI_PROJECT_DIR}/tmp/${GITLAB_WORKHORSE_FOLDER}" + local original_gitlab_workhorse_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}" + + mkdir -p ${tmp_path} + cd ${original_gitlab_workhorse_path} && mv ${GITLAB_WORKHORSE_PACKAGE_FILES_LIST} ${tmp_path} && cd - + rm -rf ${original_gitlab_workhorse_path} + + # Move the temp folder to its final destination + mv ${tmp_path} ${TMP_TEST_FOLDER} +} + +# Assets functions +function gitlab_assets_archive_doesnt_exist() { + archive_doesnt_exist "${GITLAB_ASSETS_PACKAGE_URL}" +} + +function download_and_extract_gitlab_assets() { + read_curl_package "${GITLAB_ASSETS_PACKAGE_URL}" | extract_package +} + +function create_gitlab_assets_package() { + create_package "${GITLAB_ASSETS_PACKAGE}" "${GITLAB_ASSETS_PATHS_LIST}" +} + +function upload_gitlab_assets_package() { + upload_package "${GITLAB_ASSETS_PACKAGE}" "${GITLAB_ASSETS_PACKAGE_URL}" +} diff --git a/scripts/gitlab_workhorse_component_helpers.sh b/scripts/gitlab_workhorse_component_helpers.sh deleted file mode 100644 index ebd43a125b9..00000000000 --- a/scripts/gitlab_workhorse_component_helpers.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -export CURL_TOKEN_HEADER="${CURL_TOKEN_HEADER:-"JOB-TOKEN"}" -export GITLAB_WORKHORSE_BINARIES_LIST="gitlab-resize-image gitlab-zip-cat gitlab-zip-metadata gitlab-workhorse" -export GITLAB_WORKHORSE_PACKAGE_FILES_LIST="${GITLAB_WORKHORSE_BINARIES_LIST} WORKHORSE_TREE" -export GITLAB_WORKHORSE_TREE=${GITLAB_WORKHORSE_TREE:-$(git rev-parse HEAD:workhorse)} -export GITLAB_WORKHORSE_PACKAGE="workhorse-${GITLAB_WORKHORSE_TREE}.tar.gz" -export GITLAB_WORKHORSE_PACKAGE_URL="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${GITLAB_WORKHORSE_FOLDER}/${GITLAB_WORKHORSE_TREE}/${GITLAB_WORKHORSE_PACKAGE}" - -function gitlab_workhorse_archive_doesnt_exist() { - local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}" - - status=$(curl -I --silent --retry 3 --output /dev/null -w "%{http_code}" "${package_url}") - - [[ "${status}" != "200" ]] -} - -function create_gitlab_workhorse_package() { - local archive_filename="${GITLAB_WORKHORSE_PACKAGE}" - local folder_to_archive="${GITLAB_WORKHORSE_FOLDER}" - local workhorse_folder_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}" - local tar_working_folder="${TMP_TEST_FOLDER}" - - echoinfo "Running 'tar -czvf ${archive_filename} -C ${tar_working_folder} ${folder_to_archive}'" - tar -czvf ${archive_filename} -C ${tar_working_folder} ${folder_to_archive} - du -h ${archive_filename} -} - -function extract_gitlab_workhorse_package() { - local tar_working_folder="${TMP_TEST_FOLDER}" - mkdir -p "${tar_working_folder}" - - echoinfo "Extracting archive to ${tar_working_folder}" - - tar -xzv -C ${tar_working_folder} < /dev/stdin -} - -function upload_gitlab_workhorse_package() { - local archive_filename="${GITLAB_WORKHORSE_PACKAGE}" - local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}" - local token_header="${CURL_TOKEN_HEADER}" - local token="${CI_JOB_TOKEN}" - - echoinfo "Uploading ${archive_filename} to ${package_url} ..." - curl --fail --silent --retry 3 --header "${token_header}: ${token}" --upload-file "${archive_filename}" "${package_url}" -} - -function read_curl_gitlab_workhorse_package() { - local package_url="${GITLAB_WORKHORSE_PACKAGE_URL}" - local token_header="${CURL_TOKEN_HEADER}" - local token="${CI_JOB_TOKEN}" - - echoinfo "Downloading from ${package_url} ..." - - curl --fail --silent --retry 3 --header "${token_header}: ${token}" "${package_url}" -} - -function download_and_extract_gitlab_workhorse_package() { - read_curl_gitlab_workhorse_package | extract_gitlab_workhorse_package -} - -function select_gitlab_workhorse_essentials() { - local tmp_path="${CI_PROJECT_DIR}/tmp/${GITLAB_WORKHORSE_FOLDER}" - local original_gitlab_workhorse_path="${TMP_TEST_GITLAB_WORKHORSE_PATH}" - - mkdir -p ${tmp_path} - cd ${original_gitlab_workhorse_path} && mv ${GITLAB_WORKHORSE_PACKAGE_FILES_LIST} ${tmp_path} && cd - - rm -rf ${original_gitlab_workhorse_path} - - # Move the temp folder to its final destination - mv ${tmp_path} ${TMP_TEST_FOLDER} -} diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb index c27e58634f6..e128db8d1c1 100644 --- a/spec/controllers/uploads_controller_spec.rb +++ b/spec/controllers/uploads_controller_spec.rb @@ -216,7 +216,7 @@ RSpec.describe UploadsController do end context 'for PDF files' do - let(:filename) { 'git-cheat-sheet.pdf' } + let(:filename) { 'sample.pdf' } let(:expected_disposition) { 'inline;' } let(:note) { create(:note, :with_pdf_attachment, project: project) } diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 2159f5b2dc1..530b4616765 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -184,7 +184,7 @@ FactoryBot.define do end trait :with_pdf_attachment do - attachment { fixture_file_upload("spec/fixtures/git-cheat-sheet.pdf", "application/pdf") } + attachment { fixture_file_upload("spec/fixtures/sample.pdf", "application/pdf") } end trait :confidential do diff --git a/spec/finders/packages/nuget/package_finder_spec.rb b/spec/finders/packages/nuget/package_finder_spec.rb index 415bf796a72..6a6eebca778 100644 --- a/spec/finders/packages/nuget/package_finder_spec.rb +++ b/spec/finders/packages/nuget/package_finder_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Packages::Nuget::PackageFinder do let_it_be(:subgroup) { create(:group, parent: group) } let_it_be(:project) { create(:project, namespace: subgroup) } let_it_be_with_refind(:package1) { create(:nuget_package, project: project) } - let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0', project: project) } + let_it_be(:package2) { create(:nuget_package, name: package1.name, version: '2.0.0-ABC', project: project) } let_it_be(:package3) { create(:nuget_package, name: 'Another.Dummy.Package', project: project) } let_it_be(:other_package_1) { create(:nuget_package, name: package1.name, version: package1.version) } let_it_be(:other_package_2) { create(:nuget_package, name: package1.name, version: package2.version) } @@ -43,7 +43,13 @@ RSpec.describe Packages::Nuget::PackageFinder do end context 'with valid version' do - let(:package_version) { '2.0.0' } + let(:package_version) { '2.0.0-ABC' } + + it { is_expected.to match_array([package2]) } + end + + context 'with varying case version' do + let(:package_version) { '2.0.0-abC' } it { is_expected.to match_array([package2]) } end diff --git a/spec/fixtures/git-cheat-sheet.pdf b/spec/fixtures/git-cheat-sheet.pdf deleted file mode 100644 index 5ef905c0889..00000000000 --- a/spec/fixtures/git-cheat-sheet.pdf +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:35967a21e5d856eaea89d2e5dd55a5e3b5f4e1e4efe3b000ef6d60b31600f1d2 -size 7352215 diff --git a/spec/fixtures/sample.pdf b/spec/fixtures/sample.pdf new file mode 100644 index 00000000000..81ea09d7d12 --- /dev/null +++ b/spec/fixtures/sample.pdf @@ -0,0 +1,13 @@ +%PDF-1.3 +%����������� +4 0 obj +<< /Length 5 0 R /Filter /FlateDecode >> +stream +xe���0��>ō�@��� +ba�d�1U�V��_8��n�e}��fXU�`\F�d2�����S%,�Q]�;XC�9�+Qy���k>a2>31B4�;���d)!Md�M�-�B��F���N�[v��~��E�5���^�Z_���o�l.� +endstream +endobj +5 0 obj +155 +endobj +2 0 obj diff --git a/spec/frontend/editor/schema/ci/ci_schema_spec.js b/spec/frontend/editor/schema/ci/ci_schema_spec.js index c9010fbec0c..f9f0e56d30c 100644 --- a/spec/frontend/editor/schema/ci/ci_schema_spec.js +++ b/spec/frontend/editor/schema/ci/ci_schema_spec.js @@ -29,12 +29,14 @@ import CacheYaml from './yaml_tests/positive_tests/cache.yml'; import FilterYaml from './yaml_tests/positive_tests/filter.yml'; import IncludeYaml from './yaml_tests/positive_tests/include.yml'; import RulesYaml from './yaml_tests/positive_tests/rules.yml'; +import VariablesYaml from './yaml_tests/positive_tests/variables.yml'; // YAML NEGATIVE TEST import ArtifactsNegativeYaml from './yaml_tests/negative_tests/artifacts.yml'; import CacheNegativeYaml from './yaml_tests/negative_tests/cache.yml'; import IncludeNegativeYaml from './yaml_tests/negative_tests/include.yml'; import RulesNegativeYaml from './yaml_tests/negative_tests/rules.yml'; +import VariablesNegativeYaml from './yaml_tests/negative_tests/variables.yml'; const ajv = new Ajv({ strictTypes: false, @@ -67,6 +69,7 @@ describe('positive tests', () => { FilterYaml, IncludeYaml, RulesYaml, + VariablesYaml, }), )('schema validates %s', (_, input) => { expect(input).toValidateJsonSchema(schema); @@ -90,6 +93,7 @@ describe('negative tests', () => { CacheNegativeYaml, IncludeNegativeYaml, RulesNegativeYaml, + VariablesNegativeYaml, }), )('schema validates %s', (_, input) => { expect(input).not.toValidateJsonSchema(schema); diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml new file mode 100644 index 00000000000..a7f23cf0d73 --- /dev/null +++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/variables.yml @@ -0,0 +1,5 @@ +# invalid variable (unknown keyword is used) +variables: + FOO: + value: BAR + desc: A single value variable diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml new file mode 100644 index 00000000000..ee71087a72e --- /dev/null +++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/variables.yml @@ -0,0 +1,8 @@ +variables: + TEST_VAR: "hello world!" + 123456: "123456" + FOO: + value: "BAR" + description: "A single value variable" + DEPLOY_ENVIRONMENT: + description: "A multi-value variable" diff --git a/spec/frontend/notes/components/comment_form_spec.js b/spec/frontend/notes/components/comment_form_spec.js index 55e4ef42e37..748cfdf0fb4 100644 --- a/spec/frontend/notes/components/comment_form_spec.js +++ b/spec/frontend/notes/components/comment_form_spec.js @@ -7,7 +7,7 @@ import Vuex from 'vuex'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import batchComments from '~/batch_comments/stores/modules/batch_comments'; import { refreshUserMergeRequestCounts } from '~/commons/nav/user_merge_requests'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import CommentForm from '~/notes/components/comment_form.vue'; import CommentTypeDropdown from '~/notes/components/comment_type_dropdown.vue'; @@ -490,7 +490,7 @@ describe('issue_comment_form component', () => { await nextTick(); await nextTick(); - expect(createFlash).toHaveBeenCalledWith({ + expect(createAlert).toHaveBeenCalledWith({ message: `Something went wrong while closing the ${type}. Please try again later.`, }); }); @@ -526,7 +526,7 @@ describe('issue_comment_form component', () => { await nextTick(); await nextTick(); - expect(createFlash).toHaveBeenCalledWith({ + expect(createAlert).toHaveBeenCalledWith({ message: `Something went wrong while reopening the ${type}. Please try again later.`, }); }); diff --git a/spec/frontend/operation_settings/components/metrics_settings_spec.js b/spec/frontend/operation_settings/components/metrics_settings_spec.js index 810049220ae..732dfdd42fb 100644 --- a/spec/frontend/operation_settings/components/metrics_settings_spec.js +++ b/spec/frontend/operation_settings/components/metrics_settings_spec.js @@ -2,7 +2,7 @@ import { GlButton, GlLink, GlFormGroup, GlFormInput, GlFormSelect } from '@gitla import { mount, shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; import { TEST_HOST } from 'helpers/test_constants'; -import createFlash from '~/flash'; +import { createAlert } from '~/flash'; import axios from '~/lib/utils/axios_utils'; import { refreshCurrentPage } from '~/lib/utils/url_utility'; import { timezones } from '~/monitoring/format_date'; @@ -52,7 +52,7 @@ describe('operation settings external dashboard component', () => { } axios.patch.mockReset(); refreshCurrentPage.mockReset(); - createFlash.mockReset(); + createAlert.mockReset(); }); it('renders header text', () => { @@ -208,7 +208,7 @@ describe('operation settings external dashboard component', () => { await nextTick(); await jest.runAllTicks(); - expect(createFlash).toHaveBeenCalledWith({ + expect(createAlert).toHaveBeenCalledWith({ message: `There was an error saving your changes. ${message}`, }); }); diff --git a/spec/lib/gitlab/github_import/markdown_text_spec.rb b/spec/lib/gitlab/github_import/markdown_text_spec.rb index 1da6bb06403..5bca431a110 100644 --- a/spec/lib/gitlab/github_import/markdown_text_spec.rb +++ b/spec/lib/gitlab/github_import/markdown_text_spec.rb @@ -70,7 +70,7 @@ RSpec.describe Gitlab::GithubImport::MarkdownText do let(:doc_extension) { described_class::DOC_TYPES.sample } let(:doc_attachment) do "[some-doc](https://github.com/nickname/public-test-repo/"\ - "files/9020437/git-cheat-sheet.#{doc_extension})" + "files/9020437/sample.#{doc_extension})" end let(:text) do diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 1fce1f97dcb..670a6237788 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -1839,6 +1839,12 @@ RSpec.describe Note do let(:note) { create(:note, :system, :on_issue, note: original_note_body) } it { is_expected.to eq(expected_text_replacement) } + + context 'context when note and cache are null (happens in bulk insert)' do + let(:note) { build(:note, :system, :on_issue, note: nil, note_html: nil).tap { |note| note.save!(validate: false) } } + + it { is_expected.to be_in([nil, '']) } + end end end end @@ -1868,7 +1874,7 @@ RSpec.describe Note do let(:expected_text_replacement) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the checklist item <strong>task 1</strong> as completed</p>' } before do - note.update_columns(note_html: unchanged_note_body) + note.update_columns(note_html: unchanged_note_body) unless note.note.nil? end end @@ -1878,7 +1884,7 @@ RSpec.describe Note do let(:expected_text_replacement) { '<p data-sourcepos="1:1-1:48" dir="auto">marked the checklist item <strong>task 1</strong> as incomplete</p>' } before do - note.update_columns(note_html: unchanged_note_body) + note.update_columns(note_html: unchanged_note_body) unless note.note.nil? end end end diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb index fb88dbb4212..0edb04224a3 100644 --- a/spec/models/packages/package_spec.rb +++ b/spec/models/packages/package_spec.rb @@ -904,6 +904,14 @@ RSpec.describe Packages::Package, type: :model do it { is_expected.to match_array([pypi_package]) } end + describe '.with_case_insensitive_version' do + let_it_be(:nuget_package) { create(:nuget_package, version: '1.0.0-ABC') } + + subject { described_class.with_case_insensitive_version('1.0.0-abC') } + + it { is_expected.to match_array([nuget_package]) } + end + context 'status scopes' do let_it_be(:default_package) { create(:maven_package, :default) } let_it_be(:hidden_package) { create(:maven_package, :hidden) } diff --git a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb index 6d4dcf28108..b020479a78e 100644 --- a/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb +++ b/spec/services/ci/pipeline_artifacts/coverage_report_service_spec.rb @@ -52,28 +52,12 @@ RSpec.describe Ci::PipelineArtifacts::CoverageReportService do it_behaves_like 'creating or updating a pipeline coverage report' - context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do - it "artifact has pipeline's locked status" do - subject - - artifact = Ci::PipelineArtifact.first - - expect(artifact.locked).to eq(pipeline.locked) - end - end + it "artifact has pipeline's locked status" do + subject - context 'when ci_update_unlocked_pipeline_artifacts is disabled' do - before do - stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false) - end - - it 'artifact has unknown locked status' do - subject + artifact = Ci::PipelineArtifact.first - artifact = Ci::PipelineArtifact.first - - expect(artifact.locked).to eq('unknown') - end + expect(artifact.locked).to eq(pipeline.locked) end end diff --git a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb index 75233248113..5d854b61f14 100644 --- a/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb +++ b/spec/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service_spec.rb @@ -51,28 +51,12 @@ RSpec.describe ::Ci::PipelineArtifacts::CreateCodeQualityMrDiffReportService do end end - context 'when ci_update_unlocked_pipeline_artifacts feature flag is enabled' do - it "artifact has pipeline's locked status" do - subject - - artifact = Ci::PipelineArtifact.first - - expect(artifact.locked).to eq(head_pipeline.locked) - end - end - - context 'when ci_update_unlocked_pipeline_artifacts is disabled' do - before do - stub_feature_flags(ci_update_unlocked_pipeline_artifacts: false) - end - - it 'artifact has unknown locked status' do - subject + it "artifact has pipeline's locked status" do + subject - artifact = Ci::PipelineArtifact.first + artifact = Ci::PipelineArtifact.first - expect(artifact.locked).to eq('unknown') - end + expect(artifact.locked).to eq(head_pipeline.locked) end it 'does not persist the same artifact twice' do diff --git a/spec/services/ci/unlock_artifacts_service_spec.rb b/spec/services/ci/unlock_artifacts_service_spec.rb index 776019f03f8..f21afc7fe9e 100644 --- a/spec/services/ci/unlock_artifacts_service_spec.rb +++ b/spec/services/ci/unlock_artifacts_service_spec.rb @@ -5,15 +5,11 @@ require 'spec_helper' RSpec.describe Ci::UnlockArtifactsService do using RSpec::Parameterized::TableSyntax - where(:tag, :ci_update_unlocked_job_artifacts, :ci_update_unlocked_pipeline_artifacts) do - false | false | false - false | true | false - true | false | false - true | true | false - false | false | true - false | true | true - true | false | true - true | true | true + where(:tag, :ci_update_unlocked_job_artifacts) do + false | false + false | true + true | false + true | true end with_them do @@ -35,8 +31,7 @@ RSpec.describe Ci::UnlockArtifactsService do before do stub_const("#{described_class}::BATCH_SIZE", 1) - stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts, - ci_update_unlocked_pipeline_artifacts: ci_update_unlocked_pipeline_artifacts) + stub_feature_flags(ci_update_unlocked_job_artifacts: ci_update_unlocked_job_artifacts) end describe '#execute' do @@ -80,7 +75,7 @@ RSpec.describe Ci::UnlockArtifactsService do end it 'unlocks pipeline artifact records' do - if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts + if ci_update_unlocked_job_artifacts expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1) else expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count } @@ -122,7 +117,7 @@ RSpec.describe Ci::UnlockArtifactsService do end it 'unlocks pipeline artifact records' do - if ci_update_unlocked_job_artifacts && ci_update_unlocked_pipeline_artifacts + if ci_update_unlocked_job_artifacts expect { execute }.to change { ::Ci::PipelineArtifact.artifact_unlocked.count }.from(0).to(1) else expect { execute }.not_to change { ::Ci::PipelineArtifact.artifact_unlocked.count } diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb index a595680ad02..9bb09dce289 100644 --- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb +++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb @@ -288,7 +288,7 @@ RSpec.shared_examples 'wiki controller actions' do context 'when page is a file' do include WikiHelpers - where(:file_name) { ['dk.png', 'unsanitized.svg', 'git-cheat-sheet.pdf'] } + where(:file_name) { ['dk.png', 'unsanitized.svg', 'sample.pdf'] } with_them do let(:id) { upload_file_to_wiki(wiki, user, file_name) } diff --git a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb index 0a5ad5a59c0..7737f8a73c5 100644 --- a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb +++ b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb @@ -77,9 +77,9 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false| end if drop - find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf')) + find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf')) else - attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'), make_visible: true) + attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'sample.pdf'), make_visible: true) end page.within('#modal-upload-blob') do @@ -90,7 +90,7 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false| wait_for_all_requests - visit(project_blob_path(project, 'upload_image/git-cheat-sheet.pdf')) + visit(project_blob_path(project, 'upload_image/sample.pdf')) expect(page).to have_css('.js-pdf-viewer') end diff --git a/workhorse/go.mod b/workhorse/go.mod index 768dc1a4e59..6e9a5097bd7 100644 --- a/workhorse/go.mod +++ b/workhorse/go.mod @@ -6,7 +6,7 @@ require ( github.com/Azure/azure-storage-blob-go v0.14.0 github.com/BurntSushi/toml v1.2.0 github.com/FZambia/sentinel v1.1.1 - github.com/alecthomas/chroma/v2 v2.2.0 + github.com/alecthomas/chroma/v2 v2.3.0 github.com/aws/aws-sdk-go v1.43.31 github.com/disintegration/imaging v1.6.2 github.com/getsentry/raven-go v0.2.0 diff --git a/workhorse/go.sum b/workhorse/go.sum index 994d002e2e7..74df1aed336 100644 --- a/workhorse/go.sum +++ b/workhorse/go.sum @@ -156,10 +156,10 @@ github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrU github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY= -github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs= -github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae h1:zzGwJfFlFGD94CyyYwCJeSuD32Gj9GTaSi5y9hoVzdY= -github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= +github.com/alecthomas/chroma/v2 v2.3.0 h1:83xfxrnjv8eK+Cf8qZDzNo3PPF9IbTWHs7z28GY6D0U= +github.com/alecthomas/chroma/v2 v2.3.0/go.mod h1:mZxeWZlxP2Dy+/8cBob2PYd8O2DwNAzave5AY7A2eQw= +github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= +github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= |