diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-25 21:10:57 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-25 21:10:57 +0300 |
commit | 0351d9ed83635ce3258e2d09ba92b46a7cdcfa61 (patch) | |
tree | dd3c671fd8f618b87b9beeb7cf3a5b2ffa325253 | |
parent | c59393a068f9d0113cc10ca8798d333d6a0e3d53 (diff) |
Add latest changes from gitlab-org/gitlab@master
81 files changed, 199 insertions, 598 deletions
diff --git a/.rubocop_todo/layout/space_inside_parens.yml b/.rubocop_todo/layout/space_inside_parens.yml index bfbbb6352b6..50511bbb1e3 100644 --- a/.rubocop_todo/layout/space_inside_parens.yml +++ b/.rubocop_todo/layout/space_inside_parens.yml @@ -23,21 +23,6 @@ Layout/SpaceInsideParens: - 'ee/app/services/sitemap/create_service.rb' - 'ee/lib/ee/gitlab/auth/ldap/access.rb' - 'ee/lib/gitlab/auth/smartcard/session.rb' - - 'ee/spec/features/account_recovery_regular_check_spec.rb' - - 'ee/spec/features/billings/billing_plans_spec.rb' - - 'ee/spec/features/boards/board_filters_spec.rb' - - 'ee/spec/features/boards/group_boards/board_deletion_spec.rb' - - 'ee/spec/features/boards/user_visits_board_spec.rb' - - 'ee/spec/features/groups/analytics/ci_cd_analytics_spec.rb' - - 'ee/spec/features/groups/issues_spec.rb' - - 'ee/spec/features/groups/iteration_spec.rb' - - 'ee/spec/features/groups/iterations/user_creates_iteration_in_cadence_spec.rb' - - 'ee/spec/features/groups/iterations/user_edits_iteration_cadence_spec.rb' - - 'ee/spec/features/groups/iterations/user_edits_iteration_spec.rb' - - 'ee/spec/features/merge_request/user_edits_multiple_reviewers_mr_spec.rb' - - 'ee/spec/features/merge_requests/user_resets_approvers_spec.rb' - - 'ee/spec/features/merge_requests/user_views_all_merge_requests_spec.rb' - - 'ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb' - 'ee/spec/finders/ee/alert_management/http_integrations_finder_spec.rb' - 'ee/spec/finders/epics_finder_spec.rb' - 'ee/spec/finders/security/pipeline_vulnerabilities_finder_spec.rb' @@ -229,7 +229,7 @@ gem 'gitlab-sidekiq-fetcher', '0.8.0', require: 'sidekiq-reliable-fetch' gem 'fugit', '~> 1.2.1' # HTTP requests -gem 'httparty', '~> 0.16.4' +gem 'httparty', '~> 0.20.0' # Colored output to console gem 'rainbow', '~> 3.0' diff --git a/Gemfile.checksum b/Gemfile.checksum index 1bbc982f718..6a68d1a93f3 100644 --- a/Gemfile.checksum +++ b/Gemfile.checksum @@ -272,7 +272,7 @@ {"name":"http-cookie","version":"1.0.5","platform":"ruby","checksum":"73756d46c7dbdc7023deecdb8a171348ea95a1b99810b31cfe8b4fb4e9a6318f"}, {"name":"http-form_data","version":"2.3.0","platform":"ruby","checksum":"cc4eeb1361d9876821e31d7b1cf0b68f1cf874b201d27903480479d86448a5f3"}, {"name":"http-parser","version":"1.2.3","platform":"ruby","checksum":"414dec1f443d68e1068509f184ee4b93e3442f626645071182ce49bc27db18a3"}, -{"name":"httparty","version":"0.16.4","platform":"ruby","checksum":"62c89d00f5e8933b2d397a49b57deb18ca18e16cb7d862ee4f53b73228dc3d81"}, +{"name":"httparty","version":"0.20.0","platform":"ruby","checksum":"490d2a028a5accc611f1685d479d80ef80b129140d24a93c53c119f578614867"}, {"name":"httpclient","version":"2.8.3","platform":"ruby","checksum":"2951e4991214464c3e92107e46438527d23048e634f3aee91c719e0bdfaebda6"}, {"name":"i18n","version":"1.12.0","platform":"ruby","checksum":"91e3cc1b97616d308707eedee413d82ee021d751c918661fb82152793e64aced"}, {"name":"i18n_data","version":"0.8.0","platform":"ruby","checksum":"92d942cc193dc4a54a95b68f44e52c79e024fa72e09f26a982bc61153b6f0c6c"}, diff --git a/Gemfile.lock b/Gemfile.lock index 7de50d806e2..054b5e81443 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -734,7 +734,7 @@ GEM http-form_data (2.3.0) http-parser (1.2.3) ffi-compiler (>= 1.0, < 2.0) - httparty (0.16.4) + httparty (0.20.0) mime-types (~> 3.0) multi_xml (>= 0.5.2) httpclient (2.8.3) @@ -1666,7 +1666,7 @@ DEPENDENCIES health_check (~> 3.0) html-pipeline (~> 2.13.2) html2text - httparty (~> 0.16.4) + httparty (~> 0.20.0) icalendar invisible_captcha (~> 1.1.0) ipaddr (= 1.2.2) diff --git a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue index 7d0f1ba4b5f..1cd28e027f3 100644 --- a/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue +++ b/app/assets/javascripts/pipelines/components/test_reports/test_suite_table.vue @@ -112,21 +112,21 @@ export default { > <div class="table-section section-20 section-wrap"> <div role="rowheader" class="table-mobile-header">{{ __('Suite') }}</div> - <div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break"> + <div class="table-mobile-content gl-pr-0 gl-sm-pr-2 gl-overflow-wrap-break"> <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.classname" /> </div> </div> <div class="table-section section-40 section-wrap"> <div role="rowheader" class="table-mobile-header">{{ __('Name') }}</div> - <div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break"> + <div class="table-mobile-content gl-pr-0 gl-sm-pr-2 gl-overflow-wrap-break"> <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.name" /> </div> </div> <div class="table-section section-10 section-wrap"> <div role="rowheader" class="table-mobile-header">{{ __('Filename') }}</div> - <div class="table-mobile-content gl-md-pr-2 gl-overflow-wrap-break"> + <div class="table-mobile-content gl-pr-0 gl-sm-pr-2 gl-overflow-wrap-break"> <gl-link v-if="testCase.file" :href="testCase.filePath" target="_blank"> <gl-friendly-wrap :symbols="$options.wrapSymbols" :text="testCase.file" /> </gl-link> @@ -156,7 +156,7 @@ export default { <div role="rowheader" class="table-mobile-header"> {{ __('Duration') }} </div> - <div class="table-mobile-content gl-sm-pr-2"> + <div class="table-mobile-content gl-pr-0 gl-sm-pr-2"> {{ testCase.formattedTime }} </div> </div> diff --git a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue index 98468583992..c262d65f6ce 100644 --- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue +++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue @@ -170,7 +170,7 @@ export default { this.$emit('closeForm'); }, openDatePicker() { - this.$refs.datePicker.calendar.show(); + this.$refs.datePicker.show(); }, setFixedDate(isFixed) { const date = this.issuable[dateFields[this.dateType].dateFixed]; diff --git a/app/assets/javascripts/users_select/constants.js b/app/assets/javascripts/users_select/constants.js index 64df1e1748c..6b91d7e7c10 100644 --- a/app/assets/javascripts/users_select/constants.js +++ b/app/assets/javascripts/users_select/constants.js @@ -1,11 +1,3 @@ -export const AJAX_USERS_SELECT_OPTIONS_MAP = { - projectId: 'projectId', - groupId: 'groupId', - showCurrentUser: 'currentUser', - authorId: 'authorId', - skipUsers: 'skipUsers', -}; - export const AJAX_USERS_SELECT_PARAMS_MAP = { project_id: 'projectId', group_id: 'groupId', diff --git a/app/assets/javascripts/users_select/index.js b/app/assets/javascripts/users_select/index.js index 8fc5c354802..a0550737e24 100644 --- a/app/assets/javascripts/users_select/index.js +++ b/app/assets/javascripts/users_select/index.js @@ -1,21 +1,17 @@ -/* eslint-disable func-names, prefer-rest-params, consistent-return, no-shadow, no-self-compare, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */ +/* eslint-disable func-names, consistent-return, no-shadow, no-self-compare, no-unused-expressions, camelcase, no-param-reassign */ /* global Issuable */ /* global emitSidebarEvent */ import $ from 'jquery'; import { escape, template, uniqBy } from 'lodash'; -import { - AJAX_USERS_SELECT_OPTIONS_MAP, - AJAX_USERS_SELECT_PARAMS_MAP, -} from 'ee_else_ce/users_select/constants'; +import { AJAX_USERS_SELECT_PARAMS_MAP } from 'ee_else_ce/users_select/constants'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import { isUserBusy } from '~/set_status_modal/utils'; import { fixTitle, dispose } from '~/tooltips'; import axios from '~/lib/utils/axios_utils'; import { parseBoolean, spriteIcon } from '~/lib/utils/common_utils'; -import { loadCSSFile } from '~/lib/utils/css_utils'; import { s__, __, sprintf } from '~/locale'; -import { getAjaxUsersSelectOptions, getAjaxUsersSelectParams } from './utils'; +import { getAjaxUsersSelectParams } from './utils'; // TODO: remove eventHub hack after code splitting refactor window.emitSidebarEvent = window.emitSidebarEvent || $.noop; @@ -24,9 +20,7 @@ function UsersSelect(currentUser, els, options = {}) { const elsClassName = els?.toString().match('.(.+$)')[1]; const $els = $(els || '.js-user-search'); this.users = this.users.bind(this); - this.user = this.user.bind(this); this.usersPath = '/-/autocomplete/users.json'; - this.userPath = '/-/autocomplete/users/:id.json'; if (currentUser != null) { if (typeof currentUser === 'object') { this.currentUser = currentUser; @@ -36,7 +30,6 @@ function UsersSelect(currentUser, els, options = {}) { } const { handleClick } = options; - const userSelect = this; $els.each((i, dropdown) => { const userSelect = this; @@ -619,156 +612,8 @@ function UsersSelect(currentUser, els, options = {}) { }, }); }); - - if ($('.ajax-users-select').length) { - import(/* webpackChunkName: 'select2' */ 'select2/select2') - .then(() => { - // eslint-disable-next-line promise/no-nesting - loadCSSFile(gon.select2_css_path) - .then(() => { - $('.ajax-users-select').each((i, select) => { - const options = getAjaxUsersSelectOptions($(select), AJAX_USERS_SELECT_OPTIONS_MAP); - options.skipLdap = $(select).hasClass('skip_ldap'); - const showNullUser = $(select).data('nullUser'); - const showAnyUser = $(select).data('anyUser'); - const showEmailUser = $(select).data('emailUser'); - const firstUser = $(select).data('firstUser'); - return $(select).select2({ - placeholder: __('Search for a user'), - multiple: $(select).hasClass('multiselect'), - minimumInputLength: 0, - query(query) { - return userSelect.users(query.term, options, (users) => { - let name; - const data = { - results: users, - }; - if (query.term.length === 0) { - if (firstUser) { - // Move current user to the front of the list - const ref = data.results; - - for (let index = 0, len = ref.length; index < len; index += 1) { - const obj = ref[index]; - if (obj.username === firstUser) { - data.results.splice(index, 1); - data.results.unshift(obj); - break; - } - } - } - if (showNullUser) { - const nullUser = { - name: s__('UsersSelect|Unassigned'), - id: 0, - }; - data.results.unshift(nullUser); - } - if (showAnyUser) { - name = showAnyUser; - if (name === true) { - name = s__('UsersSelect|Any User'); - } - const anyUser = { - name, - id: null, - }; - data.results.unshift(anyUser); - } - } - if ( - showEmailUser && - data.results.length === 0 && - query.term.match(/^[^@]+@[^@]+$/) - ) { - const trimmed = query.term.trim(); - const emailUser = { - name: sprintf(__('Invite "%{trimmed}" by email'), { trimmed }), - username: trimmed, - id: trimmed, - invite: true, - }; - data.results.unshift(emailUser); - } - return query.callback(data); - }); - }, - initSelection() { - const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; - return userSelect.initSelection.apply(userSelect, args); - }, - formatResult() { - const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; - return userSelect.formatResult.apply(userSelect, args); - }, - formatSelection() { - const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; - return userSelect.formatSelection.apply(userSelect, args); - }, - dropdownCssClass: 'ajax-users-dropdown', - // we do not want to escape markup since we are displaying html in results - escapeMarkup(m) { - return m; - }, - }); - }); - }) - .catch(() => {}); - }) - .catch(() => {}); - } } -UsersSelect.prototype.initSelection = function (element, callback) { - const id = $(element).val(); - if (id === '0') { - const nullUser = { - name: s__('UsersSelect|Unassigned'), - }; - return callback(nullUser); - } else if (id !== '') { - return this.user(id, callback); - } -}; - -UsersSelect.prototype.formatResult = function (user) { - let avatar = gon.default_avatar_url; - if (user.avatar_url) { - avatar = user.avatar_url; - } - return ` - <div class='user-result'> - <div class='user-image'> - <img class='avatar avatar-inline s32' src='${avatar}'> - </div> - <div class='user-info'> - <div class='user-name dropdown-menu-user-full-name'> - ${escape(user.name)} - </div> - <div class='user-username dropdown-menu-user-username text-secondary'> - ${!user.invite ? `@${escape(user.username)}` : ''} - </div> - </div> - </div> - `; -}; - -UsersSelect.prototype.formatSelection = function (user) { - return escape(user.name); -}; - -UsersSelect.prototype.user = function (user_id, callback) { - if (!/^\d+$/.test(user_id)) { - return false; - } - - let url = this.buildUrl(this.userPath); - url = url.replace(':id', user_id); - return axios.get(url).then(({ data }) => { - callback(data); - }); -}; - // Return users list. Filtered by query // Only active users retrieved UsersSelect.prototype.users = function (query, options, callback) { diff --git a/app/assets/javascripts/users_select/utils.js b/app/assets/javascripts/users_select/utils.js index b46fd15fb77..8184e646124 100644 --- a/app/assets/javascripts/users_select/utils.js +++ b/app/assets/javascripts/users_select/utils.js @@ -1,18 +1,4 @@ /** - * Get options from data attributes on passed `$select`. - * @param {jQuery} $select - * @param {Object} optionsMap e.g. { optionKeyName: 'dataAttributeName' } - */ -export const getAjaxUsersSelectOptions = ($select, optionsMap) => { - return Object.keys(optionsMap).reduce((accumulator, optionKey) => { - const dataKey = optionsMap[optionKey]; - accumulator[optionKey] = $select.data(dataKey); - - return accumulator; - }, {}); -}; - -/** * Get query parameters used for users request from passed `options` parameter * @param {Object} options e.g. { currentUserId: 1, fooBar: 'baz' } * @param {Object} paramsMap e.g. { user_id: 'currentUserId', foo_bar: 'fooBar' } diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index 1298c1316e2..dd52dc1ca55 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue @@ -538,13 +538,15 @@ export default { <div class="media-body"> <div class="mr-widget-body-controls gl-display-flex gl-align-items-center gl-flex-wrap"> <template v-if="shouldShowMergeControls"> - <div class="gl-display-flex gl-align-items-center gl-flex-wrap gl-w-full gl-mb-5"> + <div + class="gl-display-flex gl-sm-flex-direction-column gl-md-align-items-center gl-flex-wrap gl-w-full gl-md-pb-5" + > <gl-form-checkbox v-if="canRemoveSourceBranch" id="remove-source-branch-input" v-model="removeSourceBranch" :disabled="isRemoveSourceBranchButtonDisabled" - class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5" + class="js-remove-source-branch-checkbox gl-display-flex gl-align-items-center gl-mr-5 gl-mb-3 gl-md-mb-0" > {{ __('Delete source branch') }} </gl-form-checkbox> @@ -555,37 +557,18 @@ export default { v-model="squashBeforeMerge" :help-path="mr.squashBeforeMergeHelpPath" :is-disabled="isSquashReadOnly" - class="gl-mr-5" + class="gl-mr-5 gl-mb-3 gl-md-mb-0" /> <gl-form-checkbox v-if="shouldShowSquashEdit || shouldShowMergeEdit" v-model="editCommitMessage" data-testid="widget_edit_commit_message" - class="gl-display-flex gl-align-items-center" + class="gl-display-flex gl-align-items-center gl-mb-3 gl-md-mb-0" > {{ __('Edit commit message') }} </gl-form-checkbox> </div> - <div class="gl-w-full gl-text-gray-500 gl-mb-5"> - <added-commit-message - :is-squash-enabled="squashBeforeMerge" - :is-fast-forward-enabled="!shouldShowMergeEdit" - :commits-count="commitsCount" - :target-branch="stateData.targetBranch" - /> - <template v-if="mr.relatedLinks"> - · - <related-links - :state="mr.state" - :related-links="mr.relatedLinks" - :show-assign-to-me="false" - :diverged-commits-count="mr.divergedCommitsCount" - :target-branch-path="mr.targetBranchPath" - class="mr-ready-merge-related-links gl-display-inline" - /> - </template> - </div> <div v-if="editCommitMessage" class="gl-w-full" data-testid="edit_commit_message"> <ul class="border-top commits-list flex-list gl-list-style-none gl-p-0 gl-pt-4"> <commit-edit @@ -625,6 +608,25 @@ export default { </li> </ul> </div> + <div class="gl-w-full gl-text-gray-500 gl-mb-3 gl-md-mb-0 gl-md-pb-5"> + <added-commit-message + :is-squash-enabled="squashBeforeMerge" + :is-fast-forward-enabled="!shouldShowMergeEdit" + :commits-count="commitsCount" + :target-branch="stateData.targetBranch" + /> + <template v-if="mr.relatedLinks"> + · + <related-links + :state="mr.state" + :related-links="mr.relatedLinks" + :show-assign-to-me="false" + :diverged-commits-count="mr.divergedCommitsCount" + :target-branch-path="mr.targetBranchPath" + class="mr-ready-merge-related-links gl-display-inline" + /> + </template> + </div> <gl-button-group class="gl-align-self-start"> <gl-button size="medium" diff --git a/app/assets/javascripts/work_items/components/work_item_due_date.vue b/app/assets/javascripts/work_items/components/work_item_due_date.vue index eae11c2bb2f..9ee302855c7 100644 --- a/app/assets/javascripts/work_items/components/work_item_due_date.vue +++ b/app/assets/javascripts/work_items/components/work_item_due_date.vue @@ -134,12 +134,12 @@ export default { async clickShowDueDate() { this.showDueDateInput = true; await this.$nextTick(); - this.$refs.dueDatePicker.calendar.show(); + this.$refs.dueDatePicker.show(); }, async clickShowStartDate() { this.showStartDateInput = true; await this.$nextTick(); - this.$refs.startDatePicker.calendar.show(); + this.$refs.startDatePicker.show(); }, handleStartDateInput() { if (this.dirtyDueDate && this.dirtyStartDate > this.dirtyDueDate) { diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss index 900cf9fa4db..ea741af918c 100644 --- a/app/assets/stylesheets/framework/selects.scss +++ b/app/assets/stylesheets/framework/selects.scss @@ -1,15 +1,3 @@ -.ajax-users-select { - width: 400px; - - &.input-large { - width: 210px; - } - - &.input-clamp { - max-width: 100%; - } -} - .group-result { .group-image { float: left; @@ -49,7 +37,3 @@ } } } - -.ajax-users-dropdown { - min-width: 250px !important; -} diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index b75a7c4a2dd..a1195b572f8 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -84,7 +84,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController format.json do Gitlab::UsageDataCounters::ServiceUsageDataCounter.count(:download_payload_click) - render json: service_ping_data.to_json + render json: Gitlab::Json.dump(service_ping_data) end end end diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb index fbaa754124c..817f82085e6 100644 --- a/app/controllers/concerns/authenticates_with_two_factor.rb +++ b/app/controllers/concerns/authenticates_with_two_factor.rb @@ -137,7 +137,7 @@ module AuthenticatesWithTwoFactor session[:credentialRequestOptions] = get_options session[:challenge] = get_options.challenge - gon.push(webauthn: { options: get_options.to_json }) + gon.push(webauthn: { options: Gitlab::Json.dump(get_options) }) end end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 2b2764d2e34..870320a79d9 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -86,7 +86,7 @@ class Projects::CommitController < Projects::ApplicationController respond_to do |format| format.json do - render json: @merge_requests.to_json + render json: Gitlab::Json.dump(@merge_requests) end end end diff --git a/app/controllers/projects/google_cloud/configuration_controller.rb b/app/controllers/projects/google_cloud/configuration_controller.rb index 06a6674d578..e109ab95d39 100644 --- a/app/controllers/projects/google_cloud/configuration_controller.rb +++ b/app/controllers/projects/google_cloud/configuration_controller.rb @@ -15,7 +15,7 @@ module Projects gcpRegions: gcp_regions, revokeOauthUrl: revoke_oauth_url } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_page) end diff --git a/app/controllers/projects/google_cloud/databases_controller.rb b/app/controllers/projects/google_cloud/databases_controller.rb index 77ee830fd24..b511a85b0b8 100644 --- a/app/controllers/projects/google_cloud/databases_controller.rb +++ b/app/controllers/projects/google_cloud/databases_controller.rb @@ -17,7 +17,8 @@ module Projects cloudsqlInstances: ::GoogleCloud::GetCloudsqlInstancesService.new(project).execute, emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg') } - @js_data = js_data.to_json + + @js_data = Gitlab::Json.dump(js_data) track_event(:render_page) end @@ -27,7 +28,7 @@ module Projects @title = title(product) - @js_data = { + js_data = { gcpProjects: gcp_projects, refs: refs, cancelPath: project_google_cloud_databases_path(project), @@ -35,7 +36,9 @@ module Projects formDescription: description(product), databaseVersions: Projects::GoogleCloud::CloudsqlHelper::VERSIONS[product], tiers: Projects::GoogleCloud::CloudsqlHelper::TIERS - }.to_json + } + + @js_data = Gitlab::Json.dump(js_data) track_event(:render_form) render template: 'projects/google_cloud/databases/cloudsql_form', formats: :html diff --git a/app/controllers/projects/google_cloud/deployments_controller.rb b/app/controllers/projects/google_cloud/deployments_controller.rb index f6cc8d5eafb..041486eb2fb 100644 --- a/app/controllers/projects/google_cloud/deployments_controller.rb +++ b/app/controllers/projects/google_cloud/deployments_controller.rb @@ -11,7 +11,7 @@ class Projects::GoogleCloud::DeploymentsController < Projects::GoogleCloud::Base enableCloudRunUrl: project_google_cloud_deployments_cloud_run_path(project), enableCloudStorageUrl: project_google_cloud_deployments_cloud_storage_path(project) } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_page) end diff --git a/app/controllers/projects/google_cloud/gcp_regions_controller.rb b/app/controllers/projects/google_cloud/gcp_regions_controller.rb index 2f0bc05030f..c51261721b2 100644 --- a/app/controllers/projects/google_cloud/gcp_regions_controller.rb +++ b/app/controllers/projects/google_cloud/gcp_regions_controller.rb @@ -14,7 +14,7 @@ class Projects::GoogleCloud::GcpRegionsController < Projects::GoogleCloud::BaseC refs: refs, cancelPath: project_google_cloud_configuration_path(project) } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_form) end diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb index 89d624764df..7b029e25ea2 100644 --- a/app/controllers/projects/google_cloud/service_accounts_controller.rb +++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb @@ -14,7 +14,7 @@ class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud:: refs: refs, cancelPath: project_google_cloud_configuration_path(project) } - @js_data = js_data.to_json + @js_data = Gitlab::Json.dump(js_data) track_event(:render_form) end diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb index 47557133ac8..6da70b5e157 100644 --- a/app/controllers/projects/graphs_controller.rb +++ b/app/controllers/projects/graphs_controller.rb @@ -104,7 +104,7 @@ class Projects::GraphsController < Projects::ApplicationController } end - render json: @log.to_json + render json: Gitlab::Json.dump(@log) end def tracking_namespace_source diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 36c050be76b..3251b1483c3 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -124,7 +124,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo @commits_count = @merge_request.commits_count + @merge_request.context_commits_count @diffs_count = get_diffs_count @issuable_sidebar = serializer.represent(@merge_request, serializer: 'sidebar') - @current_user_data = UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity).to_json + @current_user_data = Gitlab::Json.dump(UserSerializer.new(project: @project).represent(current_user, {}, MergeRequestCurrentUserEntity)) @show_whitespace_default = current_user.nil? || current_user.show_whitespace_in_diffs @file_by_file_default = current_user&.view_diffs_file_by_file @coverage_path = coverage_reports_project_merge_request_path(@project, @merge_request, format: :json) if @merge_request.has_coverage_reports? @@ -536,7 +536,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo render json: '', status: :no_content when :parsed - render json: report_comparison[:data].to_json, status: :ok + render json: Gitlab::Json.dump(report_comparison[:data]), status: :ok when :error render json: { status_reason: report_comparison[:status_reason] }, status: :bad_request else diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb index d24b232293b..9d3506d49b0 100644 --- a/app/controllers/projects/notes_controller.rb +++ b/app/controllers/projects/notes_controller.rb @@ -58,7 +58,7 @@ class Projects::NotesController < Projects::ApplicationController def outdated_line_change diff_lines = Rails.cache.fetch(['note', note.id, 'oudated_line_change'], expires_in: 7.days) do - ::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: note.noteable.source_project, note: note).execute.to_json + Gitlab::Json.dump(::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: note.noteable.source_project, note: note).execute) end render json: diff_lines diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index cda6c8abea7..6ad85d8a47c 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -23,9 +23,11 @@ module Projects def show if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project) - @triggers_json = ::Ci::TriggerSerializer.new.represent( + triggers = ::Ci::TriggerSerializer.new.represent( @project.triggers, current_user: current_user, project: @project - ).to_json + ) + + @triggers_json = Gitlab::Json.dump(triggers) end render diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb index 6d06b05c1e9..ed5fb838670 100644 --- a/app/controllers/projects/templates_controller.rb +++ b/app/controllers/projects/templates_controller.rb @@ -12,7 +12,7 @@ class Projects::TemplatesController < Projects::ApplicationController templates = @template_type.template_subsets(project) respond_to do |format| - format.json { render json: templates.to_json } + format.json { render json: Gitlab::Json.dump(templates) } end end @@ -20,7 +20,7 @@ class Projects::TemplatesController < Projects::ApplicationController template = @template_type.find(params[:key], project) respond_to do |format| - format.json { render json: template.to_json } + format.json { render json: Gitlab::Json.dump(template) } end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index b7b6e6534fb..56eb2a6de56 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -343,7 +343,7 @@ class ProjectsController < Projects::ApplicationController options['Commits'] = [ref] end - render json: options.to_json + render json: Gitlab::Json.dump(options) rescue Gitlab::Git::CommandError render json: { error: _('Unable to load refs') }, status: :service_unavailable end diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 7d4dd04c6d4..0310728d99f 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -108,7 +108,7 @@ class SearchController < ApplicationController @ref = params[:project_ref] if params[:project_ref].present? @filter = params[:filter] - render json: search_autocomplete_opts(term, filter: @filter).to_json + render json: Gitlab::Json.dump(search_autocomplete_opts(term, filter: @filter)) end def opensearch diff --git a/app/helpers/groups/group_members_helper.rb b/app/helpers/groups/group_members_helper.rb index 6a013a6c864..776666add63 100644 --- a/app/helpers/groups/group_members_helper.rb +++ b/app/helpers/groups/group_members_helper.rb @@ -5,10 +5,6 @@ module Groups::GroupMembersHelper AVATAR_SIZE = 40 - def group_member_select_options - { multiple: true, class: 'input-clamp qa-member-select-field ', scope: :all, email_user: true } - end - def group_members_app_data(group, members:, invited:, access_requests:, banned:, include_relations:, search:) { user: group_members_list_data(group, members, { param_name: :page, params: { invited_members_page: nil, search_invited: nil } }), diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb index 14ee6007a43..99da9a7af6c 100644 --- a/app/helpers/selects_helper.rb +++ b/app/helpers/selects_helper.rb @@ -1,30 +1,6 @@ # frozen_string_literal: true module SelectsHelper - def users_select_tag(id, opts = {}) - css_class = ["ajax-users-select"] - css_class << "multiselect" if opts[:multiple] - css_class << "skip_ldap" if opts[:skip_ldap] - css_class << (opts[:class] || '') - value = opts[:selected] || '' - html = { - class: css_class.join(' '), - data: users_select_data_attributes(opts) - } - - unless opts[:scope] == :all - project = opts[:project] || @project - - if project - html['data-project-id'] = project.id - elsif @group - html['data-group-id'] = @group.id - end - end - - hidden_field_tag(id, value, html) - end - def groups_select_tag(id, opts = {}) classes = Array.wrap(opts[:class]) classes << 'ajax-groups-select' @@ -68,22 +44,6 @@ module SelectsHelper hidden_field_tag(id, value, opts) end - - private - - def users_select_data_attributes(opts) - { - placeholder: opts[:placeholder] || 'Search for a user', - null_user: opts[:null_user] || false, - any_user: opts[:any_user] || false, - email_user: opts[:email_user] || false, - first_user: opts[:first_user] && current_user ? current_user.username : false, - current_user: opts[:current_user] || false, - author_id: opts[:author_id] || '', - skip_users: opts[:skip_users] ? opts[:skip_users].map(&:id) : nil, - qa_selector: opts[:qa_selector] || '' - } - end end SelectsHelper.prepend_mod_with('SelectsHelper') diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb index 323d759510e..b2bdbda9da9 100644 --- a/app/models/ci/bridge.rb +++ b/app/models/ci/bridge.rb @@ -183,7 +183,7 @@ module Ci false end - def prevent_rollback_deployment? + def outdated_deployment? false end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index b8511536e32..466e83c5cc6 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -445,9 +445,10 @@ module Ci manual? && starts_environment? && deployment&.blocked? end - def prevent_rollback_deployment? - strong_memoize(:prevent_rollback_deployment) do + def outdated_deployment? + strong_memoize(:outdated_deployment) do starts_environment? && + incomplete? && project.ci_forward_deployment_enabled? && deployment&.older_than_last_successful_deployment? end diff --git a/app/models/concerns/ci/has_status.rb b/app/models/concerns/ci/has_status.rb index 910885c833f..9a04776f1c6 100644 --- a/app/models/concerns/ci/has_status.rb +++ b/app/models/concerns/ci/has_status.rb @@ -110,6 +110,10 @@ module Ci COMPLETED_STATUSES.include?(status) end + def incomplete? + COMPLETED_STATUSES.exclude?(status) + end + def blocked? BLOCKED_STATUS.include?(status) end diff --git a/app/policies/ci/build_policy.rb b/app/policies/ci/build_policy.rb index b657b569e3e..5ef926ef2e3 100644 --- a/app/policies/ci/build_policy.rb +++ b/app/policies/ci/build_policy.rb @@ -27,8 +27,8 @@ module Ci false end - condition(:prevent_rollback) do - @subject.prevent_rollback_deployment? + condition(:outdated_deployment) do + @subject.outdated_deployment? end condition(:owner_of_job) do @@ -77,12 +77,14 @@ module Ci # Authorizing the user to access to protected entities. # There is a "jailbreak" mode to exceptionally bypass the authorization, # however, you should NEVER allow it, rather suspect it's a wrong feature/product design. - rule { ~can?(:jailbreak) & (archived | protected_ref | protected_environment | prevent_rollback) }.policy do + rule { ~can?(:jailbreak) & (archived | protected_ref | protected_environment) }.policy do prevent :update_build prevent :update_commit_status prevent :erase_build end + rule { outdated_deployment }.prevent :update_build + rule { can?(:admin_build) | (can?(:update_build) & owner_of_job & unprotected_ref) }.enable :erase_build rule { can?(:public_access) & branch_allows_collaboration }.policy do diff --git a/app/serializers/environment_serializer.rb b/app/serializers/environment_serializer.rb index 595b11f0233..46d5a488aea 100644 --- a/app/serializers/environment_serializer.rb +++ b/app/serializers/environment_serializer.rb @@ -52,15 +52,13 @@ class EnvironmentSerializer < BaseSerializer end def batch_load(resource) - temp_deployment_associations = deployment_associations - resource = resource.preload(environment_associations) Preloaders::Environments::DeploymentPreloader.new(resource) - .execute_with_union(:last_deployment, temp_deployment_associations) + .execute_with_union(:last_deployment, deployment_associations) Preloaders::Environments::DeploymentPreloader.new(resource) - .execute_with_union(:upcoming_deployment, temp_deployment_associations) + .execute_with_union(:upcoming_deployment, deployment_associations) resource.to_a.tap do |environments| environments.each do |environment| diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb index 22cd267806d..ec403b9eb9b 100644 --- a/app/services/ci/process_build_service.rb +++ b/app/services/ci/process_build_service.rb @@ -25,7 +25,7 @@ module Ci end def enqueue(build) - return build.drop!(:failed_outdated_deployment_job) if build.prevent_rollback_deployment? + return build.drop!(:failed_outdated_deployment_job) if build.outdated_deployment? build.enqueue end diff --git a/config/feature_flags/development/scan_result_role_action.yml b/config/feature_flags/development/scan_result_role_action.yml new file mode 100644 index 00000000000..e6a4a552350 --- /dev/null +++ b/config/feature_flags/development/scan_result_role_action.yml @@ -0,0 +1,8 @@ +--- +name: scan_result_role_action +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101464 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/377866 +milestone: '15.6' +type: development +group: group::security policies +default_enabled: false diff --git a/db/post_migrate/20221024121500_drop_fingerprint_from_sbom_sources.rb b/db/post_migrate/20221024121500_drop_fingerprint_from_sbom_sources.rb new file mode 100644 index 00000000000..83856cbe5dd --- /dev/null +++ b/db/post_migrate/20221024121500_drop_fingerprint_from_sbom_sources.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class DropFingerprintFromSbomSources < Gitlab::Database::Migration[2.0] + enable_lock_retries! + + def change + remove_column :sbom_sources, :fingerprint, :bytea + end +end diff --git a/db/schema_migrations/20221024121500 b/db/schema_migrations/20221024121500 new file mode 100644 index 00000000000..6db609001ad --- /dev/null +++ b/db/schema_migrations/20221024121500 @@ -0,0 +1 @@ +8449de1e73e2fb46698e0e160641c4132b99918792b0b3379d6009bab9eab0b7
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 4ee77cdbd25..947f0d01b61 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -21098,8 +21098,7 @@ CREATE TABLE sbom_sources ( created_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL, source_type smallint NOT NULL, - source jsonb DEFAULT '{}'::jsonb NOT NULL, - fingerprint bytea + source jsonb DEFAULT '{}'::jsonb NOT NULL ); CREATE SEQUENCE sbom_sources_id_seq diff --git a/doc/administration/configure.md b/doc/administration/configure.md index 40f03d25e8d..181dd4753d6 100644 --- a/doc/administration/configure.md +++ b/doc/administration/configure.md @@ -30,7 +30,7 @@ The tables lists features on the left and provides their capabilities to the rig ## Geo Capabilities -If your availability needs to span multiple zones or multiple locations, please read about [Geo](geo/index.md). +If your availability needs to span multiple zones or multiple locations, read about [Geo](geo/index.md). | | Availability | Recoverability | Data Resiliency | Performance | Risks/Trade-offs| |-|--------------|----------------|-----------------|-------------|-----------------| diff --git a/doc/administration/geo/disaster_recovery/planned_failover.md b/doc/administration/geo/disaster_recovery/planned_failover.md index 60101f5af8e..08b1a15522d 100644 --- a/doc/administration/geo/disaster_recovery/planned_failover.md +++ b/doc/administration/geo/disaster_recovery/planned_failover.md @@ -19,7 +19,7 @@ length of this window is determined by your replication capacity - once the data loss. This document assumes you already have a fully configured, working Geo setup. -Please read it and the [Disaster Recovery](index.md) failover +Read this document and the [Disaster Recovery](index.md) failover documentation in full before proceeding. Planned failover is a major operation, and if performed incorrectly, there is a high risk of data loss. Consider rehearsing the procedure until you are comfortable with the necessary steps and diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index 96447239116..a1c381cabde 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -45,7 +45,7 @@ repository storage is either: ## Before deploying Gitaly Cluster Gitaly Cluster provides the benefits of fault tolerance, but comes with additional complexity of setup and management. -Before deploying Gitaly Cluster, please review: +Before deploying Gitaly Cluster, review: - Existing [known issues](#known-issues). - [Snapshot limitations](#snapshot-backup-and-recovery-limitations). @@ -66,7 +66,7 @@ Contact your Technical Account Manager or customer support if you have any quest ### Known issues The following table outlines current known issues impacting the use of Gitaly Cluster. For -the current status of these issues, please refer to the referenced issues and epics. +the current status of these issues, refer to the referenced issues and epics. | Issue | Summary | How to avoid | |:--------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------| @@ -83,11 +83,11 @@ during a restore, we recommend using the [official backup and restore Rake tasks The [incremental backup method](../../raketasks/backup_gitlab.md#incremental-repository-backups) can be used to speed up Gitaly Cluster backups. -If you are unable to use either method, please contact customer support for restoration help. +If you are unable to use either method, contact customer support for restoration help. ### What to do if you are on Gitaly Cluster experiencing an issue or limitation -Please contact customer support for immediate help in restoration or recovery. +Contact customer support for immediate help in restoration or recovery. ## Directly accessing repositories @@ -410,7 +410,7 @@ relative path of the repository in the metadata store. ### Moving beyond NFS Engineering support for NFS for Git repositories is deprecated. Technical support is planned to be unavailable starting -November 22, 2022. Please see our [statement of support](https://about.gitlab.com/support/statement-of-support/#gitaly-and-nfs) +November 22, 2022. See our [statement of support](https://about.gitlab.com/support/statement-of-support/#gitaly-and-nfs) for more details. [Network File System (NFS)](https://en.wikipedia.org/wiki/Network_File_System) @@ -718,4 +718,4 @@ The second facet presents the only real solution. For this, we developed ## NFS deprecation notice Engineering support for NFS for Git repositories is deprecated. Technical support is planned to be -unavailable beginning November 22, 2022. For further information, please see our [NFS Deprecation](../nfs.md#gitaly-and-nfs-deprecation) documentation. +unavailable beginning November 22, 2022. For further information, see our [NFS Deprecation](../nfs.md#gitaly-and-nfs-deprecation) documentation. diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md index 1c5f0d43864..b8cbc9855c4 100644 --- a/doc/administration/gitaly/troubleshooting.md +++ b/doc/administration/gitaly/troubleshooting.md @@ -359,7 +359,7 @@ necessary because [this issue](https://gitlab.com/gitlab-org/gitaly/-/issues/252 If this error occurs even though file permissions are correct, it's likely that the Gitaly node is experiencing [clock drift](https://en.wikipedia.org/wiki/Clock_drift). -Please ensure that the GitLab and Gitaly nodes are synchronized and use an NTP time +Ensure that the GitLab and Gitaly nodes are synchronized and use an NTP time server to keep them synchronized if possible. ### Health check warnings diff --git a/doc/administration/monitoring/performance/grafana_configuration.md b/doc/administration/monitoring/performance/grafana_configuration.md index a003a3f25bc..49f92572cc5 100644 --- a/doc/administration/monitoring/performance/grafana_configuration.md +++ b/doc/administration/monitoring/performance/grafana_configuration.md @@ -141,7 +141,7 @@ These actions pose a temporary vulnerability while your old Grafana data is in u Deciding to take any of these actions should be weighed carefully with your need to access existing data and dashboards. -For more information and further mitigation details, please refer to our +For more information and further mitigation details, refer to our [blog post on the security release](https://about.gitlab.com/releases/2019/08/12/critical-security-release-gitlab-12-dot-1-dot-6-released/). Read more on: diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md index a4acafd16da..b72bc57fd60 100644 --- a/doc/administration/nfs.md +++ b/doc/administration/nfs.md @@ -52,7 +52,7 @@ If the issue is reproducible, or if it happens intermittently but regularly, Git NFS is not well-suited to a workload consisting of many small files, like Git repositories. NFS does provide a number of configuration options designed to improve performance. However, over time, a number of these mount options have proven to result in inconsistencies across multiple nodes mounting the NFS volume, up to and including data loss. Addressing these inconsistencies consume extraordinary development and support engineer time that hamper our ability to develop [Gitaly Cluster](gitaly/praefect.md), our purpose-built solution to addressing the deficiencies of NFS in this environment. -Please note that Gitaly Cluster provides highly-available Git repository storage. If this is not a requirement, single-node Gitaly backed by block storage is a suitable substitute. +Gitaly Cluster provides highly-available Git repository storage. If this is not a requirement, single-node Gitaly backed by block storage is a suitable substitute. Engineering support for NFS for Git repositories is deprecated. Technical support is planned to be unavailable from GitLab 15.0. No further enhancements are planned for this feature. diff --git a/doc/administration/package_information/defaults.md b/doc/administration/package_information/defaults.md index c6a33ed7ba9..381f35d7c12 100644 --- a/doc/administration/package_information/defaults.md +++ b/doc/administration/package_information/defaults.md @@ -68,7 +68,7 @@ over a network which will require, based on implementation, ports `111` and `2049` to be open. NOTE: -In some cases, the GitLab Registry will be automatically enabled by default. Please see [our documentation](../packages/container_registry.md) for more details +In some cases, the GitLab Registry will be automatically enabled by default. See [our documentation](../packages/container_registry.md) for more details. [^Consul-notes]: If using additional Consul functionality, more ports may need to be opened. See the [official documentation](https://www.consul.io/docs/install/ports#ports-table) for the list. diff --git a/doc/administration/package_information/signed_packages.md b/doc/administration/package_information/signed_packages.md index 34c8148e807..e4566be7534 100644 --- a/doc/administration/package_information/signed_packages.md +++ b/doc/administration/package_information/signed_packages.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Package Signatures **(FREE SELF)** -As of the release of GitLab 9.5 on August 22, 2017, GitLab provides signed Omnibus GitLab packages for RPM and DEB based distributions. This means that all packages provided on <https://packages.gitlab.com> are signed, starting with `9.5.0`, and all future versions of supported branches (for example `9.3.x` and `9.4.x` after August 22, 2017). Any package version prior to August 22, 2017, will not be signed. Please pass the appropriate argument to your package manager. (Example: `yum --nogpgcheck`) +As of the release of GitLab 9.5 on August 22, 2017, GitLab provides signed Omnibus GitLab packages for RPM and DEB based distributions. This means that all packages provided on <https://packages.gitlab.com> are signed, starting with `9.5.0`, and all future versions of supported branches (for example `9.3.x` and `9.4.x` after August 22, 2017). Any package version prior to August 22, 2017, will not be signed. Pass the appropriate argument to your package manager. (Example: `yum --nogpgcheck`) Omnibus GitLab packages produced by GitLab are created via the [Omnibus](https://github.com/chef/omnibus) tool, for which GitLab has added DEB signing via `debsigs` in [our own fork](https://gitlab.com/gitlab-org/omnibus). This addition, combined with the existing functionality of RPM signing, allows GitLab to provide signed packages for all supported distributions using DEB or RPM. diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md index 0ee48047944..ee90b120d05 100644 --- a/doc/administration/postgresql/replication_and_failover.md +++ b/doc/administration/postgresql/replication_and_failover.md @@ -606,7 +606,7 @@ Here is a list and description of each machine and the assigned IP: - `10.6.0.33`: PostgreSQL 3 - `10.6.0.41`: GitLab application -All passwords are set to `toomanysecrets`. Please do not use this password or derived hashes and the `external_url` for GitLab is `http://gitlab.example.com`. +All passwords are set to `toomanysecrets`. Do not use this password or derived hashes and the `external_url` for GitLab is `http://gitlab.example.com`. After the initial configuration, if a failover occurs, the PostgresSQL leader node changes to one of the available secondaries until it is failed back. @@ -957,7 +957,7 @@ For further details, see [Patroni documentation on this subject](https://patroni ### Switching from repmgr to Patroni WARNING: -Switching from repmgr to Patroni is straightforward, the other way around is *not*. Rolling back from Patroni to repmgr can be complicated and may involve deletion of data directory. If you need to do that, please contact GitLab support. +Switching from repmgr to Patroni is straightforward, the other way around is *not*. Rolling back from Patroni to repmgr can be complicated and may involve deletion of data directory. If you need to do that, contact GitLab support. You can switch an exiting database cluster to use Patroni instead of repmgr with the following steps: diff --git a/doc/administration/redis/replication_and_failover.md b/doc/administration/redis/replication_and_failover.md index 1c2515099fe..2ba19aa6f0a 100644 --- a/doc/administration/redis/replication_and_failover.md +++ b/doc/administration/redis/replication_and_failover.md @@ -66,7 +66,7 @@ When a **Primary** fails to respond, it's the application's responsibility (in our case GitLab) to handle timeout and reconnect (querying a **Sentinel** for a new **Primary**). -To get a better understanding on how to correctly set up Sentinel, please read +To get a better understanding on how to correctly set up Sentinel, read the [Redis Sentinel](https://redis.io/docs/manual/sentinel/) documentation first, as failing to configure it correctly can lead to data loss or can bring your whole cluster down, invalidating the failover effort. @@ -350,7 +350,7 @@ Now that the Redis servers are all set up, let's configure the Sentinel servers. If you are not sure if your Redis servers are working and replicating -correctly, please read the [Troubleshooting Replication](troubleshooting.md#troubleshooting-redis-replication) +correctly, read the [Troubleshooting Replication](troubleshooting.md#troubleshooting-redis-replication) and fix it before proceeding with Sentinel setup. You must have at least `3` Redis Sentinel servers, and they need to diff --git a/doc/administration/redis/replication_and_failover_external.md b/doc/administration/redis/replication_and_failover_external.md index 7904fb1ded8..23c9ce33c2d 100644 --- a/doc/administration/redis/replication_and_failover_external.md +++ b/doc/administration/redis/replication_and_failover_external.md @@ -64,7 +64,7 @@ settings outlined in We cannot stress enough the importance of reading the [replication and failover](replication_and_failover.md) documentation of the Omnibus Redis HA as it provides some invaluable information to the configuration -of Redis. Please proceed to read it before going forward with this guide. +of Redis. Read it before going forward with this guide. Before proceeding on setting up the new Redis instances, here are some requirements: diff --git a/doc/administration/system_hooks.md b/doc/administration/system_hooks.md index c8b985688b6..cdcd899b5d4 100644 --- a/doc/administration/system_hooks.md +++ b/doc/administration/system_hooks.md @@ -134,7 +134,7 @@ X-Gitlab-Event: System Hook ``` Note that `project_rename` is not triggered if the namespace changes. -Please refer to `group_rename` and `user_rename` for that case. +Refer to `group_rename` and `user_rename` for that case. **Project transferred:** diff --git a/doc/administration/troubleshooting/test_environments.md b/doc/administration/troubleshooting/test_environments.md index a249d5bd133..c4d191f8c0f 100644 --- a/doc/administration/troubleshooting/test_environments.md +++ b/doc/administration/troubleshooting/test_environments.md @@ -20,13 +20,13 @@ are only available internally at GitLab. ## Docker The following were tested on Docker containers running in the cloud. Support Engineers, -please see [these docs](https://gitlab.com/gitlab-com/dev-resources/tree/master/dev-resources#running-docker-containers) +see [these docs](https://gitlab.com/gitlab-com/dev-resources/tree/master/dev-resources#running-docker-containers) on how to run Docker containers on `dev-resources`. Other setups haven't been tested, but contributions are welcome. ### GitLab -Please see [our official Docker installation method](../../install/docker.md) +See [our official Docker installation method](../../install/docker.md) for how to run GitLab on Docker. ### SAML diff --git a/doc/api/deployments.md b/doc/api/deployments.md index 2c5161c44f5..3984bfe0eeb 100644 --- a/doc/api/deployments.md +++ b/doc/api/deployments.md @@ -503,8 +503,7 @@ Example responses: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35739) in GitLab 12.7. NOTE: -Not all deployments can be associated with merge requests. -Please see +Not all deployments can be associated with merge requests. See [Track what merge requests were deployed to an environment](../ci/environments/index.md#track-newly-included-merge-requests-per-deployment) for more information. diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md index c8f795ed88c..4d6d5e50245 100644 --- a/doc/api/error_tracking.md +++ b/doc/api/error_tracking.md @@ -1,6 +1,6 @@ --- stage: Monitor -group: Respond +group: Observability info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/api/feature_flag_specs.md b/doc/api/feature_flag_specs.md index b549c790aaa..d34fd0718c3 100644 --- a/doc/api/feature_flag_specs.md +++ b/doc/api/feature_flag_specs.md @@ -9,4 +9,4 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9566) in GitLab 12.5. This API was removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213369). -Please use [the new API](feature_flags.md) instead. +Use [the new API](feature_flags.md) instead. diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index c2f431ce31c..32b9c28b6e3 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -16230,6 +16230,7 @@ Represents vulnerability finding of a security report on the pipeline. | <a id="pipelinesecurityreportfindingconfidence"></a>`confidence` **{warning-solid}** | [`String`](#string) | **Deprecated** in 15.4. This field will be removed from the Finding domain model. | | <a id="pipelinesecurityreportfindingdescription"></a>`description` | [`String`](#string) | Description of the vulnerability finding. | | <a id="pipelinesecurityreportfindingdescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. | +| <a id="pipelinesecurityreportfindingdetails"></a>`details` | [`[VulnerabilityDetail!]!`](#vulnerabilitydetail) | Details of the security finding. | | <a id="pipelinesecurityreportfindingevidence"></a>`evidence` | [`VulnerabilityEvidence`](#vulnerabilityevidence) | Evidence for the vulnerability. | | <a id="pipelinesecurityreportfindingfalsepositive"></a>`falsePositive` | [`Boolean`](#boolean) | Indicates whether the vulnerability is a false positive. | | <a id="pipelinesecurityreportfindingidentifiers"></a>`identifiers` | [`[VulnerabilityIdentifier!]!`](#vulnerabilityidentifier) | Identifiers of the vulnerability finding. | diff --git a/doc/api/groups.md b/doc/api/groups.md index 4c5440dc0d8..cba54648705 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1413,7 +1413,7 @@ Parameters: ## Group members -Please consult the [Group Members](members.md) documentation. +See the [Group Members](members.md) documentation. ## LDAP Group Links diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md index 03965800bd4..ece7b784270 100644 --- a/doc/ci/environments/deployment_safety.md +++ b/doc/ci/environments/deployment_safety.md @@ -91,12 +91,13 @@ can be prevented in some circumstances. ### How to rollback to an outdated deployment -In some cases, you need to rollback to an outdated deployment. Current workarounds are: +> In GitLab 15.6, [rollback via job retry was introduced back](https://gitlab.com/gitlab-org/gitlab/-/issues/378359). -- Temporarily disable this feature, rollback and re-enable. -- Run a new pipeline with previous commit. It contains newer deployment jobs than the latest deployment. +In some cases, you need to rollback to an outdated deployment. +This feature explicitly allows rollback via [Environment Rollback](index.md#environment-rollback), +so that you can quickly rollback in an urgent case. -Please see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/378359) for more information about improving the usability. +Alternatively, you can run a new pipeline with a previous commit. It contains newer deployment jobs than the latest deployment. ### Example diff --git a/doc/development/packages/cleanup_policies.md b/doc/development/packages/cleanup_policies.md index ae6304e940d..aa60cde450b 100644 --- a/doc/development/packages/cleanup_policies.md +++ b/doc/development/packages/cleanup_policies.md @@ -1,6 +1,6 @@ --- stage: Package -group: Package +group: Container Registry info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments --- diff --git a/doc/development/packages/index.md b/doc/development/packages/index.md index ca39831b1d1..e6ec7e9654a 100644 --- a/doc/development/packages/index.md +++ b/doc/development/packages/index.md @@ -36,3 +36,4 @@ Development and architectural documentation for the container registry - [Dependency proxy structure](dependency_proxy.md) - [Settings](settings.md) - [Structure / Schema](structure.md) +- [Cleanup policies](cleanup_policies.md) diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index f1a23f06699..2ede9c35a01 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -282,7 +282,7 @@ end #### Stubbing methods within factories -You should avoid using `allow(object).to receive(:method)` in factories, as this makes the factory unable to be used with `let_it_be`. +You should avoid using `allow(object).to receive(:method)` in factories, as this makes the factory unable to be used with `let_it_be`, as described in [common test setup](#common-test-setup). Instead, you can use `stub_method` to stub the method: @@ -921,13 +921,16 @@ them unspecified, and look up the value after the row is created. #### Redis GitLab stores two main categories of data in Redis: cached items, and Sidekiq -jobs. +jobs. [View the full list of `Gitlab::Redis::Wrapper` descendants](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/redis.rb) that are backed by +a separate Redis instance. In most specs, the Rails cache is actually an in-memory store. This is replaced between specs, so calls to `Rails.cache.read` and `Rails.cache.write` are safe. However, if a spec makes direct Redis calls, it should mark itself with the `:clean_gitlab_redis_cache`, `:clean_gitlab_redis_shared_state` or -`:clean_gitlab_redis_queues` traits as appropriate. +`:clean_gitlab_redis_queues` traits as appropriate. To avoid triggering rate +limiting in specs, mark the spec with the `:clean_gitlab_redis_rate_limiting` +trait. #### Background jobs / Sidekiq diff --git a/doc/development/windows.md b/doc/development/windows.md index 5f32848da79..bf56e16344a 100644 --- a/doc/development/windows.md +++ b/doc/development/windows.md @@ -132,7 +132,7 @@ PowerShell has aliases for all of the following commands so you don't have to le - `ls` ---> `dir` - `rm` ---> `del` - `rm -rf nonemptydir` ---> `rmdir /S nonemptydir` -- `/` ---> `\` (path separator) +- `/` ---> <code>\</code> (path separator) - `cat` ---> `type` - `mv` ---> `move` - Redirection works the same (for example, `>` and `2>&1`) diff --git a/doc/user/markdown.md b/doc/user/markdown.md index 1a743ae99bb..c44047d74b3 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -331,7 +331,7 @@ However, you cannot mix the wrapping tags: ``` If your diff includes words in `` `code` `` font, make sure to escape each backtick `` ` `` with a -backslash `\`. Otherwise the diff highlight does not render correctly: +backslash <code>\</code>. Otherwise the diff highlight does not render correctly: ```markdown - {+ Just regular text +} diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md index 12656173d95..970f2e9b3cc 100644 --- a/doc/user/packages/container_registry/index.md +++ b/doc/user/packages/container_registry/index.md @@ -81,9 +81,9 @@ Images follow this naming convention: ``` If your project is `gitlab.example.com/mynamespace/myproject`, for example, -then your image must be named `gitlab.example.com/mynamespace/myproject/my-app` at a minimum. +then your image must be named `gitlab.example.com/mynamespace/myproject` at a minimum. -You can append additional names to the end of an image name, up to three levels deep. +You can append additional names to the end of an image name, up to two levels deep. For example, these are all valid image names for images within the project named `myproject`: diff --git a/doc/user/search/global_search/advanced_search_syntax.md b/doc/user/search/global_search/advanced_search_syntax.md index cd4bff0a20e..1e64bd4b22a 100644 --- a/doc/user/search/global_search/advanced_search_syntax.md +++ b/doc/user/search/global_search/advanced_search_syntax.md @@ -27,7 +27,7 @@ Advanced Search searches default project branches only. | `+` | And | [`display +banner`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=display+%2Bbanner&snippets=) | | `-` | Exclude | [`display -banner`](https://gitlab.com/search?group_id=9970&project_id=278964&scope=blobs&search=display+-banner) | | `*` | Partial | [`bug error 50*`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=bug+error+50%2A&snippets=) | -| `\` | Escape | [`\*md`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=%5C*md&group_id=9970&project_id=278964) | +| <code>\</code> | Escape | [`\*md`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=%5C*md&group_id=9970&project_id=278964) | ## Code search diff --git a/doc/user/ssh.md b/doc/user/ssh.md index be76ce487b6..00b97d64656 100644 --- a/doc/user/ssh.md +++ b/doc/user/ssh.md @@ -499,4 +499,4 @@ You can troubleshoot this by trying the following: - Verify your IDO/U2F hardware security key supports the key type provided. - Verify the version of OpenSSH is 8.2 or greater by - running `ssh -v`. + running `ssh -V`. diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb index 31e11f73fe7..ededc3db18e 100644 --- a/lib/gitlab/template/base_template.rb +++ b/lib/gitlab/template/base_template.rb @@ -47,6 +47,8 @@ module Gitlab { key: key, name: name, content: content } end + alias_method :as_json, :to_json + def <=>(other) name <=> other.name end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 9f8ce24afb1..78d7c34d036 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -22137,9 +22137,6 @@ msgstr "" msgid "Invite \"%{email}\" by email" msgstr "" -msgid "Invite \"%{trimmed}\" by email" -msgstr "" - msgid "Invite Members" msgstr "" @@ -35687,9 +35684,6 @@ msgstr "" msgid "Search for a group" msgstr "" -msgid "Search for a user" -msgstr "" - msgid "Search for an emoji" msgstr "" diff --git a/package.json b/package.json index bf0dbf59f9d..b5b6d5576a3 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", "@gitlab/svgs": "3.5.0", - "@gitlab/ui": "46.1.0", + "@gitlab/ui": "49.0.0", "@gitlab/visual-review-tools": "1.7.3", "@gitlab/web-ide": "0.0.1-dev-20220815034418", "@rails/actioncable": "6.1.4-7", diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb index dc6e496d081..706c880d097 100644 --- a/spec/features/projects/environments/environment_spec.rb +++ b/spec/features/projects/environments/environment_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe 'Environment' do - let(:project) { create(:project, :repository) } + let_it_be(:project) { create(:project, :repository) } let(:user) { create(:user) } let(:role) { :developer } @@ -17,7 +17,7 @@ RSpec.describe 'Environment' do end describe 'environment details page' do - let!(:environment) { create(:environment, project: project) } + let_it_be(:environment) { create(:environment, project: project) } let!(:permissions) {} let!(:deployment) {} let!(:action) {} @@ -160,10 +160,20 @@ RSpec.describe 'Environment' do end context 'with related deployable present' do - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, pipeline: pipeline, environment: environment.name) } + let_it_be(:previous_pipeline) { create(:ci_pipeline, project: project) } - let(:deployment) do + let_it_be(:previous_build) do + create(:ci_build, :success, pipeline: previous_pipeline, environment: environment.name) + end + + let_it_be(:previous_deployment) do + create(:deployment, :success, environment: environment, deployable: previous_build) + end + + let_it_be(:pipeline) { create(:ci_pipeline, project: project) } + let_it_be(:build) { create(:ci_build, pipeline: pipeline, environment: environment.name) } + + let_it_be(:deployment) do create(:deployment, :success, environment: environment, deployable: build) end @@ -171,12 +181,10 @@ RSpec.describe 'Environment' do visit_environment(environment) end - it 'does show build name' do - expect(page).to have_link("#{build.name} (##{build.id})") - end - - it 'shows the re-deploy button' do + it 'shows deployment information and buttons', :js do expect(page).to have_button('Re-deploy to environment') + expect(page).to have_button('Rollback environment') + expect(page).to have_link("#{build.name} (##{build.id})") end context 'with manual action' do diff --git a/spec/frontend/users_select/utils_spec.js b/spec/frontend/users_select/utils_spec.js index a09935d8a04..7a080ddaf0f 100644 --- a/spec/frontend/users_select/utils_spec.js +++ b/spec/frontend/users_select/utils_spec.js @@ -1,21 +1,10 @@ -import $ from 'jquery'; -import { getAjaxUsersSelectOptions, getAjaxUsersSelectParams } from '~/users_select/utils'; +import { getAjaxUsersSelectParams } from '~/users_select/utils'; const options = { fooBar: 'baz', activeUserId: 1, }; -describe('getAjaxUsersSelectOptions', () => { - it('returns options built from select data attributes', () => { - const $select = $('<select />', { 'data-foo-bar': 'baz', 'data-user-id': 1 }); - - expect( - getAjaxUsersSelectOptions($select, { fooBar: 'fooBar', activeUserId: 'user-id' }), - ).toEqual(options); - }); -}); - describe('getAjaxUsersSelectParams', () => { it('returns query parameters built from provided options', () => { expect( diff --git a/spec/frontend/work_items/components/work_item_due_date_spec.js b/spec/frontend/work_items/components/work_item_due_date_spec.js index 701406b9588..7ebaf8209c7 100644 --- a/spec/frontend/work_items/components/work_item_due_date_spec.js +++ b/spec/frontend/work_items/components/work_item_due_date_spec.js @@ -140,7 +140,7 @@ describe('WorkItemDueDate component', () => { beforeEach(() => { createComponent({ canUpdate: true, dueDate: '2022-12-31', startDate: '2022-12-31' }); - datePickerOpenSpy = jest.spyOn(wrapper.vm.$refs.dueDatePicker.calendar, 'show'); + datePickerOpenSpy = jest.spyOn(wrapper.vm.$refs.dueDatePicker, 'show'); findStartDatePicker().vm.$emit('input', startDate); findStartDatePicker().vm.$emit('close'); }); diff --git a/spec/helpers/groups/group_members_helper_spec.rb b/spec/helpers/groups/group_members_helper_spec.rb index 0d53225bbcf..fa8d4991d99 100644 --- a/spec/helpers/groups/group_members_helper_spec.rb +++ b/spec/helpers/groups/group_members_helper_spec.rb @@ -7,16 +7,6 @@ RSpec.describe Groups::GroupMembersHelper do let_it_be(:group) { create(:group) } - describe '.group_member_select_options' do - before do - helper.instance_variable_set(:@group, group) - end - - it 'returns an options hash' do - expect(helper.group_member_select_options).to include(multiple: true, scope: :all, email_user: true) - end - end - describe '#group_members_app_data' do include_context 'group_group_link' diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index f3d3fd2034c..0f20529f617 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -940,10 +940,8 @@ RSpec.describe Gitlab::Git::Repository do let(:options) { { ref: 'master', path: ['PROCESS.md', 'README.md'] } } def commit_files(commit) - Gitlab::GitalyClient::StorageSettings.allow_disk_access do - commit.deltas.flat_map do |delta| - [delta.old_path, delta.new_path].uniq.compact - end + commit.deltas.flat_map do |delta| + [delta.old_path, delta.new_path].uniq.compact end end diff --git a/spec/lib/gitlab/github_import/attachments_downloader_spec.rb b/spec/lib/gitlab/github_import/attachments_downloader_spec.rb index 57391e06192..dc9f939a19b 100644 --- a/spec/lib/gitlab/github_import/attachments_downloader_spec.rb +++ b/spec/lib/gitlab/github_import/attachments_downloader_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Gitlab::GithubImport::AttachmentsDownloader do let_it_be(:content_type) { 'application/octet-stream' } let(:content_length) { 1000 } - let(:chunk_double) { instance_double(HTTParty::FragmentWithResponse, code: 200) } + let(:chunk_double) { instance_double(HTTParty::ResponseFragment, code: 200) } let(:headers_double) do instance_double( HTTParty::Response, diff --git a/spec/lib/gitlab/webpack/file_loader_spec.rb b/spec/lib/gitlab/webpack/file_loader_spec.rb index 6475ef58611..c2e9cd8124d 100644 --- a/spec/lib/gitlab/webpack/file_loader_spec.rb +++ b/spec/lib/gitlab/webpack/file_loader_spec.rb @@ -31,8 +31,8 @@ RSpec.describe Gitlab::Webpack::FileLoader do stub_request(:get, "http://hostname:2000/public_path/#{error_file_path}").to_raise(StandardError) end - it "returns content when respondes succesfully" do - expect(Gitlab::Webpack::FileLoader.load(file_path)).to be(file_contents) + it "returns content when responds successfully" do + expect(Gitlab::Webpack::FileLoader.load(file_path)).to eq(file_contents) end it "raises error when 404" do diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 9713734e97a..d9fb225e8c0 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -605,8 +605,8 @@ RSpec.describe Ci::Build do end end - describe '#prevent_rollback_deployment?' do - subject { build.prevent_rollback_deployment? } + describe '#outdated_deployment?' do + subject { build.outdated_deployment? } let(:build) { create(:ci_build, :created, :with_deployment, project: project, environment: 'production') } @@ -624,21 +624,33 @@ RSpec.describe Ci::Build do it { expect(subject).to be_falsey } end - context 'when deployment cannot rollback' do + context 'when build is not an outdated deployment' do before do - expect(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(false) + allow(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(false) end it { expect(subject).to be_falsey } end - context 'when build can prevent rollback deployment' do + context 'when build is older than the latest deployment and still pending status' do before do - expect(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(true) + allow(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(true) end it { expect(subject).to be_truthy } end + + context 'when build is older than the latest deployment but succeeded once' do + let(:build) { create(:ci_build, :success, :with_deployment, project: project, environment: 'production') } + + before do + allow(build.deployment).to receive(:older_than_last_successful_deployment?).and_return(true) + end + + it 'returns false for allowing rollback' do + expect(subject).to be_falsey + end + end end describe '#schedulable?' do diff --git a/workhorse/internal/config/config.go b/workhorse/internal/config/config.go index a7ffe1700c8..7658b7288c9 100644 --- a/workhorse/internal/config/config.go +++ b/workhorse/internal/config/config.go @@ -159,7 +159,6 @@ func (c *Config) RegisterGoCloudURLOpeners() error { if err != nil { return err } - c.ObjectStorageConfig.URLMux.RegisterBucket(azureblob.Scheme, urlOpener) } @@ -168,14 +167,13 @@ func (c *Config) RegisterGoCloudURLOpeners() error { if err != nil { return err } - c.ObjectStorageConfig.URLMux.RegisterBucket(gcsblob.Scheme, urlOpener) } return nil } -func (creds *AzureCredentials) getURLOpener() (*azureURLOpener, error) { +func (creds *AzureCredentials) getURLOpener() (*azureblob.URLOpener, error) { accountName := azureblob.AccountName(creds.AccountName) accountKey := azureblob.AccountKey(creds.AccountKey) @@ -184,14 +182,10 @@ func (creds *AzureCredentials) getURLOpener() (*azureURLOpener, error) { return nil, fmt.Errorf("error creating Azure credentials: %w", err) } - pipeline := azureblob.NewPipeline(credential, azblob.PipelineOptions{}) - - return &azureURLOpener{ - &azureblob.URLOpener{ - AccountName: accountName, - Pipeline: pipeline, - Options: azureblob.Options{Credential: credential}, - }, + return &azureblob.URLOpener{ + AccountName: accountName, + Pipeline: azureblob.NewPipeline(credential, azblob.PipelineOptions{}), + Options: azureblob.Options{Credential: credential}, }, nil } diff --git a/workhorse/internal/config/url_openers.go b/workhorse/internal/config/url_openers.go deleted file mode 100644 index d3c96ee9eef..00000000000 --- a/workhorse/internal/config/url_openers.go +++ /dev/null @@ -1,51 +0,0 @@ -package config - -import ( - "context" - "fmt" - "net/url" - - "gocloud.dev/blob" - "gocloud.dev/blob/azureblob" -) - -// This code can be removed once https://github.com/google/go-cloud/pull/2851 is merged. - -// URLOpener opens Azure URLs like "azblob://mybucket". -// -// The URL host is used as the bucket name. -// -// The following query options are supported: -// - domain: The domain name used to access the Azure Blob storage (e.g. blob.core.windows.net) -type azureURLOpener struct { - *azureblob.URLOpener -} - -func (o *azureURLOpener) OpenBucketURL(ctx context.Context, u *url.URL) (*blob.Bucket, error) { - opts := new(azureblob.Options) - *opts = o.Options - - err := setOptionsFromURLParams(u.Query(), opts) - if err != nil { - return nil, err - } - return azureblob.OpenBucket(ctx, o.Pipeline, o.AccountName, u.Host, opts) -} - -func setOptionsFromURLParams(q url.Values, opts *azureblob.Options) error { - for param, values := range q { - if len(values) > 1 { - return fmt.Errorf("multiple values of %v not allowed", param) - } - - value := values[0] - switch param { - case "domain": - opts.StorageDomain = azureblob.StorageDomain(value) - default: - return fmt.Errorf("unknown query parameter %q", param) - } - } - - return nil -} diff --git a/workhorse/internal/config/url_openers_test.go b/workhorse/internal/config/url_openers_test.go deleted file mode 100644 index 6a851cacbb8..00000000000 --- a/workhorse/internal/config/url_openers_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package config - -import ( - "context" - "net/url" - "testing" - - "github.com/stretchr/testify/require" - "gocloud.dev/blob/azureblob" -) - -func TestURLOpeners(t *testing.T) { - cfg, err := LoadConfig(azureConfig) - require.NoError(t, err) - - require.NotNil(t, cfg.ObjectStorageCredentials, "Expected object storage credentials") - - require.NoError(t, cfg.RegisterGoCloudURLOpeners()) - require.NotNil(t, cfg.ObjectStorageConfig.URLMux) - - tests := []struct { - url string - valid bool - }{ - - { - url: "azblob://container/object", - valid: true, - }, - { - url: "azblob://container/object?domain=core.windows.net", - valid: true, - }, - { - url: "azblob://container/object?domain=core.windows.net&domain=test", - valid: false, - }, - { - url: "azblob://container/object?param=value", - valid: false, - }, - { - url: "s3://bucket/object", - valid: false, - }, - } - - for _, test := range tests { - t.Run(test.url, func(t *testing.T) { - ctx := context.Background() - url, err := url.Parse(test.url) - require.NoError(t, err) - - bucket, err := cfg.ObjectStorageConfig.URLMux.OpenBucketURL(ctx, url) - if bucket != nil { - defer bucket.Close() - } - - if test.valid { - require.NotNil(t, bucket) - require.NoError(t, err) - } else { - require.Error(t, err) - } - }) - } -} - -func TestTestURLOpenersForParams(t *testing.T) { - tests := []struct { - name string - currOpts azureblob.Options - query url.Values - wantOpts azureblob.Options - wantErr bool - }{ - { - name: "InvalidParam", - query: url.Values{ - "foo": {"bar"}, - }, - wantErr: true, - }, - { - name: "StorageDomain", - query: url.Values{ - "domain": {"blob.core.usgovcloudapi.net"}, - }, - wantOpts: azureblob.Options{StorageDomain: "blob.core.usgovcloudapi.net"}, - }, - { - name: "duplicate StorageDomain", - query: url.Values{ - "domain": {"blob.core.usgovcloudapi.net", "blob.core.windows.net"}, - }, - wantErr: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - o := &azureURLOpener{ - URLOpener: &azureblob.URLOpener{ - Options: test.currOpts, - }, - } - err := setOptionsFromURLParams(test.query, &o.Options) - - if test.wantErr { - require.NotNil(t, err) - } else { - require.Nil(t, err) - require.Equal(t, test.wantOpts, o.Options) - } - }) - } -} diff --git a/yarn.lock b/yarn.lock index ed6bdf1fa74..8c825fb2c80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1113,10 +1113,10 @@ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.5.0.tgz#226240b7aa93db986f4c6f7738ca2a1846b5234d" integrity sha512-/djPsJzUY7i/FaydRVt3ZyXiFf5HGNo1rg2mfLn1EpXvT4zc2ag5ECwnYcPb97KgqFCJX6Tk+Ndu8Wh3GoOW1g== -"@gitlab/ui@46.1.0": - version "46.1.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-46.1.0.tgz#df5918dfcf76ee444ad587f325d55555e8001de7" - integrity sha512-11zdly3bDWRqlbPo5kmhoDzcJ0n16kuhuxk2U4N8TMfHXgu6vUYp5NgjPrxzZRHlNVXsYiz7cAqifbr56fxTPg== +"@gitlab/ui@49.0.0": + version "49.0.0" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-49.0.0.tgz#dee2b7de7e4d7e281cd7ccf324d0fb5ad3086a5c" + integrity sha512-UOPiGi12wTvbqzJAWo1PDmtZXvcSzy5/auh8qKO9l3uYo4j0RpqYeloSkLvRSKs3V82lpVi0pyJt/S+mMzPjxA== dependencies: "@popperjs/core" "^2.11.2" bootstrap-vue "2.20.1" |