Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-09-17 00:11:22 +00:00
parent 6b73cf95a8
commit 190e96db65
45 changed files with 303 additions and 152 deletions

View File

@ -176,6 +176,5 @@ Layout/LineContinuationSpacing:
- 'spec/support/shared_examples/requests/api/notes_shared_examples.rb'
- 'spec/support/shared_examples/requests/api/resolvable_discussions_shared_examples.rb'
- 'spec/uploaders/file_mover_spec.rb'
- 'spec/views/devise/shared/_signup_box.html.haml_spec.rb'
- 'spec/views/projects/issues/show.html.haml_spec.rb'
- 'spec/views/projects/pages/show.html.haml_spec.rb'

View File

@ -1090,7 +1090,6 @@ RSpec/NamedSubject:
- 'ee/spec/tasks/gitlab/spdx_rake_spec.rb'
- 'ee/spec/validators/user_existence_validator_spec.rb'
- 'ee/spec/validators/user_id_existence_validator_spec.rb'
- 'ee/spec/views/devise/registrations/new.html.haml_spec.rb'
- 'ee/spec/workers/active_user_count_threshold_worker_spec.rb'
- 'ee/spec/workers/admin_emails_worker_spec.rb'
- 'ee/spec/workers/app_sec/dast/profile_schedule_worker_spec.rb'

View File

@ -61,6 +61,7 @@ module ResolvesMergeRequests
commit_count: [:metrics],
diff_stats_summary: [:metrics],
approved_by: [:approved_by_users],
merge_after: [:merge_schedule],
milestone: [:milestone],
security_auto_fix: [:author],
head_pipeline: [:merge_request_diff, { head_pipeline: [:merge_request] }],

View File

@ -100,6 +100,11 @@ module Types
method: :public_merge_status, null: true,
description: 'Merge status of the merge request.'
field :merge_after, ::Types::TimeType,
null: true,
description: 'Date after which the merge request can be merged.',
alpha: { milestone: '17.4' }
field :detailed_merge_status, ::Types::MergeRequests::DetailedMergeStatusEnum, null: true,
calls_gitaly: true,
description: 'Detailed merge status of the merge request.'
@ -347,6 +352,10 @@ module Types
object.metrics&.merged_by || object.merge_user
end
def merge_after
object.merge_schedule&.merge_after
end
def detailed_merge_status
::MergeRequests::Mergeability::DetailedMergeStatusService.new(merge_request: object).execute
end

View File

@ -112,7 +112,9 @@ module Ci
def connection
return unless available?
@connection ||= ::Fog::Storage.new(object_store.connection.to_hash.deep_symbolize_keys)
::Gitlab::SafeRequestStore.fetch(object_store_raw_config) do
::Fog::Storage.new(object_store.connection.to_hash.deep_symbolize_keys)
end
end
def fog_directory

View File

@ -66,6 +66,8 @@ class MergeRequest < ApplicationRecord
has_one :predictions, inverse_of: :merge_request
delegate :suggested_reviewers, to: :predictions
has_one :merge_schedule, class_name: 'MergeRequests::MergeSchedule', inverse_of: :merge_request
belongs_to :latest_merge_request_diff, class_name: 'MergeRequestDiff'
manual_inverse_association :latest_merge_request_diff, :merge_request
@ -378,6 +380,7 @@ class MergeRequest < ApplicationRecord
preload_routables.preload(
:assignees, :author, :unresolved_notes, :labels, :milestone,
:timelogs, :latest_merge_request_diff, :reviewers,
:merge_schedule,
target_project: :project_feature,
metrics: [:latest_closed_by, :merged_by]
)

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
module MergeRequests
class MergeSchedule < ApplicationRecord
self.table_name = 'merge_request_merge_schedules'
belongs_to :merge_request, optional: false, inverse_of: :merge_schedule
before_validation :set_sharding_key
def set_sharding_key
self.project_id = merge_request&.target_project&.id
end
end
end

View File

@ -4,24 +4,6 @@ module Onboarding
class Progress < ApplicationRecord
self.table_name = 'onboarding_progresses'
include IgnorableColumns
ignore_columns %i[
git_pull_at
subscription_created_at
scoped_label_created_at
security_scan_enabled_at
issue_auto_closed_at
repository_imported_at
repository_mirrored_at
secure_container_scanning_run_at
secure_secret_detection_run_at
secure_coverage_fuzzing_run_at
secure_cluster_image_scanning_run_at
secure_api_fuzzing_run_at
],
remove_with: '17.5', remove_after: '2024-09-14'
belongs_to :namespace, optional: false
validate :namespace_is_root_namespace

View File

@ -2,7 +2,9 @@
- form_resource_name = "new_#{resource_name}"
- button_class = local_assigns[:button_class]
= gitlab_ui_form_for(resource, as: form_resource_name, url: url, html: { class: 'gl-show-field-errors js-arkose-labs-form', aria: { live: 'assertive' }}, data: { testid: 'signup-form' }) do |f|
= gitlab_ui_form_for(resource, as: form_resource_name, url: url,
html: { class: 'gl-show-field-errors js-arkose-labs-form', aria: { live: 'assertive' }},
data: { testid: 'signup-form' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Gitlab::CurrentSettings.invisible_captcha_enabled
@ -21,8 +23,9 @@
= f.text_field :first_name,
class: 'form-control gl-form-input top js-block-emoji js-validate-length js-track-error',
data: { max_length: max_first_name_length,
max_length_message: s_('SignUp|First name is too long (maximum is %{max_length} characters).') % { max_length: max_first_name_length },
track_action_for_errors: tracking_label,
max_length_message: safe_format(s_('SignUp|First name is too long (maximum is %{max_length} characters).'),
max_length: max_first_name_length),
track_action_for_errors: preregistration_tracking_label,
testid: 'new-user-first-name-field' },
required: true,
title: _('This field is required.')
@ -31,8 +34,9 @@
= f.text_field :last_name,
class: 'form-control gl-form-input top js-block-emoji js-validate-length js-track-error',
data: { max_length: max_last_name_length,
max_length_message: s_('SignUp|Last name is too long (maximum is %{max_length} characters).') % { max_length: max_last_name_length },
track_action_for_errors: tracking_label,
max_length_message: safe_format(s_('SignUp|Last name is too long (maximum is %{max_length} characters).'),
max_length: max_last_name_length),
track_action_for_errors: preregistration_tracking_label,
testid: 'new-user-last-name-field' },
required: true,
title: _('This field is required.')
@ -40,36 +44,45 @@
= f.label :username, _('Username')
= f.text_field :username,
class: 'form-control gl-form-input middle js-block-emoji js-validate-length js-validate-username js-track-error',
data: signup_username_data_attributes.merge(track_action_for_errors: tracking_label),
data: signup_username_data_attributes.merge(track_action_for_errors: preregistration_tracking_label),
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
required: true,
title: _('Please create a username with only alphanumeric characters.')
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is already taken.')
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide= _('Checking username availability...')
%p.validation-error.gl-text-red-500.gl-field-error-ignore.gl-mt-2.field-validation.hide
= _('Username is already taken.')
%p.validation-success.gl-text-green-600.gl-field-error-ignore.gl-mt-2.field-validation.hide
= _('Username is available.')
%p.validation-pending.gl-field-error-ignore.gl-mt-2.field-validation.hide
= _('Checking username availability...')
- unless @invite_email.present?
.form-group
= f.label :email, _('Email')
= f.email_field :email,
class: 'form-control gl-form-input middle js-validate-email js-track-error',
data: { testid: 'new-user-email-field', track_action_for_errors: tracking_label },
data: { testid: 'new-user-email-field', track_action_for_errors: preregistration_tracking_label },
required: true,
title: _('Please provide a valid email address.')
%p.validation-hint.gl-field-hint.text-secondary= _('We recommend a work email address.')
%p.validation-warning.gl-field-error-ignore.text-secondary.hide= _('This email address does not look right, are you sure you typed it correctly?')
%p.validation-hint.gl-field-hint.text-secondary
= _('We recommend a work email address.')
%p.validation-warning.gl-field-error-ignore.text-secondary.hide
= _('This email address does not look right, are you sure you typed it correctly?')
-# This is used for providing entry to Jihu on email verification
= render_if_exists 'devise/shared/signup_email_additional_info'
.form-group.gl-mb-5
= f.label :password, _('Password')
%input.form-control.gl-form-input.js-password{ data: { id: "#{form_resource_name}_password",
title: s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length },
title: safe_format(s_('SignUp|Minimum length is %{minimum_password_length} characters.'),
minimum_password_length: @minimum_password_length),
minimum_password_length: @minimum_password_length,
testid: 'new-user-password-field',
track_action_for_errors: tracking_label,
track_action_for_errors: preregistration_tracking_label,
autocomplete: 'new-password',
name: "#{form_resource_name}[password]" } }
%p.gl-field-hint-valid.text-secondary= s_('SignUp|Minimum length is %{minimum_password_length} characters.') % { minimum_password_length: @minimum_password_length }
%p.gl-field-hint-valid.text-secondary
= safe_format(s_('SignUp|Minimum length is %{minimum_password_length} characters.'),
minimum_password_length: @minimum_password_length)
= render_if_exists 'shared/password_requirements_list', show_basic_requirements: true
-# This is used for providing entry to Jihu phone verification
= render_if_exists 'devise/shared/phone_verification', form: f
.form-group
@ -78,11 +91,9 @@
- elsif show_recaptcha_sign_up?
= recaptcha_tags nonce: content_security_policy_nonce
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true,
button_options: { class: button_class,
data: { testid: 'new-user-register-button', track_action: 'register', track_label: tracking_label }}) do
= button_text
= render 'devise/shared/terms_of_service_notice', button_text: button_text
= yield :omniauth_providers_bottom if show_omniauth_providers
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, block: true,
button_options: { class: "#{button_class} gl-mt-4",
data: { testid: 'new-user-register-button', track_action: 'register', track_label: preregistration_tracking_label }}) do
= button_text

View File

@ -7,16 +7,23 @@
= render "layouts/bizible"
= render_if_exists "layouts/google_tag_manager_body"
- content_for :omniauth_providers_bottom do
= render 'devise/shared/signup_omniauth_providers',
tracking_label: preregistration_tracking_label
.signup-page
= render 'devise/shared/signup_box',
url: registration_path(resource_name, registration_path_params),
button_text: _('Register'),
show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?,
tracking_label: preregistration_tracking_label
.gl-mb-3.gl-p-4
= render 'signup_box_form',
url: registration_path(resource_name, registration_path_params),
button_text: _('Continue')
- if omniauth_enabled? && button_based_providers_enabled?
.gl-text-center.gl-pt-5
%label.gl-font-normal
= _('Continue with:')
.gl-flex.gl-flex-col.gl-gap-3
- enabled_button_based_providers.each do |provider|
= render 'devise/shared/omniauth_provider_button',
href: omniauth_authorize_path(:user, provider, register_omniauth_params({})),
provider: provider,
classes: 'js-track-omni-auth',
data: { provider: provider, track_action: "#{provider}_sso", track_label: preregistration_tracking_label }
= render 'devise/shared/sign_in_link',
tracking_action: 'click_sign_in_from_registration_page',

View File

@ -1,8 +0,0 @@
.gl-mb-3.gl-p-4
= yield :omniauth_providers_top if show_omniauth_providers
= render 'devise/shared/signup_box_form',
button_text: button_text,
url: url,
show_omniauth_providers: omniauth_enabled? && button_based_providers_enabled?,
tracking_label: tracking_label

View File

@ -1,5 +0,0 @@
= render 'devise/shared/omniauth_provider_button',
href: href,
provider: provider,
classes: 'js-track-omni-auth',
data: { provider: provider, track_action: "#{provider}_sso", track_label: tracking_label }

View File

@ -1,9 +0,0 @@
.gl-text-center.gl-pt-5
%label.gl-font-normal
= _("Register with:")
.gl-flex.gl-flex-col.gl-gap-3
- providers.each do |provider|
= render 'devise/shared/signup_omniauth_provider_button',
href: omniauth_authorize_path(:user, provider, register_omniauth_params(local_assigns)),
provider: provider,
tracking_label: tracking_label

View File

@ -1,3 +0,0 @@
= render 'devise/shared/signup_omniauth_provider_list',
providers: enabled_button_based_providers,
tracking_label: local_assigns[:tracking_label]

View File

@ -10,6 +10,8 @@ path = "/gitleaks.toml"
regexes = [
# spotted in doc/user/application_security/secret_detection/index.md and some frontend specs
"glpat-1234567890abcdefghij",
# doc/user/application_security/secret_detection/remove_secrets_tutorial.md
"glpat-12345678901234567890",
# spec/frontend/lib/utils/secret_detection_spec.js
"glpat-cgyKc1k_AsnEpmP-5fRL",
"gldt-cgyKc1k_AsnEpmP-5fRL",

View File

@ -0,0 +1,12 @@
---
table_name: merge_request_merge_schedules
classes:
- MergeRequests::MergeSchedule
feature_categories:
- code_review_workflow
description: Stores timestamps for scheduled merges
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165092
milestone: '17.4'
gitlab_schema: gitlab_main_cell
sharding_key:
project_id: projects

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class CreateMergeRequestMergeSchedules < Gitlab::Database::Migration[2.2]
milestone '17.4'
def change
create_table :merge_request_merge_schedules do |t| # rubocop:disable Migration/EnsureFactoryForTable -- factory exists in spec/factories/merge_request_merge_schedule.rb
t.references :merge_request, foreign_key: { on_delete: :cascade }, index: false, null: false
t.datetime_with_timezone :merge_after
t.bigint :project_id, null: false
t.index :merge_request_id, unique: true
t.index :project_id
end
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class CreateMergeRequestMergeSchedulesShardingKeyFk < Gitlab::Database::Migration[2.2]
milestone '17.4'
disable_ddl_transaction!
def up
add_concurrent_foreign_key :merge_request_merge_schedules, :projects, column: :project_id, on_delete: :cascade
end
def down
with_lock_retries do
remove_foreign_key :merge_request_merge_schedules, column: :project_id
end
end
end

View File

@ -0,0 +1 @@
6dd9484b5c7d61943dae2ed684c8d84d0c0319e009c26d1bcbfcbe0ae69939e7

View File

@ -0,0 +1 @@
4e56708b920c40ba9c6050f2441f313715e3db134ad6114fb9091829506736c1

View File

@ -13199,6 +13199,22 @@ CREATE SEQUENCE merge_request_diffs_id_seq
ALTER SEQUENCE merge_request_diffs_id_seq OWNED BY merge_request_diffs.id;
CREATE TABLE merge_request_merge_schedules (
id bigint NOT NULL,
merge_request_id bigint NOT NULL,
merge_after timestamp with time zone,
project_id bigint NOT NULL
);
CREATE SEQUENCE merge_request_merge_schedules_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE merge_request_merge_schedules_id_seq OWNED BY merge_request_merge_schedules.id;
CREATE TABLE merge_request_metrics (
merge_request_id bigint NOT NULL,
latest_build_started_at timestamp without time zone,
@ -21922,6 +21938,8 @@ ALTER TABLE ONLY merge_request_diff_details ALTER COLUMN merge_request_diff_id S
ALTER TABLE ONLY merge_request_diffs ALTER COLUMN id SET DEFAULT nextval('merge_request_diffs_id_seq'::regclass);
ALTER TABLE ONLY merge_request_merge_schedules ALTER COLUMN id SET DEFAULT nextval('merge_request_merge_schedules_id_seq'::regclass);
ALTER TABLE ONLY merge_request_metrics ALTER COLUMN id SET DEFAULT nextval('merge_request_metrics_id_seq'::regclass);
ALTER TABLE ONLY merge_request_predictions ALTER COLUMN merge_request_id SET DEFAULT nextval('merge_request_predictions_merge_request_id_seq'::regclass);
@ -24263,6 +24281,9 @@ ALTER TABLE ONLY merge_request_diff_files
ALTER TABLE ONLY merge_request_diffs
ADD CONSTRAINT merge_request_diffs_pkey PRIMARY KEY (id);
ALTER TABLE ONLY merge_request_merge_schedules
ADD CONSTRAINT merge_request_merge_schedules_pkey PRIMARY KEY (id);
ALTER TABLE ONLY merge_request_metrics
ADD CONSTRAINT merge_request_metrics_pkey PRIMARY KEY (id);
@ -28945,6 +28966,10 @@ CREATE INDEX index_merge_request_diffs_on_project_id ON merge_request_diffs USIN
CREATE UNIQUE INDEX index_merge_request_diffs_on_unique_merge_request_id ON merge_request_diffs USING btree (merge_request_id) WHERE (diff_type = 2);
CREATE UNIQUE INDEX index_merge_request_merge_schedules_on_merge_request_id ON merge_request_merge_schedules USING btree (merge_request_id);
CREATE INDEX index_merge_request_merge_schedules_on_project_id ON merge_request_merge_schedules USING btree (project_id);
CREATE INDEX index_merge_request_metrics_on_first_deployed_to_production_at ON merge_request_metrics USING btree (first_deployed_to_production_at);
CREATE INDEX index_merge_request_metrics_on_latest_closed_at ON merge_request_metrics USING btree (latest_closed_at) WHERE (latest_closed_at IS NOT NULL);
@ -34063,6 +34088,9 @@ ALTER TABLE ONLY operations_strategies
ALTER TABLE ONLY lfs_objects_projects
ADD CONSTRAINT fk_a56e02279c FOREIGN KEY (lfs_object_id) REFERENCES lfs_objects(id) ON DELETE RESTRICT NOT VALID;
ALTER TABLE ONLY merge_request_merge_schedules
ADD CONSTRAINT fk_a5ff9339a9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_a6963e8447 FOREIGN KEY (target_project_id) REFERENCES projects(id) ON DELETE CASCADE;
@ -35242,6 +35270,9 @@ ALTER TABLE zoekt_tasks
ALTER TABLE ONLY ml_models
ADD CONSTRAINT fk_rails_51e87f7c50 FOREIGN KEY (project_id) REFERENCES projects(id);
ALTER TABLE ONLY merge_request_merge_schedules
ADD CONSTRAINT fk_rails_5294434bc3 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
ALTER TABLE ONLY elastic_group_index_statuses
ADD CONSTRAINT fk_rails_52b9969b12 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;

View File

@ -25665,6 +25665,7 @@ Defines which user roles, users, or groups can merge into a protected branch.
| <a id="mergerequestiid"></a>`iid` | [`String!`](#string) | Internal ID of the merge request. |
| <a id="mergerequestinprogressmergecommitsha"></a>`inProgressMergeCommitSha` | [`String`](#string) | Commit SHA of the merge request if merge is in progress. |
| <a id="mergerequestlabels"></a>`labels` | [`LabelConnection`](#labelconnection) | Labels of the merge request. (see [Connections](#connections)) |
| <a id="mergerequestmergeafter"></a>`mergeAfter` **{warning-solid}** | [`Time`](#time) | **Introduced** in GitLab 17.4. **Status**: Experiment. Date after which the merge request can be merged. |
| <a id="mergerequestmergecommitsha"></a>`mergeCommitSha` | [`String`](#string) | SHA of the merge request commit (set once merged). |
| <a id="mergerequestmergeerror"></a>`mergeError` | [`String`](#string) | Error message due to a merge error. |
| <a id="mergerequestmergeongoing"></a>`mergeOngoing` | [`Boolean!`](#boolean) | Indicates if a merge is currently occurring. |

View File

@ -17,6 +17,7 @@ DETAILS:
> - `with_merge_status_recheck` [changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115948) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `restrict_merge_status_recheck` to be ignored for requests from users insufficient permissions. Disabled by default.
> - `approvals_before_merge` [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/119503) in GitLab 16.0.
> - `prepared_at` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122001) in GitLab 16.1.
> - `merge_after` [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/165092) in GitLab 17.4.
All API calls to non-public information require authentication.
@ -118,6 +119,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -367,6 +369,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -553,6 +556,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -747,6 +751,7 @@ Example response:
"merged_by": null, // Deprecated and will be removed in API v5. Use `merge_user` instead.
"merge_user": null,
"merged_at": null,
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -1134,6 +1139,7 @@ Example response:
"merged_by": null,
"merge_user": null,
"merged_at": null,
"merge_after": "2018-09-07T11:16:00.000Z",
"closed_by": null,
"closed_at": null,
"target_branch": "master",
@ -1243,6 +1249,7 @@ Example response:
"merged_by": null,
"merge_user": null,
"merged_at": null,
"merge_after": "2018-09-07T11:16:00.000Z",
"closed_by": null,
"closed_at": null,
"target_branch": "master",
@ -1787,6 +1794,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -1960,6 +1968,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -2153,6 +2162,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -2354,6 +2364,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -2826,6 +2837,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,
@ -2990,6 +3002,7 @@ Example response:
"web_url": "https://gitlab.com/DouweM"
},
"merged_at": "2018-09-07T11:16:17.520Z",
"merge_after": "2018-09-07T11:16:00.000Z",
"prepared_at": "2018-09-04T11:16:17.520Z",
"closed_by": null,
"closed_at": null,

View File

@ -33,6 +33,27 @@ to make the shorter pipeline run, you must follow these guidelines when naming y
| Starting with `docs-` | `docs-update-api-issues` |
| Ending in `-docs` | `123-update-api-issues-docs` |
### Moving content
When you move content to a new location, and edit the content in the same merge request,
use separate commits.
Separate commits help the reviewer, because the MR diff for moved content
does not clearly highlight edits.
When you use separate commits, the reviewer can verify the location change
in the first commit diff, then the content changes in subsequent commits.
For example, if you move a page, but also update the content of the page:
1. In the first commit: Move the content to its new location and put [redirects](redirects.md) in place if required.
If you can, fix broken links in this commit.
1. In subsequent commits: Make content changes. Fix broken links if you haven't already.
1. In the merge request: Explain the commits in the MR description and in a
comment to the reviewer.
You can add as many commits as you want, but make sure the first commit only moves the content,
and does not edit it.
## Documentation labels
When you author an issue or merge request, choose the

View File

@ -32,7 +32,7 @@ GitLab from backup. The secrets file is stored at `/etc/gitlab/gitlab-secrets.js
## Create a database backup
A database backup is required to roll back a GitLab upgrade if you encounter issues.
Before upgrading GitLab, you should create a database-only backup. If you encounter issues during the GitLab upgrade, you can restore the database backup to roll back the upgrade. To create a database backup, run this command:
```shell
docker exec -t <container name> gitlab-backup create SKIP=artifacts,repositories,registry,uploads,builds,pages,lfs,packages,terraform_state
@ -40,3 +40,5 @@ docker exec -t <container name> gitlab-backup create SKIP=artifacts,repositories
The backup is written to `/var/opt/gitlab/backups` which should be on a
[volume mounted by Docker](installation.md#set-up-the-volumes-location).
For more information on using the backup to roll back an upgrade, see [Downgrade GitLab](upgrade.md#downgrade-gitlab).

View File

@ -64,6 +64,11 @@ module API
merge_request.public_merge_status
end
expose :detailed_merge_status
expose :merge_after do |merge_request, _options|
merge_request.merge_schedule&.merge_after
end
expose :diff_head_sha, as: :sha
expose :merge_commit_sha
expose :squash_commit_sha

View File

@ -9,7 +9,7 @@ module Gitlab
IMPORTED_OBJECT_MAX_RETRIES = 5
OVERRIDES = { user_contributions: :user }.freeze
OVERRIDES = { user_contributions: :user, merge_schedule: 'MergeRequests::MergeSchedule' }.freeze
EXISTING_OBJECT_RELATIONS = %i[].freeze
# This represents all relations that have unique key on `project_id` or `group_id`

View File

@ -3,10 +3,6 @@
module Gitlab
module UsageDataCounters
module IssueActivityUniqueCounter
ISSUE_CATEGORY = 'issues_edit'
ISSUE_ACTION = 'perform_issue_action'
ISSUE_LABEL = 'redis_hll_counters.issues_edit.issues_edit_total_unique_counts_monthly'
ISSUE_ASSIGNEE_CHANGED = 'g_project_management_issue_assignee_changed'
ISSUE_CREATED = 'g_project_management_issue_created'
ISSUE_CLOSED = 'g_project_management_issue_closed'

View File

@ -15277,6 +15277,9 @@ msgstr ""
msgid "Continue with overages"
msgstr ""
msgid "Continue with:"
msgstr ""
msgid "Continue…"
msgstr ""
@ -37966,9 +37969,6 @@ msgstr ""
msgid "Options"
msgstr ""
msgid "Or create your own GitLab account"
msgstr ""
msgid "Ordered list"
msgstr ""
@ -44870,9 +44870,6 @@ msgstr ""
msgid "Register with two-factor app"
msgstr ""
msgid "Register with:"
msgstr ""
msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
msgstr ""
@ -51467,9 +51464,6 @@ msgstr ""
msgid "Sign up"
msgstr ""
msgid "Sign up for your free trial with:"
msgstr ""
msgid "Sign-in count:"
msgstr ""

View File

@ -4,7 +4,7 @@ module QA
module Page
module Registration
class SignUp < Page::Base
view 'app/views/devise/shared/_signup_box_form.html.haml' do
view 'app/views/devise/registrations/_signup_box_form.html.haml' do
element 'new-user-first-name-field'
element 'new-user-last-name-field'
element 'new-user-email-field'

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
factory :merge_request_merge_schedule, class: 'MergeRequests::MergeSchedule' do
merge_request
end
end

View File

@ -228,7 +228,7 @@ RSpec.describe 'Group or Project invitations', :with_current_organization, :aggr
expect(page).to have_current_path(new_user_registration_path, ignore_query: true)
fill_in_sign_up_form(new_user, 'Register', invite: true)
fill_in_sign_up_form(new_user, invite: true)
expect(page).to have_current_path(group_path(group))
expect(page)

View File

@ -47,7 +47,7 @@ RSpec.describe 'Signup', :with_current_organization, :js, feature_category: :use
let(:terms_text) do
<<~TEXT.squish
By clicking Register or registering through a third party you accept the
By clicking Continue or registering through a third party you accept the
Terms of Use and acknowledge the Privacy Statement and Cookie Policy
TEXT
end
@ -130,7 +130,7 @@ RSpec.describe 'Signup', :with_current_organization, :js, feature_category: :use
fill_in 'new_user_username', with: 'new$user!username'
wait_for_requests
click_button "Register"
click_button _('Continue')
expect(page).to have_content("Please create a username with only alphanumeric characters.")
end

View File

@ -37,7 +37,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'], feature_category: :code_revie
squash_on_merge available_auto_merge_strategies
has_ci mergeable commits committers commits_without_merge_commits squash security_auto_fix default_squash_commit_message
auto_merge_strategy merge_user award_emoji prepared_at codequality_reports_comparer supports_lock_on_merge
mergeability_checks
mergeability_checks merge_after
allows_multiple_assignees allows_multiple_reviewers retargeted name
]

View File

@ -20,7 +20,7 @@ RSpec.describe ::API::Entities::MergeRequestBasic, feature_category: :code_revie
expected_fields = %i[
merged_by merge_user merged_at closed_by closed_at target_branch user_notes_count upvotes downvotes
author assignees assignee reviewers source_project_id target_project_id labels draft work_in_progress
milestone merge_when_pipeline_succeeds merge_status detailed_merge_status sha merge_commit_sha
milestone merge_when_pipeline_succeeds merge_status detailed_merge_status merge_after sha merge_commit_sha
squash_commit_sha discussion_locked should_remove_source_branch force_remove_source_branch prepared_at
reference references web_url time_stats squash task_completion_status has_conflicts blocking_discussions_resolved
imported imported_from

View File

@ -227,6 +227,7 @@ merge_requests:
- merge_request_context_commits
- merge_request_context_commit_diff_files
- merge_request_stage_events
- merge_schedule
- events
- merge_requests_closing_issues
- cached_closes_issues
@ -293,6 +294,8 @@ merge_request_diff_files:
merge_request_context_commits:
- merge_request
- diff_files
merge_schedule:
- merge_request
cleanup_schedule:
- merge_request
ci_pipelines:

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state, :clean_gitlab_redis_trace_chunks do
RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state, :clean_gitlab_redis_trace_chunks, feature_category: :pipeline_execution do
include ExclusiveLeaseHelpers
let_it_be(:build) { create(:ci_build, :running) }
@ -142,18 +142,29 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state, :clean_git
it { is_expected.to eq('Sample data in database') }
end
context 'when data_store is fog' do
context 'when data_store is fog', :request_store do
let(:data_store) { :fog }
let(:sample_data) { +'Sample data in fog' }
before do
build_trace_chunk.send(:unsafe_set_data!, +'Sample data in fog')
build_trace_chunk.send(:unsafe_set_data!, sample_data)
end
it { is_expected.to eq('Sample data in fog') }
it { is_expected.to eq(sample_data) }
it 'returns a new Fog store' do
expect(described_class.get_store_class(data_store)).to be_a(Ci::BuildTraceChunks::Fog)
end
it 'only initializes Fog::Storage once' do
RequestStore.clear!
expect(Fog::Storage).to receive(:new).and_call_original
2.times do
expect(build_trace_chunk.reload.build.trace_chunks.first.data).to eq(sample_data)
end
end
end
end

View File

@ -36,6 +36,7 @@ RSpec.describe MergeRequest, factory_default: :keep, feature_category: :code_rev
it { is_expected.to have_many(:reviews).inverse_of(:merge_request) }
it { is_expected.to have_many(:reviewed_by_users).through(:reviews).source(:author) }
it { is_expected.to have_one(:cleanup_schedule).inverse_of(:merge_request) }
it { is_expected.to have_one(:merge_schedule).class_name('MergeRequests::MergeSchedule').inverse_of(:merge_request) }
it { is_expected.to have_many(:created_environments).class_name('Environment').inverse_of(:merge_request) }
it { is_expected.to have_many(:assignment_events).class_name('ResourceEvents::MergeRequestAssignmentEvent').inverse_of(:merge_request) }

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe MergeRequests::MergeSchedule, feature_category: :code_review_workflow do
subject { create(:merge_request_merge_schedule) }
describe 'associations' do
it { is_expected.to belong_to(:merge_request).required }
end
describe 'callbacks' do
let(:merge_request) { create(:merge_request) }
let(:schedule) do
create(:merge_request_merge_schedule, merge_request: merge_request,
project_id: merge_request.target_project.id + 1)
end
it 'overrides project_id to the correct sharding key' do
expect(schedule.project_id).to eq(merge_request.target_project.id)
end
end
end

View File

@ -137,7 +137,7 @@ module LoginHelpers
def register_via(provider, uid, email, additional_info: {})
mock_auth_hash(provider, uid, email, additional_info: additional_info)
visit new_user_registration_path
expect(page).to have_content('Create an account using').or(have_content('Register with'))
expect(page).to have_content('Create an account using').or(have_content('Continue with'))
click_button Gitlab::Auth::OAuth::Provider.label_for(provider)
end

View File

@ -3,7 +3,7 @@
require 'spec_helper'
module SignUpHelpers
def fill_in_sign_up_form(new_user, submit_button_text = 'Register', invite: false)
def fill_in_sign_up_form(new_user, invite: false)
fill_in 'new_user_first_name', with: new_user.first_name
fill_in 'new_user_last_name', with: new_user.last_name
fill_in 'new_user_username', with: new_user.username
@ -16,7 +16,7 @@ module SignUpHelpers
yield if block_given?
click_button submit_button_text
click_button _('Continue')
end
def confirm_email(new_user)

View File

@ -1,10 +0,0 @@
# frozen_string_literal: true
RSpec.shared_examples 'issue_edit snowplow tracking' do
let(:category) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_CATEGORY }
let(:action) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_ACTION }
let(:label) { Gitlab::UsageDataCounters::IssueActivityUniqueCounter::ISSUE_LABEL }
let(:namespace) { project.namespace }
it_behaves_like 'Snowplow event tracking with RedisHLL context'
end

View File

@ -2,14 +2,13 @@
require 'spec_helper'
RSpec.describe 'devise/shared/_signup_box', feature_category: :system_access do
RSpec.describe 'devise/registrations/_signup_box_form', feature_category: :system_access do
before do
stub_devise
allow(view).to receive(:arkose_labs_enabled?).and_return(false)
allow(view).to receive(:show_omniauth_providers).and_return(false)
allow(view).to receive(:url).and_return('_url_')
allow(view).to receive(:button_text).and_return('')
allow(view).to receive(:tracking_label).and_return('')
allow(view).to receive(:preregistration_tracking_label).and_return('')
stub_template 'devise/shared/_error_messages.html.haml' => ''
end

View File

@ -0,0 +1,36 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'devise/registrations/new', feature_category: :system_access do
let(:resource) { Users::RegistrationsBuildService.new(nil, {}).execute }
let(:tracking_label) { '_some_registration_' }
subject { render && rendered }
before do
allow(view).to receive(:resource).and_return(resource)
allow(view).to receive(:resource_name).and_return(:user)
allow(view).to receive(:glm_tracking_params).and_return({})
allow(view).to receive(:registration_path_params).and_return({})
allow(view).to receive(:preregistration_tracking_label).and_return(tracking_label)
allow(view).to receive(:arkose_labs_enabled?)
end
context 'for omniauth provider buttons' do
let(:provider_label) { :github }
let(:tracking_action) { "#{provider_label}_sso" }
before do
allow(view).to receive(:providers).and_return([provider_label])
end
it { is_expected.to have_css("[data-track-action='#{tracking_action}'][data-track-label='#{tracking_label}']") }
it { is_expected.to have_content(_('Continue with:')) }
it { is_expected.to have_css('form[action="/users/auth/github"]') }
end
context 'without broadcast messaging' do
it { is_expected.not_to render_template('layouts/_broadcast') }
end
end

View File

@ -1,35 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'devise/shared/_signup_omniauth_provider_list', feature_category: :system_access do
let_it_be(:provider_label) { :github }.freeze
let_it_be(:tracking_label) { 'free_registration' }.freeze
let_it_be(:tracking_action) { "#{provider_label}_sso" }.freeze
subject { rendered }
before do
allow(view).to receive(:providers).and_return([provider_label])
allow(view).to receive(:tracking_label).and_return(tracking_label)
allow(view).to receive(:glm_tracking_params).and_return({})
render
end
shared_examples 'sso buttons have snowplow tracking' do
it 'contains tracking attributes' do
css = "[data-track-action='#{tracking_action}']"
css += "[data-track-label='#{tracking_label}']"
expect(rendered).to have_css(css)
end
end
it { is_expected.to have_content(_("Register with:")) }
it_behaves_like 'sso buttons have snowplow tracking'
it 'renders button in form' do
expect(rendered).to have_css('form[action="/users/auth/github"]')
end
end