diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-25 15:09:24 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-25 15:09:24 +0300 |
commit | 7a3aca2b5b3bfdebbd7bb6353d5bdcdc422670da (patch) | |
tree | d3431811140c48c2ed31f2e8fdc90504f3bd4344 | |
parent | 9c3a433b3176e895a23cf0f4b87411b44e264397 (diff) |
Add latest changes from gitlab-org/gitlab@master
53 files changed, 711 insertions, 580 deletions
diff --git a/.rubocop_todo/rspec/file_path.yml b/.rubocop_todo/rspec/file_path.yml index ea193948909..06832184c04 100644 --- a/.rubocop_todo/rspec/file_path.yml +++ b/.rubocop_todo/rspec/file_path.yml @@ -24,6 +24,7 @@ RSpec/FilePath: - 'spec/benchmarks/banzai_benchmark.rb' - 'spec/docs_screenshots/container_registry_docs.rb' - 'spec/docs_screenshots/wiki_docs.rb' + - 'spec/initializers/gitlab_http_spec.rb' - 'spec/lib/error_tracking/sentry_client/event_spec.rb' - 'spec/lib/gitlab/import_export/import_export_spec.rb' - 'spec/lib/gitlab/mail_room/mail_room_spec.rb' diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index dd2a5654d2c..6abc624dd52 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0fed39f4d44b51ff5dfa20e6dc4a1a940a5a6b38 +531d5205acec6b5160d862ea687c157c07cbcff1 @@ -253,7 +253,7 @@ gem 'rainbow', '~> 3.0' gem 'ruby-progressbar', '~> 1.10' # Linear-time regex library for untrusted regular expressions -gem 're2', '2.1.2' +gem 're2', '2.1.3' # Misc @@ -349,6 +349,7 @@ gem 'sentry-sidekiq', '~> 5.8.0' gem 'pg_query', '~> 4.2.3' gem 'gitlab-schema-validation', path: 'gems/gitlab-schema-validation' +gem 'gitlab-http', path: 'gems/gitlab-http' gem 'premailer-rails', '~> 1.10.3' diff --git a/Gemfile.checksum b/Gemfile.checksum index 0e3094d3570..b8a244ef785 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -490,16 +490,16 @@ {"name":"rbtree","version":"0.4.6","platform":"ruby","checksum":"14eea4469b24fd2472542e5f3eb105d6344c8ccf36f0b56d55fdcfeb4e0f10fc"}, {"name":"rchardet","version":"1.8.0","platform":"ruby","checksum":"693acd5253d5ade81a51940697955f6dd4bb2f0d245bda76a8e23deec70a52c7"}, {"name":"rdoc","version":"6.3.2","platform":"ruby","checksum":"def4a720235c27d56c176ae73555e647eb04ea58a8bbaa927f8f9f79de7805a6"}, -{"name":"re2","version":"2.1.2","platform":"aarch64-linux","checksum":"dbd87fb2432f17734cfb948d38cb0d138335228d31c4316719c75ac0a976731f"}, -{"name":"re2","version":"2.1.2","platform":"arm-linux","checksum":"4c0d903508bc0d82f27d09c84498e0fdc6ab87ef418bea884d711b85f7fca62f"}, -{"name":"re2","version":"2.1.2","platform":"arm64-darwin","checksum":"39bb8a44a4afbd2d3f2e07d531d223728f7c4b83946bc55e8ce6aae8c2c34579"}, -{"name":"re2","version":"2.1.2","platform":"ruby","checksum":"06bd25bf566dda720cbc607ceecb65ed16871427fbcb3e5239c300ec796fee9c"}, -{"name":"re2","version":"2.1.2","platform":"x64-mingw-ucrt","checksum":"a1ad9cda576dae6020664c7578d7e43d2062ca21e5e945aea125f539944ee713"}, -{"name":"re2","version":"2.1.2","platform":"x64-mingw32","checksum":"804fc9bafc6590e3e75d27d289546d7223b51bf3e46e9d81ee89cf5168c1a9be"}, -{"name":"re2","version":"2.1.2","platform":"x86-linux","checksum":"6a048f8a1511a5481f7a386045e67ecbb221a856d2987b33a231efb5e17250bc"}, -{"name":"re2","version":"2.1.2","platform":"x86-mingw32","checksum":"8e0e9d0f3166ff3000ffa38a05c9e5275ba431f2abce494fa7600033206ce108"}, -{"name":"re2","version":"2.1.2","platform":"x86_64-darwin","checksum":"6b41f328b551173e58eb04320c70295de143b5aeb38c78122aa623a4308bc472"}, -{"name":"re2","version":"2.1.2","platform":"x86_64-linux","checksum":"e082a1db722b7da3adc9e1f9d8681cba80a2d1176c54ae741443965ce277e6af"}, +{"name":"re2","version":"2.1.3","platform":"aarch64-linux","checksum":"27316bb47cfc0f28cfd1626426120e1c55ca8420a64c9e966f8feb1c911eae2a"}, +{"name":"re2","version":"2.1.3","platform":"arm-linux","checksum":"81ffdd76b202f24461b4868abed96c994e2106e57970004b841499da983f688c"}, +{"name":"re2","version":"2.1.3","platform":"arm64-darwin","checksum":"86d553e85779943a353865cbfdd89156c0411b92a1c7fe6abf1024135d53190e"}, +{"name":"re2","version":"2.1.3","platform":"ruby","checksum":"03a30b53002ab66b66fa2d4500c82ec0866020c22e11c23516f660ce43cfae8f"}, +{"name":"re2","version":"2.1.3","platform":"x64-mingw-ucrt","checksum":"be0277c15bef6f38a2f9805aca798de4a31f6319cb1790ff6683112cb89721da"}, +{"name":"re2","version":"2.1.3","platform":"x64-mingw32","checksum":"cadba41d90f2186507c97593084b8f951c9c3ee7ecb2be02f3497aa9c5cdaadb"}, +{"name":"re2","version":"2.1.3","platform":"x86-linux","checksum":"ad54cafdaf40310cf3aab485697b997718c573d6a780f802c3faab7a38119623"}, +{"name":"re2","version":"2.1.3","platform":"x86-mingw32","checksum":"6bfa3c1c119b485375688a9c90c0b8cfc03991495c2e4d50accb6bbcd406c186"}, +{"name":"re2","version":"2.1.3","platform":"x86_64-darwin","checksum":"513b12c5b7536c65e80ddb2a7eee0dbbefea534d6352e9470040016c547f90a5"}, +{"name":"re2","version":"2.1.3","platform":"x86_64-linux","checksum":"73a2e20fc1dc7b2773d2862ec061e545f6820643486c0d69e3ad40de19ce5c0b"}, {"name":"recaptcha","version":"5.12.3","platform":"ruby","checksum":"37d1894add9e70a54d0c6c7f0ecbeedffbfa7d075acfbd4c509818dfdebdb7ee"}, {"name":"recursive-open-struct","version":"1.1.3","platform":"ruby","checksum":"a3538a72552fcebcd0ada657bdff313641a4a5fbc482c08cfb9a65acb1c9de5a"}, {"name":"redcarpet","version":"3.6.0","platform":"ruby","checksum":"8ad1889c0355ff4c47174af14edd06d62f45a326da1da6e8a121d59bdcd2e9e9"}, diff --git a/Gemfile.lock b/Gemfile.lock index d6911ef9114..3823c2528b6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,6 +24,16 @@ PATH typhoeus (~> 1.0, >= 1.0.1) PATH + remote: gems/gitlab-http + specs: + gitlab-http (0.1.0) + activesupport (~> 7.0.6) + httparty (~> 0.21.0) + ipaddress (~> 0.8.3) + nokogiri (~> 1.15.4) + railties (~> 7.0.6) + +PATH remote: gems/gitlab-rspec specs: gitlab-rspec (0.1.0) @@ -1288,7 +1298,7 @@ GEM rbtree (0.4.6) rchardet (1.8.0) rdoc (6.3.2) - re2 (2.1.2) + re2 (2.1.3) mini_portile2 (~> 2.8.4) recaptcha (5.12.3) json @@ -1812,6 +1822,7 @@ DEPENDENCIES gitlab-dangerfiles (~> 4.0.0) gitlab-experiment (~> 0.8.0) gitlab-fog-azure-rm (~> 1.8.0) + gitlab-http! gitlab-labkit (~> 0.34.0) gitlab-license (~> 2.3) gitlab-mail_room (~> 0.0.23) @@ -1954,7 +1965,7 @@ DEPENDENCIES rainbow (~> 3.0) rbtrace (~> 0.4) rdoc (~> 6.3.2) - re2 (= 2.1.2) + re2 (= 2.1.3) recaptcha (~> 5.12) redis (~> 4.8.0) redis-actionpack (~> 5.3.0) diff --git a/app/assets/javascripts/repository/components/commit_info.vue b/app/assets/javascripts/repository/components/commit_info.vue new file mode 100644 index 00000000000..99ec5c78830 --- /dev/null +++ b/app/assets/javascripts/repository/components/commit_info.vue @@ -0,0 +1,116 @@ +<script> +import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui'; +import { __ } from '~/locale'; +import SafeHtml from '~/vue_shared/directives/safe_html'; +import defaultAvatarUrl from 'images/no_avatar.png'; +import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; +import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; +import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue'; +import getRefMixin from '../mixins/get_ref'; + +export default { + components: { + UserAvatarLink, + TimeagoTooltip, + GlButton, + GlLink, + UserAvatarImage, + }, + directives: { + GlTooltip: GlTooltipDirective, + SafeHtml, + }, + mixins: [getRefMixin], + props: { + commit: { + type: Object, + required: true, + }, + }, + data() { + return { showDescription: false }; + }, + computed: { + commitDescription() { + // Strip the newline at the beginning + return this.commit?.descriptionHtml?.replace(/^
/, ''); + }, + }, + methods: { + toggleShowDescription() { + this.showDescription = !this.showDescription; + }, + }, + defaultAvatarUrl, + safeHtmlConfig: { + ADD_TAGS: ['gl-emoji'], + }, + i18n: { + toggleCommitDescription: __('Toggle commit description'), + authored: __('authored'), + }, +}; +</script> + +<template> + <div class="well-segment commit gl-min-h-8 gl-p-5 gl-w-full gl-display-flex"> + <user-avatar-link + v-if="commit.author" + :link-href="commit.author.webPath" + :img-src="commit.author.avatarUrl" + :img-size="32" + class="gl-my-2 gl-mr-4" + /> + <user-avatar-image + v-else + class="gl-my-2 gl-mr-4" + :img-src="commit.authorGravatar || $options.defaultAvatarUrl" + :size="32" + /> + <div + class="commit-detail flex-list gl-display-flex gl-justify-content-space-between gl-align-items-center gl-flex-grow-1 gl-min-w-0" + > + <div class="commit-content" data-qa-selector="commit_content"> + <gl-link + v-safe-html:[$options.safeHtmlConfig]="commit.titleHtml" + :href="commit.webPath" + :class="{ 'gl-font-style-italic': !commit.message }" + class="commit-row-message item-title" + /> + <gl-button + v-if="commit.descriptionHtml" + v-gl-tooltip + :class="{ open: showDescription }" + :title="$options.i18n.toggleCommitDescription" + :aria-label="$options.i18n.toggleCommitDescription" + :selected="showDescription" + class="text-expander gl-vertical-align-bottom!" + icon="ellipsis_h" + @click="toggleShowDescription" + /> + <div class="committer"> + <gl-link + v-if="commit.author" + :href="commit.author.webPath" + class="commit-author-link js-user-link" + > + {{ commit.author.name }}</gl-link + > + <template v-else> + {{ commit.authorName }} + </template> + {{ $options.i18n.authored }} + <timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" /> + </div> + <pre + v-if="commitDescription" + v-safe-html:[$options.safeHtmlConfig]="commitDescription" + :class="{ 'gl-display-block!': showDescription }" + class="commit-row-description gl-mb-3 gl-white-space-pre-line" + ></pre> + </div> + <div class="gl-flex-grow-1"></div> + <slot></slot> + </div> + </div> +</template> diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue index 12edeeb0d2f..ff6acd5239d 100644 --- a/app/assets/javascripts/repository/components/last_commit.vue +++ b/app/assets/javascripts/repository/components/last_commit.vue @@ -1,32 +1,26 @@ <script> -import { GlTooltipDirective, GlLink, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui'; +import { GlTooltipDirective, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui'; import SafeHtml from '~/vue_shared/directives/safe_html'; -import defaultAvatarUrl from 'images/no_avatar.png'; import pathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql'; import { sprintf, s__ } from '~/locale'; import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; -import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; -import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; -import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue'; import SignatureBadge from '~/commit/components/signature_badge.vue'; import getRefMixin from '../mixins/get_ref'; import projectPathQuery from '../queries/project_path.query.graphql'; import eventHub from '../event_hub'; import { FORK_UPDATED_EVENT } from '../constants'; +import CommitInfo from './commit_info.vue'; export default { components: { - UserAvatarLink, - TimeagoTooltip, + CommitInfo, ClipboardButton, - GlButton, - GlButtonGroup, - GlLink, - GlLoadingIcon, - UserAvatarImage, SignatureBadge, CiBadgeLink, + GlButtonGroup, + GlButton, + GlLoadingIcon, }, directives: { GlTooltip: GlTooltipDirective, @@ -80,13 +74,12 @@ export default { return { projectPath: '', commit: null, - showDescription: false, }; }, computed: { statusTitle() { return sprintf(s__('PipelineStatusTooltip|Pipeline: %{ciStatus}'), { - ciStatus: this.commit.pipeline.detailedStatus.text, + ciStatus: this.commit?.pipeline?.detailedStatus?.text, }); }, isLoading() { @@ -95,10 +88,6 @@ export default { showCommitId() { return this.commit?.sha?.substr(0, 8); }, - commitDescription() { - // Strip the newline at the beginning - return this.commit?.descriptionHtml?.replace(/^
/, ''); - }, }, watch: { currentPath() { @@ -112,112 +101,40 @@ export default { eventHub.$off(FORK_UPDATED_EVENT, this.refetchLastCommit); }, methods: { - toggleShowDescription() { - this.showDescription = !this.showDescription; - }, refetchLastCommit() { this.$apollo.queries.commit.refetch(); }, }, - defaultAvatarUrl, - safeHtmlConfig: { - ADD_TAGS: ['gl-emoji'], - }, }; </script> <template> - <div class="well-segment commit gl-p-5 gl-w-full gl-display-flex"> - <gl-loading-icon v-if="isLoading" size="lg" color="dark" class="m-auto" /> - <template v-else-if="commit"> - <user-avatar-link - v-if="commit.author" - :link-href="commit.author.webPath" - :img-src="commit.author.avatarUrl" - :img-size="32" - class="gl-my-2 gl-mr-4" - /> - <user-avatar-image - v-else - class="gl-my-2 gl-mr-4" - :img-src="commit.authorGravatar || $options.defaultAvatarUrl" - :size="32" - /> - <div - class="commit-detail flex-list gl-display-flex gl-justify-content-space-between gl-align-items-center gl-flex-grow-1 gl-min-w-0" - > - <div class="commit-content" data-qa-selector="commit_content"> - <gl-link - v-safe-html:[$options.safeHtmlConfig]="commit.titleHtml" - :href="commit.webPath" - :class="{ 'font-italic': !commit.message }" - class="commit-row-message item-title" - /> - <gl-button - v-if="commit.descriptionHtml" - v-gl-tooltip - :class="{ open: showDescription }" - :title="__('Toggle commit description')" - :aria-label="__('Toggle commit description')" - :selected="showDescription" - class="text-expander gl-vertical-align-bottom!" - icon="ellipsis_h" - @click="toggleShowDescription" - /> - <div class="committer"> - <gl-link - v-if="commit.author" - :href="commit.author.webPath" - class="commit-author-link js-user-link" - > - {{ commit.author.name }}</gl-link - > - <template v-else> - {{ commit.authorName }} - </template> - {{ s__('LastCommit|authored') }} - <timeago-tooltip :time="commit.authoredDate" tooltip-placement="bottom" /> - </div> - <pre - v-if="commitDescription" - v-safe-html:[$options.safeHtmlConfig]="commitDescription" - :class="{ 'd-block': showDescription }" - class="commit-row-description gl-mb-3 gl-white-space-pre-line" - ></pre> - </div> - <div class="gl-flex-grow-1"></div> - <div - class="commit-actions gl-display-flex gl-flex-align gl-align-items-center gl-flex-direction-row" - > - <signature-badge v-if="commit.signature" :signature="commit.signature" /> - <div v-if="commit.pipeline" class="ci-status-link"> - <ci-badge-link - :status="commit.pipeline.detailedStatus" - :details-path="commit.pipeline.detailedStatus.detailsPath" - :aria-label="statusTitle" - size="lg" - :show-text="false" - class="js-commit-pipeline" - /> - </div> - <gl-button-group class="gl-ml-4 js-commit-sha-group"> - <gl-button label class="gl-font-monospace" data-testid="last-commit-id-label">{{ - showCommitId - }}</gl-button> - <clipboard-button - :text="commit.sha" - :title="__('Copy commit SHA')" - class="input-group-text" - /> - </gl-button-group> - </div> + <gl-loading-icon v-if="isLoading" size="lg" color="dark" class="m-auto" /> + <commit-info v-else-if="commit" :commit="commit"> + <div + class="commit-actions gl-display-flex gl-flex-align gl-align-items-center gl-flex-direction-row" + > + <signature-badge v-if="commit.signature" :signature="commit.signature" /> + <div v-if="commit.pipeline" class="ci-status-link"> + <ci-badge-link + :status="commit.pipeline.detailedStatus" + :details-path="commit.pipeline.detailedStatus.detailsPath" + :aria-label="statusTitle" + size="lg" + :show-text="false" + class="js-commit-pipeline" + /> </div> - </template> - </div> + <gl-button-group class="gl-ml-4 js-commit-sha-group"> + <gl-button label class="gl-font-monospace" data-testid="last-commit-id-label">{{ + showCommitId + }}</gl-button> + <clipboard-button + :text="commit.sha" + :title="__('Copy commit SHA')" + class="input-group-text" + /> + </gl-button-group> + </div> + </commit-info> </template> - -<style scoped> -.commit { - min-height: 4.75rem; -} -</style> diff --git a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue index 038fb3ea61c..bd15dfe29a6 100644 --- a/app/assets/javascripts/super_sidebar/components/super_sidebar.vue +++ b/app/assets/javascripts/super_sidebar/components/super_sidebar.vue @@ -163,7 +163,7 @@ export default { <div class="gl-flex-grow-1 gl-overflow-auto" data-testid="nav-container"> <div id="super-sidebar-context-header" - class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-sm super-sidebar-context-header" + class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header" > {{ sidebarData.current_context_header }} </div> diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 5a90e246499..8ed24257d61 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -51,6 +51,7 @@ module ApplicationSettingImplementation container_registry_token_expire_delay: 5, container_registry_vendor: '', container_registry_version: '', + container_registry_db_enabled: false, custom_http_clone_url_root: nil, decompress_archive_file_timeout: 210, default_artifacts_expire_in: '30 days', diff --git a/app/models/clusters/agent_token.rb b/app/models/clusters/agent_token.rb index f4c497a42cc..e2754db73b9 100644 --- a/app/models/clusters/agent_token.rb +++ b/app/models/clusters/agent_token.rb @@ -33,6 +33,10 @@ module Clusters revoked: 1 } + def revoke! + update(status: :revoked) + end + def to_ability_name :cluster end diff --git a/app/services/clusters/agent_tokens/revoke_service.rb b/app/services/clusters/agent_tokens/revoke_service.rb index 5d89b405969..46873fbbc47 100644 --- a/app/services/clusters/agent_tokens/revoke_service.rb +++ b/app/services/clusters/agent_tokens/revoke_service.rb @@ -13,7 +13,7 @@ module Clusters def execute return error_no_permissions unless current_user.can?(:create_cluster, token.agent.project) - if token.update(status: token.class.statuses[:revoked]) + if token.revoke! log_activity_event(token) ServiceResponse.success diff --git a/app/views/admin/users/_profile.html.haml b/app/views/admin/users/_profile.html.haml index bb89b5baf28..df0a59ccfc3 100644 --- a/app/views/admin/users/_profile.html.haml +++ b/app/views/admin/users/_profile.html.haml @@ -1,4 +1,4 @@ -= render Pajamas::CardComponent.new(body_options: { class: 'gl-py-0' }) do |c| += render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' }, body_options: { class: 'gl-py-0' }) do |c| - c.with_header do = _('Profile') - c.with_body do diff --git a/app/workers/merge_worker.rb b/app/workers/merge_worker.rb index a0594b15e31..29f0c0bbbf4 100644 --- a/app/workers/merge_worker.rb +++ b/app/workers/merge_worker.rb @@ -16,8 +16,6 @@ class MergeWorker # rubocop:disable Scalability/IdempotentWorker deduplicate :until_executed, including_scheduled: true def perform(merge_request_id, current_user_id, params) - params = params.with_indifferent_access - begin current_user = User.find(current_user_id) merge_request = MergeRequest.find(merge_request_id) @@ -25,6 +23,9 @@ class MergeWorker # rubocop:disable Scalability/IdempotentWorker return end + params = params.with_indifferent_access + params[:check_mergeability_retry_lease] = true unless params.has_key?(:check_mergeability_retry_lease) + MergeRequests::MergeService.new(project: merge_request.target_project, current_user: current_user, params: params) .execute(merge_request) end diff --git a/config/initializers/active_record_table_definition.rb b/config/initializers/active_record_table_definition.rb index 2e571ec7525..3c6311f034f 100644 --- a/config/initializers/active_record_table_definition.rb +++ b/config/initializers/active_record_table_definition.rb @@ -36,13 +36,6 @@ module ActiveRecord def aliased_types(name, fallback) fallback end - - # Adds a compatible_table_definition method that - # returns the value passed in so that all of the - # versioned Migrations can always return super. - def compatible_table_definition(table) - table - end end end end diff --git a/config/initializers/gitlab_http.rb b/config/initializers/gitlab_http.rb new file mode 100644 index 00000000000..8a84313a7fb --- /dev/null +++ b/config/initializers/gitlab_http.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +# When including this gem, we also initialize the patch / override classes in the gem. +require 'gitlab-http' + +Gitlab::HTTP_V2.configure do |config| + config.allowed_internal_uris = [ + URI::HTTP.build( + scheme: Gitlab.config.gitlab.protocol, + host: Gitlab.config.gitlab.host, + port: Gitlab.config.gitlab.port + ), + URI::Generic.build( + scheme: 'ssh', + host: Gitlab.config.gitlab_shell.ssh_host, + port: Gitlab.config.gitlab_shell.ssh_port + ) + ] + + config.log_exception_proc = ->(exception, extra_info) do + Gitlab::ErrorTracking.log_exception(exception, extra_info) + end + config.silent_mode_log_info_proc = ->(message, http_method) do + Gitlab::SilentMode.log_info(message: message, outbound_http_request_method: http_method) + end +end diff --git a/config/initializers/http_hostname_override.rb b/config/initializers/http_hostname_override.rb deleted file mode 100644 index 3d840cd3251..00000000000 --- a/config/initializers/http_hostname_override.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -# This override allows passing `@hostname_override` to the SNI protocol, -# which is used to lookup the correct SSL certificate in the -# request handshake process. -# -# Given we've forced the HTTP request to be sent to the resolved -# IP address in a few scenarios (e.g.: `Gitlab::HTTP` through -# `Gitlab::UrlBlocker.validate!`), we need to provide the _original_ -# hostname via SNI in order to have a clean connection setup. -# -# This is ultimately needed in order to avoid DNS rebinding attacks -# through HTTP requests. -# -class OpenSSL::SSL::SSLContext - attr_accessor :hostname_override -end - -class OpenSSL::SSL::SSLSocket - module HostnameOverride - # rubocop: disable Gitlab/ModuleWithInstanceVariables - def hostname=(hostname) - super(@context.hostname_override || hostname) - end - - def post_connection_check(hostname) - super(@context.hostname_override || hostname) - end - # rubocop: enable Gitlab/ModuleWithInstanceVariables - end - - prepend HostnameOverride -end - -class Net::HTTP - attr_accessor :hostname_override - - SSL_IVNAMES << :@hostname_override - SSL_ATTRIBUTES << :hostname_override - - module HostnameOverride - def addr_port - return super unless hostname_override - - addr = hostname_override - default_port = use_ssl? ? Net::HTTP.https_default_port : Net::HTTP.http_default_port - default_port == port ? addr : "#{addr}:#{port}" - end - end - - prepend HostnameOverride -end diff --git a/config/initializers/net_http_patch.rb b/config/initializers/net_http_patch.rb deleted file mode 100644 index 8231423e1a5..00000000000 --- a/config/initializers/net_http_patch.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -# Monkey patch Net::HTTP to fix missing URL decoding for username and password in proxy settings -# -# See proposed upstream fix https://github.com/ruby/net-http/pull/5 -# See Ruby-lang issue https://bugs.ruby-lang.org/issues/17542 -# See issue on GitLab https://gitlab.com/gitlab-org/gitlab/-/issues/289836 - -require 'net/http' - -# This file can be removed once Ruby 3.0 is no longer supported: -# https://gitlab.com/gitlab-org/gitlab/-/issues/396223 -return if Gem::Version.new(Net::HTTP::VERSION) >= Gem::Version.new('0.2.0') - -module Net - class HTTP < Protocol - def proxy_user - if environment_variable_is_multiuser_safe? && @proxy_from_env - user = proxy_uri&.user - CGI.unescape(user) unless user.nil? - else - @proxy_user - end - end - - def proxy_pass - if environment_variable_is_multiuser_safe? && @proxy_from_env - pass = proxy_uri&.password - CGI.unescape(pass) unless pass.nil? - else - @proxy_pass - end - end - - def environment_variable_is_multiuser_safe? - ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE - end - end -end diff --git a/config/initializers/net_http_response_patch.rb b/config/initializers/net_http_response_patch.rb deleted file mode 100644 index 4f3eaeec24a..00000000000 --- a/config/initializers/net_http_response_patch.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -module Net - class HTTPResponse - # rubocop: disable Cop/LineBreakAfterGuardClauses - # rubocop: disable Cop/LineBreakAroundConditionalBlock - # rubocop: disable Layout/EmptyLineAfterGuardClause - # rubocop: disable Style/AndOr - # rubocop: disable Style/CharacterLiteral - # rubocop: disable Style/InfiniteLoop - - # Original method: - # https://github.com/ruby/ruby/blob/v2_7_5/lib/net/http/response.rb#L54-L69 - # - # Our changes: - # - Pass along the `start_time` to `Gitlab::BufferedIo`, so we can raise a timeout - # if reading the headers takes too long. - # - Limit the regexes to avoid ReDoS attacks. - def self.each_response_header(sock) - start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - key = value = nil - while true - line = sock.is_a?(Gitlab::BufferedIo) ? sock.readuntil("\n", true, start_time) : sock.readuntil("\n", true) - line = line.sub(/\s{0,10}\z/, '') - break if line.empty? - if line[0] == ?\s or line[0] == ?\t and value - # rubocop:disable Gitlab/NoCodeCoverageComment - # :nocov: - value << ' ' unless value.empty? - value << line.strip - # :nocov: - # rubocop:enable Gitlab/NoCodeCoverageComment - else - yield key, value if key - key, value = line.strip.split(/\s{0,10}:\s{0,10}/, 2) - raise Net::HTTPBadResponse, 'wrong header line format' if value.nil? - end - end - yield key, value if key - end - # rubocop: enable Cop/LineBreakAfterGuardClauses - # rubocop: enable Cop/LineBreakAroundConditionalBlock - # rubocop: enable Layout/EmptyLineAfterGuardClause - # rubocop: enable Style/AndOr - # rubocop: enable Style/CharacterLiteral - # rubocop: enable Style/InfiniteLoop - end -end diff --git a/db/migrate/20221206211814_add_authorized_scopes_to_slack_integration.rb b/db/migrate/20221206211814_add_authorized_scopes_to_slack_integration.rb index 40abf087dfe..94d553fdab5 100644 --- a/db/migrate/20221206211814_add_authorized_scopes_to_slack_integration.rb +++ b/db/migrate/20221206211814_add_authorized_scopes_to_slack_integration.rb @@ -9,7 +9,7 @@ class AddAuthorizedScopesToSlackIntegration < Gitlab::Database::Migration[2.1] end create_table :slack_integrations_scopes do |t| - references :slack_api_scope, + t.references :slack_api_scope, null: false, index: false, # See composite index foreign_key: { @@ -17,7 +17,7 @@ class AddAuthorizedScopesToSlackIntegration < Gitlab::Database::Migration[2.1] on_delete: :cascade } - references :slack_integration, + t.references :slack_integration, null: false, index: false, # see composite index foreign_key: { diff --git a/db/migrate/20230919123305_add_container_registry_db_enabled_to_application_settings.rb b/db/migrate/20230919123305_add_container_registry_db_enabled_to_application_settings.rb new file mode 100644 index 00000000000..861294054e8 --- /dev/null +++ b/db/migrate/20230919123305_add_container_registry_db_enabled_to_application_settings.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddContainerRegistryDbEnabledToApplicationSettings < Gitlab::Database::Migration[2.1] + enable_lock_retries! + + def change + add_column :application_settings, :container_registry_db_enabled, :boolean, null: false, default: false + end +end diff --git a/db/migrate/20230920153321_add_last_assigned_users_refreshed_at_to_subscription_add_on_purchases.rb b/db/migrate/20230920153321_add_last_assigned_users_refreshed_at_to_subscription_add_on_purchases.rb new file mode 100644 index 00000000000..7f347e55031 --- /dev/null +++ b/db/migrate/20230920153321_add_last_assigned_users_refreshed_at_to_subscription_add_on_purchases.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddLastAssignedUsersRefreshedAtToSubscriptionAddOnPurchases < Gitlab::Database::Migration[2.1] + enable_lock_retries! + + def change + add_column(:subscription_add_on_purchases, :last_assigned_users_refreshed_at, :datetime_with_timezone) + end +end diff --git a/db/post_migrate/20230918084159_drop_columns_from_geo_node_status_table.rb b/db/post_migrate/20230918084159_drop_columns_from_geo_node_status_table.rb new file mode 100644 index 00000000000..54941552ef9 --- /dev/null +++ b/db/post_migrate/20230918084159_drop_columns_from_geo_node_status_table.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +class DropColumnsFromGeoNodeStatusTable < Gitlab::Database::Migration[2.1] + enable_lock_retries! + + def up + remove_columns :geo_node_statuses, + :wikis_checksum_failed_count, + :wikis_checksum_mismatch_count, + :wikis_checksummed_count, + :wikis_failed_count, + :wikis_retrying_verification_count, + :wikis_synced_count, + :wikis_verification_failed_count, + :wikis_verified_count, + :design_repositories_count, + :design_repositories_synced_count, + :design_repositories_failed_count, + :design_repositories_registry_count + end + + def down + change_table(:geo_node_statuses) do |t| + t.integer :wikis_checksum_failed_count + t.integer :wikis_checksum_mismatch_count + t.integer :wikis_checksummed_count + t.integer :wikis_failed_count + t.integer :wikis_retrying_verification_count + t.integer :wikis_synced_count + t.integer :wikis_verification_failed_count + t.integer :wikis_verified_count + t.integer :design_repositories_count + t.integer :design_repositories_synced_count + t.integer :design_repositories_failed_count + t.integer :design_repositories_registry_count + end + end +end diff --git a/db/schema_migrations/20230918084159 b/db/schema_migrations/20230918084159 new file mode 100644 index 00000000000..c436c247702 --- /dev/null +++ b/db/schema_migrations/20230918084159 @@ -0,0 +1 @@ +0e31f2b685b3d229816f7e330b54cf5cafb7abb71aa4489d88af768dfb3629fc
\ No newline at end of file diff --git a/db/schema_migrations/20230919123305 b/db/schema_migrations/20230919123305 new file mode 100644 index 00000000000..d497f91a90b --- /dev/null +++ b/db/schema_migrations/20230919123305 @@ -0,0 +1 @@ +6f95154ad6b0a9417935a203cb666aea99e06eef22f32c110e1f0e3914c87778
\ No newline at end of file diff --git a/db/schema_migrations/20230920153321 b/db/schema_migrations/20230920153321 new file mode 100644 index 00000000000..edce6fcce4c --- /dev/null +++ b/db/schema_migrations/20230920153321 @@ -0,0 +1 @@ +821bf9cd2c93d34323edc587949a70779acdcc3f7866d7165ef3ebec2127ea0a
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 13e77a40ce5..8b7eae7eb47 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -12052,6 +12052,7 @@ CREATE TABLE application_settings ( decompress_archive_file_timeout integer DEFAULT 210 NOT NULL, search_rate_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL, snowplow_database_collector_hostname text, + container_registry_db_enabled boolean DEFAULT false NOT NULL, CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), CONSTRAINT app_settings_container_registry_pre_import_tags_rate_positive CHECK ((container_registry_pre_import_tags_rate >= (0)::numeric)), CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), @@ -16602,8 +16603,6 @@ CREATE TABLE geo_node_statuses ( replication_slots_count integer, replication_slots_used_count integer, replication_slots_max_retained_wal_bytes bigint, - wikis_synced_count integer, - wikis_failed_count integer, job_artifacts_count integer, job_artifacts_synced_count integer, job_artifacts_failed_count integer, @@ -16611,28 +16610,18 @@ CREATE TABLE geo_node_statuses ( revision character varying, repositories_verified_count integer, repositories_verification_failed_count integer, - wikis_verified_count integer, - wikis_verification_failed_count integer, lfs_objects_synced_missing_on_primary_count integer, job_artifacts_synced_missing_on_primary_count integer, repositories_checksummed_count integer, repositories_checksum_failed_count integer, repositories_checksum_mismatch_count integer, - wikis_checksummed_count integer, - wikis_checksum_failed_count integer, - wikis_checksum_mismatch_count integer, storage_configuration_digest bytea, repositories_retrying_verification_count integer, - wikis_retrying_verification_count integer, projects_count integer, container_repositories_count integer, container_repositories_synced_count integer, container_repositories_failed_count integer, container_repositories_registry_count integer, - design_repositories_count integer, - design_repositories_synced_count integer, - design_repositories_failed_count integer, - design_repositories_registry_count integer, status jsonb DEFAULT '{}'::jsonb NOT NULL ); @@ -23650,6 +23639,7 @@ CREATE TABLE subscription_add_on_purchases ( quantity integer NOT NULL, expires_on date NOT NULL, purchase_xid text NOT NULL, + last_assigned_users_refreshed_at timestamp with time zone, CONSTRAINT check_3313c4d200 CHECK ((char_length(purchase_xid) <= 255)) ); diff --git a/doc/administration/settings/continuous_integration.md b/doc/administration/settings/continuous_integration.md index f0423021e8b..841b6e644eb 100644 --- a/doc/administration/settings/continuous_integration.md +++ b/doc/administration/settings/continuous_integration.md @@ -231,7 +231,8 @@ It is also possible to specify a [custom CI/CD configuration file for a specific ## Set CI/CD limits -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352175) in GitLab 14.10. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352175) in GitLab 14.10. +> - **Maximum number of active pipelines per project** setting [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/368195) in GitLab 16.0. You can configure some [CI/CD limits](../../administration/instance_limits.md#cicd-limits) from the Admin Area: @@ -243,7 +244,6 @@ from the Admin Area: 1. In the **CI/CD limits** section, you can set the following limits: - **Maximum number of jobs in a single pipeline** - **Total number of jobs in currently active pipelines** - - **Maximum number of active pipelines per project** - **Maximum number of pipeline subscriptions to and from a project** - **Maximum number of pipeline schedules** - **Maximum number of DAG dependencies that a job can have** diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md index 2ee7b8ead61..e9d4915da57 100644 --- a/doc/api/job_artifacts.md +++ b/doc/api/job_artifacts.md @@ -315,9 +315,20 @@ If the artifacts were deleted successfully, a response with status `204 No Conte > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223793) in GitLab 14.7 [with a flag](../administration/feature_flags.md) named `bulk_expire_project_artifacts`. Enabled by default on GitLab self-managed. Enabled on GitLab.com. > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/350609) in GitLab 14.10. -Delete artifacts of a project that can be deleted. +Delete artifacts eligible for deletion in a project. By default, artifacts from +[the most recent successful pipeline of each ref](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs). +are not deleted. -By default, [artifacts from the most recent successful pipeline of each ref are kept](../ci/jobs/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs). +Requests to this endpoint set the expiry of all artifacts that +can be deleted to the current time. The files are then deleted from the system as part +of the regular cleanup of expired job artifacts. Job logs are never deleted. + +The regular cleanup occurs asynchronously on a schedule, so there might be a short delay +before artifacts are deleted. + +Prerequisite: + +- You must have at least the Maintainer role for the project. ```plaintext DELETE /projects/:id/artifacts @@ -333,8 +344,4 @@ Example request: curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/artifacts" ``` -NOTE: -At least Maintainer role is required to delete artifacts. - -Schedules a worker to update to the current time the expiry of all artifacts that can be deleted. A response with status `202 Accepted` is returned. diff --git a/gems/gitlab-http/lib/net_http/response_patch.rb b/gems/gitlab-http/lib/net_http/response_patch.rb index e5477a31318..303d629b32e 100644 --- a/gems/gitlab-http/lib/net_http/response_patch.rb +++ b/gems/gitlab-http/lib/net_http/response_patch.rb @@ -20,11 +20,12 @@ module Net start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) key = value = nil while true - line = if sock.is_a?(Gitlab::HTTP_V2::BufferedIo) - sock.readuntil("\n", true, start_time) - else - sock.readuntil("\n", true) - end + uses_buffered_io = sock.is_a?(Gitlab::HTTP_V2::BufferedIo) + + # TODO: Gitlab::BufferedIo is temporarily used for an easy migration. + uses_buffered_io ||= sock.is_a?(Gitlab::BufferedIo) if defined?(Gitlab::BufferedIo) + + line = uses_buffered_io ? sock.readuntil("\n", true, start_time) : sock.readuntil("\n", true) line = line.sub(/\s{0,10}\z/, '') break if line.empty? if line[0] == ?\s or line[0] == ?\t and value diff --git a/gems/gitlab-http/spec/gitlab/http_v2/net_http_patch_spec.rb b/gems/gitlab-http/spec/gitlab/http_v2/net_http_patch_spec.rb index b82646fb365..f34b0d98403 100644 --- a/gems/gitlab-http/spec/gitlab/http_v2/net_http_patch_spec.rb +++ b/gems/gitlab-http/spec/gitlab/http_v2/net_http_patch_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' require 'net/http' -RSpec.describe 'Net::HTTP patch proxy user and password encoding' do +RSpec.describe 'Net::HTTP patch proxy user and password encoding', feature_category: :shared do let(:net_http) { Net::HTTP.new('hostname.example') } before do diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb index 4278510e999..bfaba5c4d7a 100644 --- a/lib/api/concerns/packages/npm_endpoints.rb +++ b/lib/api/concerns/packages/npm_endpoints.rb @@ -76,12 +76,14 @@ module API ] failure [ { code: 400, message: 'Bad Request' }, + { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, { code: 404, message: 'Not Found' } ] tags %w[npm_packages] end - route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true + route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true, + authenticate_non_public: true get 'dist-tags', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do package_name = params[:package_name] @@ -186,6 +188,7 @@ module API ] failure [ { code: 400, message: 'Bad Request' }, + { code: 401, message: 'Unauthorized' }, { code: 403, message: 'Forbidden' }, { code: 404, message: 'Not Found' } ] @@ -194,7 +197,8 @@ module API params do use :package_name end - route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true + route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true, + authenticate_non_public: true get '*package_name', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do package_name = params[:package_name] available_packages = @@ -224,9 +228,7 @@ module API ).execute if available_packages.any? && available_packages_to_user.empty? - forbidden! if current_user - - not_found!('Packages') + current_user ? forbidden! : unauthorized! end available_packages = available_packages_to_user diff --git a/lib/api/helpers/packages/npm.rb b/lib/api/helpers/packages/npm.rb index a80122c5309..ef3da055b19 100644 --- a/lib/api/helpers/packages/npm.rb +++ b/lib/api/helpers/packages/npm.rb @@ -102,8 +102,7 @@ module API def group group = find_group(params[:id]) - not_found!('Group') unless can?(current_user, :read_group, group) - group + check_group_access(group) end strong_memoize_attr :group diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb index b83d67c359d..e2a1b8296f6 100644 --- a/lib/container_registry/client.rb +++ b/lib/container_registry/client.rb @@ -10,6 +10,7 @@ module ContainerRegistry REGISTRY_VERSION_HEADER = 'gitlab-container-registry-version' REGISTRY_FEATURES_HEADER = 'gitlab-container-registry-features' REGISTRY_TAG_DELETE_FEATURE = 'tag_delete' + REGISTRY_DB_ENABLED_HEADER = 'gitlab-container-registry-database-enabled' DEFAULT_TAGS_PAGE_SIZE = 10000 @@ -47,11 +48,13 @@ module ContainerRegistry version = response.headers[REGISTRY_VERSION_HEADER] features = response.headers.fetch(REGISTRY_FEATURES_HEADER, '') + db_enabled = response.headers.fetch(REGISTRY_DB_ENABLED_HEADER, '') { version: version, features: features.split(',').map(&:strip), - vendor: version ? 'gitlab' : 'other' + vendor: version ? 'gitlab' : 'other', + db_enabled: ::Gitlab::Utils.to_boolean(db_enabled, default: false) } end diff --git a/lib/gitlab/database/migration_helpers/v2.rb b/lib/gitlab/database/migration_helpers/v2.rb index 07e22963177..7cfafa1a6a6 100644 --- a/lib/gitlab/database/migration_helpers/v2.rb +++ b/lib/gitlab/database/migration_helpers/v2.rb @@ -43,7 +43,7 @@ module Gitlab end end - t.instance_eval(&block) unless block.nil? + yield t unless block.nil? end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d4277a26485..a53c8f8b10a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -27504,9 +27504,6 @@ msgstr "" msgid "Last year" msgstr "" -msgid "LastCommit|authored" -msgstr "" - msgid "LastPushEvent|You pushed to" msgstr "" @@ -46691,9 +46688,6 @@ msgstr "" msgid "TanukiBot|What is a fork?" msgstr "" -msgid "Targe branch" -msgstr "" - msgid "Target" msgstr "" diff --git a/package.json b/package.json index 9105864d7e5..f612e6d3728 100644 --- a/package.json +++ b/package.json @@ -176,7 +176,7 @@ "mousetrap": "1.6.5", "orderedmap": "^2.1.1", "papaparse": "^5.3.1", - "patch-package": "^6.4.7", + "patch-package": "6.5.1", "pdfjs-dist": "^2.16.105", "pikaday": "^1.8.0", "popper.js": "^1.16.1", diff --git a/patches/@rails+ujs+7.0.6.patch b/patches/@rails+ujs+7.0.8.patch index 65a4eb029b8..65a4eb029b8 100644 --- a/patches/@rails+ujs+7.0.6.patch +++ b/patches/@rails+ujs+7.0.8.patch diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb index 12154cdb728..9d90400f42f 100644 --- a/qa/qa/page/file/shared/commit_message.rb +++ b/qa/qa/page/file/shared/commit_message.rb @@ -14,7 +14,7 @@ module QA element :commit_message_field end - base.view 'app/assets/javascripts/repository/components/last_commit.vue' do + base.view 'app/assets/javascripts/repository/components/commit_info.vue' do element :commit_content end diff --git a/scripts/frontend/postinstall.js b/scripts/frontend/postinstall.js index 50052bb806e..07456ef36c9 100644 --- a/scripts/frontend/postinstall.js +++ b/scripts/frontend/postinstall.js @@ -1,4 +1,4 @@ -const { execSync } = require('child_process'); +const { spawnSync } = require('child_process'); const chalk = require('chalk'); // check that fsevents is available if we're on macOS @@ -24,5 +24,7 @@ console.log(`${chalk.green('success')} Dependency postinstall check passed.`); // Apply any patches to our packages // See https://gitlab.com/gitlab-org/gitlab/-/issues/336138 -execSync('node_modules/.bin/patch-package --error-on-fail'); -console.log(`${chalk.green('success')} Packages successfully patched.`); +process.exitCode = + spawnSync('node_modules/.bin/patch-package', ['--error-on-fail', '--error-on-warn'], { + stdio: ['ignore', 'inherit', 'inherit'], + }).status ?? 1; diff --git a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap index 3f901dc61b8..e48041c1032 100644 --- a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap +++ b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap @@ -1,97 +1,48 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Repository last commit component renders commit widget 1`] = ` -<div - class="commit gl-display-flex gl-p-5 gl-w-full well-segment" +<commit-info-stub + commit="[object Object]" > - <user-avatar-link-stub - class="gl-mr-4 gl-my-2" - imgalt="" - imgcssclasses="" - imgcsswrapperclasses="" - imgsize="32" - imgsrc="https://test.com" - linkhref="/test" - popoveruserid="" - popoverusername="" - tooltipplacement="top" - tooltiptext="" - username="" - /> <div - class="commit-detail flex-list gl-align-items-center gl-display-flex gl-flex-grow-1 gl-justify-content-space-between gl-min-w-0" + class="commit-actions gl-align-items-center gl-display-flex gl-flex-align gl-flex-direction-row" > <div - class="commit-content" - data-qa-selector="commit_content" + class="ci-status-link" > - <gl-link-stub - class="commit-row-message item-title" - href="/commit/123" - > - Commit title - </gl-link-stub> - <div - class="committer" - > - <gl-link-stub - class="commit-author-link js-user-link" - href="/test" - > - Test - </gl-link-stub> - authored - <timeago-tooltip-stub - cssclass="" - datetimeformat="DATE_WITH_TIME_FORMAT" - time="2019-01-01" - tooltipplacement="bottom" - /> - </div> + <ci-badge-link-stub + aria-label="Pipeline: failed" + class="js-commit-pipeline" + details-path="https://test.com/pipeline" + size="lg" + status="[object Object]" + /> </div> - <div - class="gl-flex-grow-1" - /> - <div - class="commit-actions gl-align-items-center gl-display-flex gl-flex-align gl-flex-direction-row" + <gl-button-group-stub + class="gl-ml-4 js-commit-sha-group" > - <div - class="ci-status-link" - > - <ci-badge-link-stub - aria-label="Pipeline: failed" - class="js-commit-pipeline" - details-path="https://test.com/pipeline" - size="lg" - status="[object Object]" - /> - </div> - <gl-button-group-stub - class="gl-ml-4 js-commit-sha-group" + <gl-button-stub + buttontextclasses="" + category="primary" + class="gl-font-monospace" + data-testid="last-commit-id-label" + icon="" + label="true" + size="medium" + variant="default" > - <gl-button-stub - buttontextclasses="" - category="primary" - class="gl-font-monospace" - data-testid="last-commit-id-label" - icon="" - label="true" - size="medium" - variant="default" - > - 12345678 - </gl-button-stub> - <clipboard-button-stub - category="secondary" - class="input-group-text" - size="medium" - text="123456789" - title="Copy commit SHA" - tooltipplacement="top" - variant="default" - /> - </gl-button-group-stub> - </div> + 12345678 + </gl-button-stub> + <clipboard-button-stub + category="secondary" + class="input-group-text" + size="medium" + text="123456789" + title="Copy commit SHA" + tooltipplacement="top" + variant="default" + /> + </gl-button-group-stub> </div> -</div> +</commit-info-stub> `; diff --git a/spec/frontend/repository/components/commit_info_spec.js b/spec/frontend/repository/components/commit_info_spec.js new file mode 100644 index 00000000000..34e941aa858 --- /dev/null +++ b/spec/frontend/repository/components/commit_info_spec.js @@ -0,0 +1,87 @@ +import { nextTick } from 'vue'; +import { GlButton } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import CommitInfo from '~/repository/components/commit_info.vue'; +import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; + +let wrapper; +const commit = { + title: 'Commit title', + titleHtml: 'Commit title html', + message: 'Commit message', + authoredDate: '2019-01-01', + authorName: 'Test authorName', + author: { name: 'Test name', avatarUrl: 'https://test.com', webPath: '/test' }, +}; + +const findTextExpander = () => wrapper.findComponent(GlButton); +const findUserLink = () => wrapper.findByText(commit.author.name); +const findUserAvatarLink = () => wrapper.findComponent(UserAvatarLink); +const findAuthorName = () => wrapper.findByText(`${commit.authorName} authored`); +const findCommitRowDescription = () => wrapper.find('pre'); +const findTitleHtml = () => wrapper.findByText(commit.titleHtml); + +const createComponent = async ({ commitMock = {} } = {}) => { + wrapper = shallowMountExtended(CommitInfo, { + propsData: { commit: { ...commit, ...commitMock } }, + }); + + await nextTick(); +}; + +describe('Repository last commit component', () => { + it('renders author info', () => { + createComponent(); + + expect(findUserLink().exists()).toBe(true); + expect(findUserAvatarLink().exists()).toBe(true); + }); + + it('hides author component when author does not exist', () => { + createComponent({ commitMock: { author: null } }); + + expect(findUserLink().exists()).toBe(false); + expect(findUserAvatarLink().exists()).toBe(false); + expect(findAuthorName().exists()).toBe(true); + }); + + it('does not render description expander when description is null', () => { + createComponent(); + + expect(findTextExpander().exists()).toBe(false); + expect(findCommitRowDescription().exists()).toBe(false); + }); + + describe('when the description is present', () => { + beforeEach(() => { + createComponent({ commitMock: { descriptionHtml: '
Update ADOPTERS.md' } }); + }); + + it('strips the first newline of the description', () => { + expect(findCommitRowDescription().html()).toBe( + '<pre class="commit-row-description gl-mb-3 gl-white-space-pre-line">Update ADOPTERS.md</pre>', + ); + }); + + it('renders commit description collapsed by default', () => { + expect(findCommitRowDescription().classes('gl-display-block!')).toBe(false); + expect(findTextExpander().classes('open')).toBe(false); + expect(findTextExpander().props('selected')).toBe(false); + }); + + it('expands commit description when clicking expander', async () => { + findTextExpander().vm.$emit('click'); + await nextTick(); + + expect(findCommitRowDescription().classes('gl-display-block!')).toBe(true); + expect(findTextExpander().classes('open')).toBe(true); + expect(findTextExpander().props('selected')).toBe(true); + }); + }); + + it('sets correct CSS class if the commit message is empty', () => { + createComponent({ commitMock: { message: '' } }); + + expect(findTitleHtml().classes()).toContain('gl-font-style-italic'); + }); +}); diff --git a/spec/frontend/repository/components/last_commit_spec.js b/spec/frontend/repository/components/last_commit_spec.js index c207d32d61d..d5ec34b1f6d 100644 --- a/spec/frontend/repository/components/last_commit_spec.js +++ b/spec/frontend/repository/components/last_commit_spec.js @@ -1,29 +1,26 @@ import Vue, { nextTick } from 'vue'; -import VueApollo from 'vue-apollo'; import { GlLoadingIcon } from '@gitlab/ui'; +import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import LastCommit from '~/repository/components/last_commit.vue'; +import CommitInfo from '~/repository/components/commit_info.vue'; import SignatureBadge from '~/commit/components/signature_badge.vue'; -import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; import eventHub from '~/repository/event_hub'; import pathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql'; import { FORK_UPDATED_EVENT } from '~/repository/constants'; import { refMock } from '../mock_data'; let wrapper; +let commitData; let mockResolver; const findPipeline = () => wrapper.find('.js-commit-pipeline'); -const findTextExpander = () => wrapper.find('.text-expander'); -const findUserLink = () => wrapper.find('.js-user-link'); -const findUserAvatarLink = () => wrapper.findComponent(UserAvatarLink); const findLastCommitLabel = () => wrapper.findByTestId('last-commit-id-label'); const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); -const findCommitRowDescription = () => wrapper.find('.commit-row-description'); const findStatusBox = () => wrapper.findComponent(SignatureBadge); -const findItemTitle = () => wrapper.find('.item-title'); +const findCommitInfo = () => wrapper.findComponent(CommitInfo); const defaultPipelineEdges = [ { @@ -44,23 +41,7 @@ const defaultPipelineEdges = [ }, ]; -const defaultAuthor = { - __typename: 'UserCore', - id: 'gid://gitlab/User/1', - name: 'Test', - avatarUrl: 'https://test.com', - webPath: '/test', -}; - -const defaultMessage = 'Commit title'; - -const createCommitData = ({ - pipelineEdges = defaultPipelineEdges, - author = defaultAuthor, - descriptionHtml = '', - signature = null, - message = defaultMessage, -}) => { +const createCommitData = ({ pipelineEdges = defaultPipelineEdges, signature = null }) => { return { data: { project: { @@ -79,13 +60,19 @@ const createCommitData = ({ sha: '123456789', title: 'Commit title', titleHtml: 'Commit title', - descriptionHtml, - message, + descriptionHtml: '', + message: '', webPath: '/commit/123', authoredDate: '2019-01-01', authorName: 'Test', authorGravatar: 'https://test.com', - author, + author: { + __typename: 'UserCore', + id: 'gid://gitlab/User/1', + name: 'Test', + avatarUrl: 'https://test.com', + webPath: '/test', + }, signature, pipelines: { __typename: 'PipelineConnection', @@ -101,12 +88,13 @@ const createCommitData = ({ }; }; -const createComponent = (data = {}) => { +const createComponent = async (data = {}) => { Vue.use(VueApollo); const currentPath = 'path'; - mockResolver = jest.fn().mockResolvedValue(createCommitData(data)); + commitData = createCommitData(data); + mockResolver = jest.fn().mockResolvedValue(commitData); wrapper = shallowMountExtended(LastCommit, { apolloProvider: createMockApollo([[pathLastCommitQuery, mockResolver]]), @@ -116,8 +104,13 @@ const createComponent = (data = {}) => { SignatureBadge, }, }); + + await waitForPromises(); + await nextTick(); }; +beforeEach(() => createComponent()); + afterEach(() => { mockResolver = null; }); @@ -137,17 +130,17 @@ describe('Repository last commit component', () => { expect(findLoadingIcon().exists()).toBe(loading); }); - it('renders commit widget', async () => { - createComponent(); - await waitForPromises(); + it('renders a CommitInfo component', () => { + const commit = { ...commitData.project?.repository.paginatedTree.nodes[0].lastCommit }; - expect(wrapper.element).toMatchSnapshot(); + expect(findCommitInfo().props().commit).toMatchObject(commit); }); - it('renders short commit ID', async () => { - createComponent(); - await waitForPromises(); + it('renders commit widget', () => { + expect(wrapper.element).toMatchSnapshot(); + }); + it('renders short commit ID', () => { expect(findLastCommitLabel().text()).toBe('12345678'); }); @@ -158,29 +151,10 @@ describe('Repository last commit component', () => { expect(findPipeline().exists()).toBe(false); }); - it('renders pipeline components when pipeline exists', async () => { - createComponent(); - await waitForPromises(); - + it('renders pipeline components when pipeline exists', () => { expect(findPipeline().exists()).toBe(true); }); - it('hides author component when author does not exist', async () => { - createComponent({ author: null }); - await waitForPromises(); - - expect(findUserLink().exists()).toBe(false); - expect(findUserAvatarLink().exists()).toBe(false); - }); - - it('does not render description expander when description is null', async () => { - createComponent(); - await waitForPromises(); - - expect(findTextExpander().exists()).toBe(false); - expect(findCommitRowDescription().exists()).toBe(false); - }); - describe('created', () => { it('binds `epicsListScrolled` event listener via eventHub', () => { jest.spyOn(eventHub, '$on').mockImplementation(() => {}); @@ -200,32 +174,6 @@ describe('Repository last commit component', () => { }); }); - describe('when the description is present', () => { - beforeEach(async () => { - createComponent({ descriptionHtml: '
Update ADOPTERS.md' }); - await waitForPromises(); - }); - - it('strips the first newline of the description', () => { - expect(findCommitRowDescription().html()).toBe( - '<pre class="commit-row-description gl-mb-3 gl-white-space-pre-line">Update ADOPTERS.md</pre>', - ); - }); - - it('expands commit description when clicking expander', async () => { - expect(findCommitRowDescription().classes('d-block')).toBe(false); - expect(findTextExpander().classes('open')).toBe(false); - expect(findTextExpander().props('selected')).toBe(false); - - findTextExpander().vm.$emit('click'); - await nextTick(); - - expect(findCommitRowDescription().classes('d-block')).toBe(true); - expect(findTextExpander().classes('open')).toBe(true); - expect(findTextExpander().props('selected')).toBe(true); - }); - }); - it('renders the signature HTML as returned by the backend', async () => { const signatureResponse = { __typename: 'GpgSignature', @@ -241,11 +189,4 @@ describe('Repository last commit component', () => { expect(findStatusBox().props()).toMatchObject({ signature: signatureResponse }); }); - - it('sets correct CSS class if the commit message is empty', async () => { - createComponent({ message: '' }); - await waitForPromises(); - - expect(findItemTitle().classes()).toContain('font-italic'); - }); }); diff --git a/spec/initializers/gitlab_http_spec.rb b/spec/initializers/gitlab_http_spec.rb new file mode 100644 index 00000000000..7715112abf4 --- /dev/null +++ b/spec/initializers/gitlab_http_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::HTTP_V2, feature_category: :shared do + it 'handles log_exception_proc' do + expect(Gitlab::HTTP_V2::Client).to receive(:httparty_perform_request) + .and_raise(Net::ReadTimeout) + + expect(Gitlab::ErrorTracking).to receive(:log_exception) + .with(Net::ReadTimeout, {}) + + expect { described_class.get('http://example.org') }.to raise_error(Net::ReadTimeout) + end + + context 'when silent_mode_enabled is true' do + before do + stub_application_setting(silent_mode_enabled: true) + end + + context 'when sending a POST request' do + it 'handles silent_mode_log_info_proc' do + expect(::Gitlab::AppJsonLogger).to receive(:info).with( + message: "Outbound HTTP request blocked", + outbound_http_request_method: 'Net::HTTP::Post', + silent_mode_enabled: true + ) + + expect { described_class.post('http://example.org', silent_mode_enabled: true) }.to raise_error( + Gitlab::HTTP_V2::SilentModeBlockedError + ) + end + end + + context 'when sending a GET request' do + before do + stub_request(:get, 'http://example.org').to_return(body: 'hello') + end + + it 'does not raise an error' do + expect(::Gitlab::AppJsonLogger).not_to receive(:info) + + expect(described_class.get('http://example.org', silent_mode_enabled: true).body).to eq('hello') + end + end + end +end diff --git a/spec/initializers/net_http_patch_spec.rb b/spec/initializers/net_http_patch_spec.rb index b9f5299b58c..959eae954c4 100644 --- a/spec/initializers/net_http_patch_spec.rb +++ b/spec/initializers/net_http_patch_spec.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'fast_spec_helper' -require 'net/http' +# TODO: This spec file can be removed after fully migration to the gitlab-http gem. +# It's already covered in gems/gitlab-http/spec/gitlab/http_v2/net_http_patch_spec.rb -require_relative '../../config/initializers/net_http_patch' +require 'spec_helper' -RSpec.describe 'Net::HTTP patch proxy user and password encoding' do +RSpec.describe 'Net::HTTP patch proxy user and password encoding', feature_category: :shared do let(:net_http) { Net::HTTP.new('hostname.example') } before do diff --git a/spec/initializers/net_http_response_patch_spec.rb b/spec/initializers/net_http_response_patch_spec.rb index cd261d7b997..8074047d6aa 100644 --- a/spec/initializers/net_http_response_patch_spec.rb +++ b/spec/initializers/net_http_response_patch_spec.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +# TODO: This spec file can be removed after fully migration to the gitlab-http gem. +# It's already covered in gems/gitlab-http/spec/gitlab/http_v2/net_http_response_patch_spec.rb + require 'spec_helper' RSpec.describe 'Net::HTTPResponse patch header read timeout', feature_category: :shared do diff --git a/spec/lib/container_registry/client_spec.rb b/spec/lib/container_registry/client_spec.rb index a1425169dee..39409cf8d3a 100644 --- a/spec/lib/container_registry/client_spec.rb +++ b/spec/lib/container_registry/client_spec.rb @@ -89,13 +89,14 @@ RSpec.describe ContainerRegistry::Client do it_behaves_like 'handling timeouts' end - shared_examples 'handling repository info' do + shared_examples 'handling registry info' do context 'when the check is successful' do context 'when using the GitLab container registry' do before do stub_registry_info(headers: { 'GitLab-Container-Registry-Version' => '2.9.1-gitlab', - 'GitLab-Container-Registry-Features' => 'a,b,c' + 'GitLab-Container-Registry-Features' => 'a,b,c', + 'GitLab-Container-Registry-Database-Enabled' => 'true' }) end @@ -106,6 +107,10 @@ RSpec.describe ContainerRegistry::Client do it 'identifies version and features' do expect(subject).to include(version: '2.9.1-gitlab', features: %w[a b c]) end + + it 'identifies the registry DB as enabled' do + expect(subject).to include(db_enabled: true) + end end context 'when using a third-party container registry' do @@ -120,6 +125,10 @@ RSpec.describe ContainerRegistry::Client do it 'does not identify version or features' do expect(subject).to include(version: nil, features: []) end + + it 'does not identify the registry DB as enabled' do + expect(subject).to include(db_enabled: false) + end end end @@ -130,6 +139,16 @@ RSpec.describe ContainerRegistry::Client do expect(subject).to eq({}) end end + + context 'when the check returns an unexpected value in the database enabled header' do + it 'does not identify the registry DB as enabled' do + stub_registry_info(headers: { + 'GitLab-Container-Registry-Database-Enabled' => '123' + }) + + expect(subject).to include(db_enabled: false) + end + end end describe '#repository_manifest' do @@ -360,7 +379,7 @@ RSpec.describe ContainerRegistry::Client do describe '#registry_info' do subject { client.registry_info } - it_behaves_like 'handling repository info' + it_behaves_like 'handling registry info' end describe '.supports_tag_delete?' do @@ -446,7 +465,7 @@ RSpec.describe ContainerRegistry::Client do stub_container_registry_config(enabled: true, api_url: registry_api_url, key: 'spec/fixtures/x509_certificate_pk.key') end - it_behaves_like 'handling repository info' + it_behaves_like 'handling registry info' end def stub_upload(path, content, digest, status = 200) diff --git a/spec/models/clusters/agent_token_spec.rb b/spec/models/clusters/agent_token_spec.rb index bc158fc9117..5f731336b4b 100644 --- a/spec/models/clusters/agent_token_spec.rb +++ b/spec/models/clusters/agent_token_spec.rb @@ -95,6 +95,15 @@ RSpec.describe Clusters::AgentToken, feature_category: :deployment_management do expect(agent_token.token).to start_with described_class::TOKEN_PREFIX end + + it 'is revoked on revoke!' do + agent_token = build(:cluster_agent_token, token_encrypted: nil) + agent_token.save! + + agent_token.revoke! + + expect(agent_token.active?).to be_falsey + end end describe '#to_ability_name' do diff --git a/spec/requests/api/group_export_spec.rb b/spec/requests/api/group_export_spec.rb index b4add2494b0..ddee2081bcf 100644 --- a/spec/requests/api/group_export_spec.rb +++ b/spec/requests/api/group_export_spec.rb @@ -325,8 +325,13 @@ RSpec.describe API::GroupExport, feature_category: :importers do end context 'when bulk import is disabled' do + before do + stub_application_setting(bulk_import_enabled: false) + end + it_behaves_like '404 response' do - let(:request) { get api(path, user) } + let(:message) { '404 Not Found' } + let(:request) { post api(path, user) } end end end diff --git a/spec/requests/api/npm_group_packages_spec.rb b/spec/requests/api/npm_group_packages_spec.rb index 7fba75b0630..12b2ccd1bf7 100644 --- a/spec/requests/api/npm_group_packages_spec.rb +++ b/spec/requests/api/npm_group_packages_spec.rb @@ -22,11 +22,11 @@ RSpec.describe API::NpmGroupPackages, feature_category: :package_registry do where(:auth, :group_visibility, :project_visibility, :user_role, :expected_status) do nil | :public | :public | nil | :ok - nil | :public | :internal | nil | :not_found - nil | :public | :private | nil | :not_found - nil | :internal | :internal | nil | :not_found - nil | :internal | :private | nil | :not_found - nil | :private | :private | nil | :not_found + nil | :public | :internal | nil | :unauthorized + nil | :public | :private | nil | :unauthorized + nil | :internal | :internal | nil | :unauthorized + nil | :internal | :private | nil | :unauthorized + nil | :private | :private | nil | :unauthorized :oauth | :public | :public | :guest | :ok :oauth | :public | :internal | :guest | :ok diff --git a/spec/requests/api/project_export_spec.rb b/spec/requests/api/project_export_spec.rb index 3603a71151e..8a47eb2dae1 100644 --- a/spec/requests/api/project_export_spec.rb +++ b/spec/requests/api/project_export_spec.rb @@ -708,6 +708,8 @@ RSpec.describe API::ProjectExport, :aggregate_failures, :clean_gitlab_redis_cach describe 'POST /projects/:id/export_relations' do it_behaves_like '404 response' do + let(:message) { '404 Not Found' } + subject(:request) { post api(path, user) } end end @@ -721,12 +723,16 @@ RSpec.describe API::ProjectExport, :aggregate_failures, :clean_gitlab_redis_cach end it_behaves_like '404 response' do - subject(:request) { post api(path, user) } + let(:message) { '404 Not Found' } + + subject(:request) { get api(download_path, user) } end end describe 'GET /projects/:id/export_relations/status' do it_behaves_like '404 response' do + let(:message) { '404 Not Found' } + subject(:request) { get api(status_path, user) } end end @@ -758,11 +764,5 @@ RSpec.describe API::ProjectExport, :aggregate_failures, :clean_gitlab_redis_cach end end end - - context 'when bulk import is disabled' do - it_behaves_like '404 response' do - subject(:request) { get api(path, user) } - end - end end end diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb index 5f043cdd996..a4091d6bceb 100644 --- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb @@ -68,22 +68,22 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project| nil | :unscoped | false | :public | nil | :accept | :ok nil | :non_existing | true | :public | nil | :redirect | :redirected nil | :non_existing | false | :public | nil | :reject | :not_found - nil | :scoped_naming_convention | true | :private | nil | :reject | :not_found - nil | :scoped_naming_convention | false | :private | nil | :reject | :not_found - nil | :scoped_no_naming_convention | true | :private | nil | :reject | :not_found - nil | :scoped_no_naming_convention | false | :private | nil | :reject | :not_found - nil | :unscoped | true | :private | nil | :reject | :not_found - nil | :unscoped | false | :private | nil | :reject | :not_found + nil | :scoped_naming_convention | true | :private | nil | :reject | :unauthorized + nil | :scoped_naming_convention | false | :private | nil | :reject | :unauthorized + nil | :scoped_no_naming_convention | true | :private | nil | :reject | :unauthorized + nil | :scoped_no_naming_convention | false | :private | nil | :reject | :unauthorized + nil | :unscoped | true | :private | nil | :reject | :unauthorized + nil | :unscoped | false | :private | nil | :reject | :unauthorized nil | :non_existing | true | :private | nil | :redirect | :redirected - nil | :non_existing | false | :private | nil | :reject | :not_found - nil | :scoped_naming_convention | true | :internal | nil | :reject | :not_found - nil | :scoped_naming_convention | false | :internal | nil | :reject | :not_found - nil | :scoped_no_naming_convention | true | :internal | nil | :reject | :not_found - nil | :scoped_no_naming_convention | false | :internal | nil | :reject | :not_found - nil | :unscoped | true | :internal | nil | :reject | :not_found - nil | :unscoped | false | :internal | nil | :reject | :not_found + nil | :non_existing | false | :private | nil | :reject | :unauthorized + nil | :scoped_naming_convention | true | :internal | nil | :reject | :unauthorized + nil | :scoped_naming_convention | false | :internal | nil | :reject | :unauthorized + nil | :scoped_no_naming_convention | true | :internal | nil | :reject | :unauthorized + nil | :scoped_no_naming_convention | false | :internal | nil | :reject | :unauthorized + nil | :unscoped | true | :internal | nil | :reject | :unauthorized + nil | :unscoped | false | :internal | nil | :reject | :unauthorized nil | :non_existing | true | :internal | nil | :redirect | :redirected - nil | :non_existing | false | :internal | nil | :reject | :not_found + nil | :non_existing | false | :internal | nil | :reject | :unauthorized :oauth | :scoped_naming_convention | true | :public | :guest | :accept | :ok :oauth | :scoped_naming_convention | true | :public | :reporter | :accept | :ok @@ -280,11 +280,15 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project| end end - if (scope == :group && params[:package_name_type] == :non_existing) && - (!params[:request_forward] || (!params[:auth] && params[:request_forward] && params[:visibility] != :public)) + if scope == :group && params[:package_name_type] == :non_existing && !params[:request_forward] && params[:auth] status = :not_found end + if scope == :group && params[:package_name_type] == :non_existing && params[:request_forward] && !params[:auth] && params[:visibility] != :public + example_name = 'reject metadata request' + status = :unauthorized + end + # Check the error message for :not_found example_name = 'returning response status with error' if status == :not_found @@ -522,14 +526,14 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project| nil | :scoped_no_naming_convention | :public | nil | :accept | :ok nil | :unscoped | :public | nil | :accept | :ok nil | :non_existing | :public | nil | :reject | :not_found - nil | :scoped_naming_convention | :private | nil | :reject | :not_found - nil | :scoped_no_naming_convention | :private | nil | :reject | :not_found - nil | :unscoped | :private | nil | :reject | :not_found - nil | :non_existing | :private | nil | :reject | :not_found - nil | :scoped_naming_convention | :internal | nil | :reject | :not_found - nil | :scoped_no_naming_convention | :internal | nil | :reject | :not_found - nil | :unscoped | :internal | nil | :reject | :not_found - nil | :non_existing | :internal | nil | :reject | :not_found + nil | :scoped_naming_convention | :private | nil | :reject | :unauthorized + nil | :scoped_no_naming_convention | :private | nil | :reject | :unauthorized + nil | :unscoped | :private | nil | :reject | :unauthorized + nil | :non_existing | :private | nil | :reject | :unauthorized + nil | :scoped_naming_convention | :internal | nil | :reject | :unauthorized + nil | :scoped_no_naming_convention | :internal | nil | :reject | :unauthorized + nil | :unscoped | :internal | nil | :reject | :unauthorized + nil | :non_existing | :internal | nil | :reject | :unauthorized :oauth | :scoped_naming_convention | :public | :guest | :accept | :ok :oauth | :scoped_naming_convention | :public | :reporter | :accept | :ok diff --git a/spec/workers/merge_worker_spec.rb b/spec/workers/merge_worker_spec.rb index 9c6a6564df6..48d8ea3ab16 100644 --- a/spec/workers/merge_worker_spec.rb +++ b/spec/workers/merge_worker_spec.rb @@ -48,4 +48,61 @@ RSpec.describe MergeWorker, feature_category: :source_code_management do end end end + + describe 'delegation to MergeRequests::MergeService' do + # Some ids that should be nonexistentn + let(:user_id) { -1 } + let(:merge_request_id) { -1 } + let(:params) { {} } + + subject { described_class.new.perform(merge_request_id, user_id, params) } + + context 'when user exists' do + let!(:user) { create(:user) } + let(:user_id) { user.id } + + context 'and merge request exists' do + let!(:merge_request) { create(:merge_request, source_project: create(:project, :empty_repo)) } + let(:merge_request_id) { merge_request.id } + let(:user) { merge_request.author } + let(:merge_service_double) { instance_double(MergeRequests::MergeService) } + + it 'delegates to MergeRequests::MergeService' do + expect(MergeRequests::MergeService).to receive(:new).with( + project: merge_request.target_project, + current_user: user, + params: { check_mergeability_retry_lease: true } + ).and_return(merge_service_double) + + expect(merge_service_double).to receive(:execute) + subject + end + + context 'and check_mergeability_retry_lease is specified' do + let(:params) { { check_mergeability_retry_lease: false } } + + it 'does not change the check_mergeability_retry_lease parameter' do + expect(MergeRequests::MergeService).to receive(:new).with( + project: merge_request.target_project, + current_user: user, + params: params + ).and_return(merge_service_double) + + expect(merge_service_double).to receive(:execute) + subject + end + end + end + + it 'does not call MergeRequests::MergeService' do + expect(MergeRequests::MergeService).not_to receive(:new) + subject + end + end + + it 'does not call MergeRequests::MergeService' do + expect(MergeRequests::MergeService).not_to receive(:new) + subject + end + end end diff --git a/yarn.lock b/yarn.lock index 4821b2360e7..ca8eef5815a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3510,6 +3510,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -4184,9 +4189,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0, ci-info@^3.3.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" - integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg== + version "3.8.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" @@ -6859,14 +6864,15 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-extra@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" - integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== +fs-extra@^9.0.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" fs-minipass@^2.0.0: version "2.0.0" @@ -7130,10 +7136,10 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.10" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" - integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: version "1.4.0" @@ -8687,10 +8693,12 @@ jsonc-parser@^3.0.0, jsonc-parser@~3.2.0: resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" @@ -10610,24 +10618,25 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@^6.4.7: - version "6.4.7" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" - integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== +patch-package@6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" + integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== dependencies: "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" + chalk "^4.1.2" cross-spawn "^6.0.5" find-yarn-workspace-root "^2.0.0" - fs-extra "^7.0.1" + fs-extra "^9.0.0" is-ci "^2.0.0" klaw-sync "^6.0.0" - minimist "^1.2.0" + minimist "^1.2.6" open "^7.4.2" rimraf "^2.6.3" semver "^5.6.0" slash "^2.0.0" tmp "^0.0.33" + yaml "^1.10.2" path-browserify@0.0.1: version "0.0.1" @@ -11852,9 +11861,9 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.3.4, semver@^7.3.5, semver@^7.3.6, semver@^7.3.7, semver@^7.5.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0" - integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA== + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" @@ -13246,11 +13255,16 @@ unist-util-visit@^4.0.0: unist-util-is "^5.0.0" unist-util-visit-parents "^5.0.0" -universalify@^0.1.0, universalify@^0.1.2: +universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + unixify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" @@ -14096,10 +14110,15 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yaml@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + yaml@^2.0.0, yaml@^2.0.0-10: - version "2.1.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.1.tgz#1e06fb4ca46e60d9da07e4f786ea370ed3c3cfec" - integrity sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw== + version "2.3.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" + integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== yargs-parser@^18.1.2: version "18.1.3" |