diff --git a/app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss b/app/assets/stylesheets/page_bundles/signup.scss similarity index 76% rename from app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss rename to app/assets/stylesheets/page_bundles/signup.scss index 337b5b001fe..9ed48b693b9 100644 --- a/app/assets/stylesheets/page_bundles/experimental_separate_sign_up.scss +++ b/app/assets/stylesheets/page_bundles/signup.scss @@ -1,27 +1,6 @@ @import 'mixins_and_variables_and_functions'; .signup-page { - .page-wrap { - background-color: var(--gray-10, $gray-10); - } - - .signup-box-container { - max-width: 960px; - } - - .signup-box { - background-color: var(--white, $white); - box-shadow: 0 0 0 1px var(--border-color, $border-color); - border-radius: $border-radius; - } - - .form-control { - &:active, - &:focus { - background-color: var(--white, $white); - } - } - .devise-errors { h2 { font-size: $gl-font-size; diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 7fce61516dc..55683e3c23c 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -14,15 +14,12 @@ class RegistrationsController < Devise::RegistrationsController prepend_before_action :check_captcha, only: :create before_action :whitelist_query_limiting, :ensure_destroy_prerequisites_met, only: [:destroy] before_action :load_recaptcha, only: :new + before_action :set_invite_params, only: :new feature_category :authentication_and_authorization def new - if experiment_enabled?(:signup_flow) - @resource = build_resource - else - redirect_to new_user_session_path(anchor: 'register-pane') - end + @resource = build_resource end def create @@ -206,8 +203,8 @@ class RegistrationsController < Devise::RegistrationsController # Part of an experiment to build a new sign up flow. Will be resolved # with https://gitlab.com/gitlab-org/growth/engineering/issues/64 def choose_layout - if %w(welcome update_registration).include?(action_name) || experiment_enabled?(:signup_flow) - 'devise_experimental_separate_sign_up_flow' + if %w(welcome update_registration).include?(action_name) + 'welcome' else 'devise' end @@ -225,6 +222,10 @@ class RegistrationsController < Devise::RegistrationsController resource.state = BLOCKED_PENDING_APPROVAL_STATE end + + def set_invite_params + @invite_email = ActionController::Base.helpers.sanitize(params[:invite_email]) + end end RegistrationsController.prepend_if_ee('EE::RegistrationsController') diff --git a/app/models/project.rb b/app/models/project.rb index 7e4ec6c7036..d002d7edeb5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -571,6 +571,7 @@ class Project < ApplicationRecord scope :imported_from, -> (type) { where(import_type: type) } scope :with_tracing_enabled, -> { joins(:tracing_setting) } + scope :with_enabled_error_tracking, -> { joins(:error_tracking_setting).where(project_error_tracking_settings: { enabled: true }) } enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 } diff --git a/app/services/jira_connect/sync_service.rb b/app/services/jira_connect/sync_service.rb index 07a648bb8c9..f8855fb6deb 100644 --- a/app/services/jira_connect/sync_service.rb +++ b/app/services/jira_connect/sync_service.rb @@ -6,11 +6,11 @@ module JiraConnect self.project = project end - def execute(commits: nil, branches: nil, merge_requests: nil) + def execute(commits: nil, branches: nil, merge_requests: nil, update_sequence_id: nil) JiraConnectInstallation.for_project(project).each do |installation| client = Atlassian::JiraConnect::Client.new(installation.base_url, installation.shared_secret) - response = client.store_dev_info(project: project, commits: commits, branches: branches, merge_requests: merge_requests) + response = client.store_dev_info(project: project, commits: commits, branches: branches, merge_requests: merge_requests, update_sequence_id: update_sequence_id) log_response(response) end diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 2f75203ac62..a1e6e701c79 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -1,16 +1,6 @@ - page_title _("Sign up") -- if experiment_enabled?(:signup_flow) - .row - .col-lg-7 - %h1.mb-3.font-weight-bold.text-6.mt-0 - = html_escape(_("Speed up your DevOps%{br_tag}with GitLab")) % { br_tag: '
'.html_safe } - %p.text-3 - = _("GitLab is a single application for the entire software development lifecycle. From project planning and source code management to CI/CD, monitoring, and security.") - .col-lg-5.order-12 - .text-center.mb-3 - %h2.font-weight-bold= _('Register for GitLab') - = render 'devise/shared/experimental_separate_sign_up_flow_box' - = render 'devise/shared/sign_in_link' -- else +- add_page_specific_style 'page_bundles/signup' + +.signup-page = render 'devise/shared/signup_box' = render 'devise/shared/sign_in_link' diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index c466d2ce936..e57220a8b14 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -2,23 +2,21 @@ #signin-container - if any_form_based_providers_enabled? - = render 'devise/shared/tabs_ldap' - - else - - unless experiment_enabled?(:signup_flow) - = render 'devise/shared/tabs_normal' + = render 'devise/shared/tabs_ldap', render_signup_link: false .tab-content - if password_authentication_enabled_for_web? || ldap_sign_in_enabled? || crowd_enabled? = render 'devise/shared/signin_box' - -# Signup only makes sense if you can also sign-in - - if allow_signup? - = render 'devise/shared/signup_box' - -# Show a message if none of the mechanisms above are enabled - if !password_authentication_enabled_for_web? && !ldap_sign_in_enabled? && !(omniauth_enabled? && devise_mapping.omniauthable?) %div No authentication methods configured. + - if allow_signup? + %p.gl-mt-3 + = _("Don't have an account yet?") + = link_to _("Register now"), new_registration_path(:user, invite_email: @invite_email), data: { qa_selector: 'register_link' } + - if omniauth_enabled? && devise_mapping.omniauthable? && button_based_providers_enabled? .clearfix = render 'devise/shared/omniauth_box' diff --git a/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml b/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml deleted file mode 100644 index 1ad9e7c82b6..00000000000 --- a/app/views/devise/shared/_experimental_separate_sign_up_flow_box.html.haml +++ /dev/null @@ -1,38 +0,0 @@ -- max_first_name_length = max_last_name_length = 127 -- max_username_length = 255 -- min_username_length = 2 -.signup-box.p-3.mb-2 - .signup-body - = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f| - .devise-errors.mt-0 - = render "devise/shared/error_messages", resource: resource - - if Feature.enabled?(:invisible_captcha) - = invisible_captcha - .name.form-row - .col.form-group - = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold' - = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => _("First name is too long (maximum is %{max_length} characters).") % { max_length: max_first_name_length }, :qa_selector => 'new_user_firstname_field' }, required: true, title: _("This field is required.") - .col.form-group - = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold' - = f.text_field :last_name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_last_name_length, :max_length_message => _("Last name is too long (maximum is %{max_length} characters).") % { max_length: max_last_name_length }, :qa_selector => 'new_user_lastname_field' }, required: true, title: _("This field is required.") - .username.form-group - = f.label :username, class: 'label-bold' - = f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :min_length => min_username_length, :min_length_message => s_("SignUp|Username is too short (minimum is %{min_length} characters).") % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => _("Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.") - %p.validation-error.gl-field-error-ignore.field-validation.mt-1.hide.cred= _('Username is already taken.') - %p.validation-success.gl-field-error-ignore.field-validation.mt-1.hide.cgreen= _('Username is available.') - %p.validation-pending.gl-field-error-ignore.field-validation.mt-1.hide= _('Checking username availability...') - .form-group - = f.label :email, class: 'label-bold' - = f.email_field :email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.") - .form-group.append-bottom-20#password-strength - = f.label :password, class: 'label-bold' - = f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length } - %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length } - %div - - if show_recaptcha_sign_up? - = recaptcha_tags - .submit-container.mt-3 - = f.submit _("Register"), class: "btn-register gl-button btn btn-block btn-success mb-0 p-2", data: { qa_selector: 'new_user_register_button' } - = render 'devise/shared/terms_of_service_notice' - - if omniauth_enabled? && button_based_providers_enabled? - = render 'devise/shared/experimental_separate_sign_up_flow_omniauth_box' diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml index d217b47527a..ff93449194a 100644 --- a/app/views/devise/shared/_signin_box.html.haml +++ b/app/views/devise/shared/_signin_box.html.haml @@ -22,8 +22,3 @@ .login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' } .login-body = render 'devise/sessions/new_base' - -- if experiment_enabled?(:signup_flow) - %p.light.mt-2 - = _("Don't have an account yet?") - = link_to _("Register now"), new_registration_path(:user) diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index 4543fb8ec92..b5c2adb0b9a 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -1,36 +1,38 @@ - max_first_name_length = max_last_name_length = 127 - max_username_length = 255 - min_username_length = 2 -#register-pane.tab-pane.login-box{ role: 'tabpanel' } - .login-body - = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f| - .devise-errors - = render "devise/shared/error_messages", resource: resource - - if Feature.enabled?(:invisible_captcha) - = invisible_captcha - .name.form-row - .col.form-group - = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold' - = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => _("First name is too long (maximum is %{max_length} characters).") % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _("This field is required.") - .col.form-group - = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold' - = f.text_field :last_name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_last_name_length, :max_length_message => _("Last name is too long (maximum is %{max_length} characters).") % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _("This field is required.") - .username.form-group - = f.label :username, class: 'label-bold' - = f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :min_length => min_username_length, :min_length_message => s_("SignUp|Username is too short (minimum is %{min_length} characters).") % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.") - %p.validation-error.gl-field-error-ignore.field-validation.hide= _('Username is already taken.') - %p.validation-success.gl-field-error-ignore.field-validation.hide= _('Username is available.') - %p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking username availability...') - .form-group - = f.label :email, class: 'label-bold' - = f.email_field :email, value: @invite_email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.") - .form-group.append-bottom-20#password-strength - = f.label :password, class: 'label-bold' - = f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length } - %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length } - %div - - if show_recaptcha_sign_up? - = recaptcha_tags - .submit-container - = f.submit _("Register"), class: "btn-register btn", data: { qa_selector: 'new_user_register_button' } - = render 'devise/shared/terms_of_service_notice' +.gl-mb-3.gl-p-4.gl-border-gray-100.gl-border-1.gl-border-solid.gl-rounded-base + = form_for(resource, as: "new_#{resource_name}", url: registration_path(resource_name), html: { class: "new_new_user gl-show-field-errors", "aria-live" => "assertive" }) do |f| + .devise-errors + = render "devise/shared/error_messages", resource: resource + - if Feature.enabled?(:invisible_captcha) + = invisible_captcha + .name.form-row + .col.form-group + = f.label :first_name, _('First name'), for: 'new_user_first_name', class: 'label-bold' + = f.text_field :first_name, class: 'form-control top js-block-emoji js-validate-length', :data => { :max_length => max_first_name_length, :max_length_message => _("First name is too long (maximum is %{max_length} characters).") % { max_length: max_first_name_length }, :qa_selector => 'new_user_first_name_field' }, required: true, title: _("This field is required.") + .col.form-group + = f.label :last_name, _('Last name'), for: 'new_user_last_name', class: 'label-bold' + = f.text_field :last_name, class: "form-control top js-block-emoji js-validate-length", :data => { :max_length => max_last_name_length, :max_length_message => _("Last name is too long (maximum is %{max_length} characters).") % { max_length: max_last_name_length }, :qa_selector => 'new_user_last_name_field' }, required: true, title: _("This field is required.") + .username.form-group + = f.label :username, class: 'label-bold' + = f.text_field :username, class: "form-control middle js-block-emoji js-validate-length js-validate-username", :data => { :min_length => min_username_length, :min_length_message => s_("SignUp|Username is too short (minimum is %{min_length} characters).") % { min_length: min_username_length }, :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length }, :qa_selector => 'new_user_username_field' }, 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...') + .form-group + = f.label :email, class: 'label-bold' + = f.email_field :email, value: @invite_email, class: "form-control middle", data: { qa_selector: 'new_user_email_field' }, required: true, title: _("Please provide a valid email address.") + .form-group.append-bottom-20#password-strength + = f.label :password, class: 'label-bold' + = f.password_field :password, class: "form-control bottom", data: { qa_selector: 'new_user_password_field' }, required: true, pattern: ".{#{@minimum_password_length},}", title: _("Minimum length is %{minimum_password_length} characters.") % { minimum_password_length: @minimum_password_length } + %p.gl-field-hint.text-secondary= _('Minimum length is %{minimum_password_length} characters') % { minimum_password_length: @minimum_password_length } + %div + - if show_recaptcha_sign_up? + = recaptcha_tags + .submit-container + = f.submit _("Register"), class: "btn gl-button btn-success", data: { qa_selector: 'new_user_register_button' } + = render 'devise/shared/terms_of_service_notice' + - if omniauth_enabled? && button_based_providers_enabled? + = render 'devise/shared/signup_omniauth_providers' + diff --git a/app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml b/app/views/devise/shared/_signup_omniauth_providers.haml similarity index 100% rename from app/views/devise/shared/_experimental_separate_sign_up_flow_omniauth_box.haml rename to app/views/devise/shared/_signup_omniauth_providers.haml diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml index 9d0c3ad5787..1d12b30c58c 100644 --- a/app/views/layouts/_head.html.haml +++ b/app/views/layouts/_head.html.haml @@ -1,17 +1,4 @@ - page_description brand_title unless page_description - --# Needs a redirect on the client side since it's using an anchor to distinguish --# between sign in and registration. We need to inline the JS to not render --# anything from this page beforehand. --# Part of an experiment to build a new sign up flow. Will be removed again with --# https://gitlab.com/gitlab-org/growth/engineering/issues/64 -- if experiment_enabled?(:signup_flow) && current_path?("sessions#new") - = javascript_tag nonce: true do - :plain - if (window.location.hash === '#register-pane') { - window.location.replace("/users/sign_up") - } - - site_name = "GitLab" %head{ prefix: "og: http://ogp.me/ns#" } %meta{ charset: "utf-8" } diff --git a/app/views/layouts/devise_experimental_onboarding_issues.html.haml b/app/views/layouts/devise_experimental_onboarding_issues.html.haml index ec9867f9e1f..f768fba84ca 100644 --- a/app/views/layouts/devise_experimental_onboarding_issues.html.haml +++ b/app/views/layouts/devise_experimental_onboarding_issues.html.haml @@ -1,6 +1,6 @@ !!! 5 %html.devise-layout-html.navless{ class: system_message_class } - - add_page_specific_style 'page_bundles/experimental_separate_sign_up' + - add_page_specific_style 'page_bundles/signup' = render "layouts/head" %body.ui-indigo.signup-page{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } } = render "layouts/header/logo_with_title" diff --git a/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml b/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml deleted file mode 100644 index 6be62645768..00000000000 --- a/app/views/layouts/devise_experimental_separate_sign_up_flow.html.haml +++ /dev/null @@ -1,20 +0,0 @@ -!!! 5 -%html.devise-layout-html.navless{ class: system_message_class } - - add_page_specific_style 'page_bundles/experimental_separate_sign_up' - = render "layouts/head" - %body.ui-indigo.signup-page{ class: "#{client_class_list}", data: { page: body_data_page, qa_selector: 'signup_page' } } - = render "layouts/header/logo_with_title" - = render "layouts/init_client_detection_flags" - .page-wrap - .container.signup-box-container.navless-container - = render "layouts/broadcast" - .content - = render "layouts/flash" - = yield - %hr.footer-fixed - .footer-container - .container - .footer-links - = link_to _("Help"), help_path - = link_to _("About GitLab"), "https://about.gitlab.com/" - = footer_message diff --git a/app/views/layouts/welcome.html.haml b/app/views/layouts/welcome.html.haml new file mode 100644 index 00000000000..48921e9ff89 --- /dev/null +++ b/app/views/layouts/welcome.html.haml @@ -0,0 +1,8 @@ +!!! 5 +%html.subscriptions-layout-html{ lang: 'en' } + = render 'layouts/head' + %body.ui-indigo.d-flex.vh-100.gl-bg-gray-10 + = render "layouts/header/logo_with_title" + = render "layouts/broadcast" + .container.d-flex.flex-grow-1.m-0 + = yield diff --git a/app/views/registrations/welcome.html.haml b/app/views/registrations/welcome.html.haml index bebcc2152af..dfb2d508f3a 100644 --- a/app/views/registrations/welcome.html.haml +++ b/app/views/registrations/welcome.html.haml @@ -1,6 +1,6 @@ - page_title _('Your profile') -.row.gl-flex-grow-1.gl-bg-gray-10 +.row.gl-flex-grow-1 .d-flex.gl-flex-direction-column.gl-align-items-center.gl-w-full.gl-p-5 .edit-profile.login-page.d-flex.flex-column.gl-align-items-center.pt-lg-3 = render_if_exists "registrations/welcome/progress_bar" diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml index 9baa340376b..1b03225d48d 100644 --- a/app/views/shared/notes/_notes_with_form.html.haml +++ b/app/views/shared/notes/_notes_with_form.html.haml @@ -19,7 +19,7 @@ = render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete - elsif !current_user .disabled-comment.text-center.gl-mt-3 - - link_to_register = link_to(_("register"), new_session_path(:user, redirect_to_referer: 'yes', anchor: 'register-pane'), class: 'js-register-link') + - link_to_register = link_to(_("register"), new_user_registration_path(redirect_to_referer: 'yes'), class: 'js-register-link') - link_to_sign_in = link_to(_("sign in"), new_session_path(:user, redirect_to_referer: 'yes'), class: 'js-sign-in-link') = _("Please %{link_to_register} or %{link_to_sign_in} to comment").html_safe % { link_to_register: link_to_register, link_to_sign_in: link_to_sign_in } - elsif discussion_locked diff --git a/app/workers/jira_connect/sync_branch_worker.rb b/app/workers/jira_connect/sync_branch_worker.rb index 8c3416478fd..4c1c987353d 100644 --- a/app/workers/jira_connect/sync_branch_worker.rb +++ b/app/workers/jira_connect/sync_branch_worker.rb @@ -8,7 +8,7 @@ module JiraConnect feature_category :integrations loggable_arguments 1, 2 - def perform(project_id, branch_name, commit_shas) + def perform(project_id, branch_name, commit_shas, update_sequence_id = nil) project = Project.find_by_id(project_id) return unless project @@ -16,7 +16,7 @@ module JiraConnect branches = [project.repository.find_branch(branch_name)] if branch_name.present? commits = project.commits_by(oids: commit_shas) if commit_shas.present? - JiraConnect::SyncService.new(project).execute(commits: commits, branches: branches) + JiraConnect::SyncService.new(project).execute(commits: commits, branches: branches, update_sequence_id: update_sequence_id) end end end diff --git a/app/workers/jira_connect/sync_merge_request_worker.rb b/app/workers/jira_connect/sync_merge_request_worker.rb index b78bb8dfe16..f45ab38f35d 100644 --- a/app/workers/jira_connect/sync_merge_request_worker.rb +++ b/app/workers/jira_connect/sync_merge_request_worker.rb @@ -7,12 +7,12 @@ module JiraConnect queue_namespace :jira_connect feature_category :integrations - def perform(merge_request_id) + def perform(merge_request_id, update_sequence_id = nil) merge_request = MergeRequest.find_by_id(merge_request_id) return unless merge_request && merge_request.project - JiraConnect::SyncService.new(merge_request.project).execute(merge_requests: [merge_request]) + JiraConnect::SyncService.new(merge_request.project).execute(merge_requests: [merge_request], update_sequence_id: update_sequence_id) end end end diff --git a/changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml b/changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml new file mode 100644 index 00000000000..8a602a858bd --- /dev/null +++ b/changelogs/unreleased/250323-move-projects_with_error_tracking_enabled-to-core.yml @@ -0,0 +1,5 @@ +--- +title: Moves projects_with_error_tracking_enabled ping usage to Core +merge_request: 46556 +author: +type: changed diff --git a/changelogs/unreleased/nicolasdular-split-signin-and-signup.yml b/changelogs/unreleased/nicolasdular-split-signin-and-signup.yml new file mode 100644 index 00000000000..f4fdf10acad --- /dev/null +++ b/changelogs/unreleased/nicolasdular-split-signin-and-signup.yml @@ -0,0 +1,5 @@ +--- +title: Split sign in and sign up pages +merge_request: 42592 +author: +type: changed diff --git a/config/application.rb b/config/application.rb index 0f550f40ea9..b01bd92e5e1 100644 --- a/config/application.rb +++ b/config/application.rb @@ -183,7 +183,7 @@ module Gitlab config.assets.precompile << "page_bundles/environments.css" config.assets.precompile << "page_bundles/error_tracking_details.css" config.assets.precompile << "page_bundles/error_tracking_index.css" - config.assets.precompile << "page_bundles/experimental_separate_sign_up.css" + config.assets.precompile << "page_bundles/signup.css" config.assets.precompile << "page_bundles/ide.css" config.assets.precompile << "page_bundles/issues_list.css" config.assets.precompile << "page_bundles/jira_connect.css" diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md index d073ed81afa..f5627cef621 100644 --- a/doc/administration/object_storage.md +++ b/doc/administration/object_storage.md @@ -262,6 +262,7 @@ Here are the valid connection parameters for GCS: | `google_project` | GCP project name | `gcp-project-12345` | | `google_client_email` | The email address of the service account | `foo@gcp-project-12345.iam.gserviceaccount.com` | | `google_json_key_location` | The JSON key path | `/path/to/gcp-project-12345-abcde.json` | +| `google_application_default` | Set to `true` to use [Google Cloud Application Default Credentials](https://cloud.google.com/docs/authentication/production#automatically) to locate service account credentials. | NOTE: **Note:** The service account must have permission to access the bucket. @@ -280,6 +281,33 @@ gitlab_rails['object_store']['connection'] = { } ``` +##### Google example with ADC (consolidated form) + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275979) in GitLab 13.6. + +Google Cloud Application Default Credentials (ADC) are typically +used with GitLab to use the default service account. This eliminates the +need to supply credentials for the instance. For example: + +```ruby +gitlab_rails['object_store']['connection'] = { + 'provider' => 'Google', + 'google_project' => '', + 'google_application_default' => true +} +``` + +If you use ADC, be sure that: + +- The service account that you use has the +[`iam.serviceAccounts.signBlob` permission](https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob). + Typically this is done by granting the `Service Account Token Creator` role to the service account. +- Your virtual machines have the [correct access scopes to access Google Cloud APIs](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#changeserviceaccountandscopes). If the machines do not have the right scope, the error logs may show: + + ```markdown + Google::Apis::ClientError (insufficientPermissions: Request had insufficient authentication scopes.) + ``` + #### Azure Blob storage > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25877) in GitLab 13.4. diff --git a/doc/raketasks/generate_sample_prometheus_data.md b/doc/raketasks/generate_sample_prometheus_data.md index ef2376da0a9..f37aa95c63b 100644 --- a/doc/raketasks/generate_sample_prometheus_data.md +++ b/doc/raketasks/generate_sample_prometheus_data.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Monitor +group: Health info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md index 948fee9230c..a03c8e758de 100644 --- a/doc/subscriptions/gitlab_com/index.md +++ b/doc/subscriptions/gitlab_com/index.md @@ -57,7 +57,7 @@ To subscribe to GitLab.com: - **For individuals**: 1. Create a user account for yourself using our - [sign up page](https://gitlab.com/users/sign_in#register-pane). + [sign up page](https://gitlab.com/users/sign_up). 1. Visit the [billing page](https://gitlab.com/profile/billings) under your profile. 1. Select the **Bronze**, **Silver**, or **Gold** GitLab.com plan through the @@ -70,7 +70,7 @@ To subscribe to GitLab.com: 1. Proceed to checkout. - **For groups**: 1. Create a user account for yourself using our - [sign up page](https://gitlab.com/users/sign_in#register-pane). + [sign up page](https://gitlab.com/users/sign_up). 1. Create a [group](../../user/group/index.md). GitLab groups help assemble related projects together allowing you to grant members access to several projects at once. A group is not required if you plan on having projects inside a personal diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md index 09bfa7afc9e..cf5e4591a50 100644 --- a/doc/user/profile/account/create_accounts.md +++ b/doc/user/profile/account/create_accounts.md @@ -14,9 +14,9 @@ You can create users: ## Create users on sign in page -If you have [sign-up enabled](../../admin_area/settings/sign_up_restrictions.md), users can create their own accounts using the **Register** tab on the sign in page. +If you have [sign-up enabled](../../admin_area/settings/sign_up_restrictions.md), users can create their own accounts by selecting "Register now" on the sign-in page, or navigate to `https://gitlab.example.com/users/sign_up`. -![Register Tab](img/register_tab.png) +![Register Tab](img/register_v13_6.png) ## Create users in Admin Area diff --git a/doc/user/profile/account/img/register_tab.png b/doc/user/profile/account/img/register_tab.png deleted file mode 100644 index 4bbb4e62687..00000000000 Binary files a/doc/user/profile/account/img/register_tab.png and /dev/null differ diff --git a/doc/user/profile/account/img/register_v13_6.png b/doc/user/profile/account/img/register_v13_6.png new file mode 100644 index 00000000000..7c6eb04de79 Binary files /dev/null and b/doc/user/profile/account/img/register_v13_6.png differ diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb index 0b578c03782..d548251b602 100644 --- a/lib/atlassian/jira_connect/client.rb +++ b/lib/atlassian/jira_connect/client.rb @@ -3,19 +3,24 @@ module Atlassian module JiraConnect class Client < Gitlab::HTTP + def self.generate_update_sequence_id + Gitlab::Metrics::System.monotonic_time.to_i + end + def initialize(base_uri, shared_secret) @base_uri = base_uri @shared_secret = shared_secret end - def store_dev_info(project:, commits: nil, branches: nil, merge_requests: nil) + def store_dev_info(project:, commits: nil, branches: nil, merge_requests: nil, update_sequence_id: nil) dev_info_json = { repositories: [ Serializers::RepositoryEntity.represent( project, commits: commits, branches: branches, - merge_requests: merge_requests + merge_requests: merge_requests, + update_sequence_id: update_sequence_id ) ] }.to_json diff --git a/lib/atlassian/jira_connect/serializers/base_entity.rb b/lib/atlassian/jira_connect/serializers/base_entity.rb index c5490aa3f54..94deb174a45 100644 --- a/lib/atlassian/jira_connect/serializers/base_entity.rb +++ b/lib/atlassian/jira_connect/serializers/base_entity.rb @@ -9,12 +9,12 @@ module Atlassian format_with(:string) { |value| value.to_s } - expose :monotonic_time, as: :updateSequenceId + expose :update_sequence_id, as: :updateSequenceId private - def monotonic_time - Gitlab::Metrics::System.monotonic_time.to_i + def update_sequence_id + options[:update_sequence_id] || Client.generate_update_sequence_id end end end diff --git a/lib/atlassian/jira_connect/serializers/repository_entity.rb b/lib/atlassian/jira_connect/serializers/repository_entity.rb index 819ca2b62e0..9ae88ea21d1 100644 --- a/lib/atlassian/jira_connect/serializers/repository_entity.rb +++ b/lib/atlassian/jira_connect/serializers/repository_entity.rb @@ -15,13 +15,13 @@ module Atlassian end expose :commits do |project, options| - JiraConnect::Serializers::CommitEntity.represent options[:commits], project: project + JiraConnect::Serializers::CommitEntity.represent options[:commits], project: project, update_sequence_id: options[:update_sequence_id] end expose :branches do |project, options| - JiraConnect::Serializers::BranchEntity.represent options[:branches], project: project + JiraConnect::Serializers::BranchEntity.represent options[:branches], project: project, update_sequence_id: options[:update_sequence_id] end expose :pullRequests do |project, options| - JiraConnect::Serializers::PullRequestEntity.represent options[:merge_requests], project: project + JiraConnect::Serializers::PullRequestEntity.represent options[:merge_requests], project: project, update_sequence_id: options[:update_sequence_id] end end end diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index ab49c3e6829..c4c372b0806 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -617,7 +617,8 @@ module Gitlab operations_dashboard_default_dashboard: count(::User.active.with_dashboard('operations').where(time_period), start: user_minimum_id, finish: user_maximum_id), - projects_with_tracing_enabled: distinct_count(::Project.with_tracing_enabled.where(time_period), :creator_id) + projects_with_tracing_enabled: distinct_count(::Project.with_tracing_enabled.where(time_period), :creator_id), + projects_with_error_tracking_enabled: distinct_count(::Project.with_enabled_error_tracking.where(time_period), :creator_id) } end # rubocop: enable CodeReuse/ActiveRecord diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6bf07db03c7..11367498406 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -22016,9 +22016,6 @@ msgstr "" msgid "Register device" msgstr "" -msgid "Register for GitLab" -msgstr "" - msgid "Register now" msgstr "" @@ -25305,9 +25302,6 @@ msgstr "" msgid "Specify the following URL during the Runner setup:" msgstr "" -msgid "Speed up your DevOps%{br_tag}with GitLab" -msgstr "" - msgid "Squash commit message" msgstr "" @@ -29246,9 +29240,6 @@ msgstr "" msgid "Username is available." msgstr "" -msgid "Username is too long (maximum is %{max_length} characters)." -msgstr "" - msgid "Username or email" msgstr "" diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index 8eb28eb53e7..265e2b7573c 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -125,9 +125,9 @@ module QA click_element :sign_in_tab end - def switch_to_register_tab + def switch_to_register_page set_initial_password_if_present - click_element :register_tab + click_element :register_link end def switch_to_ldap_tab diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb index 5cd4147e154..ca30ff12480 100644 --- a/qa/qa/resource/user.rb +++ b/qa/qa/resource/user.rb @@ -75,7 +75,7 @@ module QA end else Page::Main::Login.perform do |login| - login.switch_to_register_tab + login.switch_to_register_page end Page::Main::SignUp.perform do |signup| signup.sign_up!(self) diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb index 31eaf3c83a5..cc7b469b3b8 100644 --- a/spec/controllers/registrations_controller_spec.rb +++ b/spec/controllers/registrations_controller_spec.rb @@ -12,30 +12,10 @@ RSpec.describe RegistrationsController do describe '#new' do subject { get :new } - context 'with the experimental signup flow enabled and the user is part of the experimental group' do - before do - stub_experiment(signup_flow: true) - stub_experiment_for_user(signup_flow: true) - end - - it 'renders new template and sets the resource variable' do - expect(subject).to render_template(:new) - expect(response).to have_gitlab_http_status(:ok) - expect(assigns(:resource)).to be_a(User) - end - end - - context 'with the experimental signup flow enabled and the user is part of the control group' do - before do - stub_experiment(signup_flow: true) - stub_experiment_for_user(signup_flow: false) - end - - it 'renders new template and sets the resource variable' do - subject - expect(response).to have_gitlab_http_status(:found) - expect(response).to redirect_to(new_user_session_path(anchor: 'register-pane')) - end + it 'renders new template and sets the resource variable' do + expect(subject).to render_template(:new) + expect(response).to have_gitlab_http_status(:ok) + expect(assigns(:resource)).to be_a(User) end end @@ -426,12 +406,10 @@ RSpec.describe RegistrationsController do describe '#welcome' do subject { get :welcome } - it 'renders the devise_experimental_separate_sign_up_flow layout' do + it 'renders the welcome layout' do sign_in(create(:user)) - expected_layout = Gitlab.ee? ? :checkout : :devise_experimental_separate_sign_up_flow - - expect(subject).to render_template(expected_layout) + expect(subject).to render_template(:welcome) end context '2FA is required from group' do diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb index 8ccaf82536a..d1520a5a53a 100644 --- a/spec/features/invites_spec.rb +++ b/spec/features/invites_spec.rb @@ -58,6 +58,8 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do end it 'pre-fills the Email field on the sign up box with the invite_email from the invite' do + click_link 'Register now' + expect(find_field('Email').value).to eq(group_invite.invite_email) end @@ -92,6 +94,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do before do stub_application_setting(send_user_confirmation_email: send_email_confirmation) visit invite_path(group_invite.raw_invite_token) + click_link 'Register now' end context 'email confirmation disabled' do diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb index f56c6f28f9d..0761c1871d3 100644 --- a/spec/features/users/login_spec.rb +++ b/spec/features/users/login_spec.rb @@ -26,7 +26,6 @@ RSpec.describe 'Login' do user.reload expect(user.reset_password_token).not_to be_nil - find('a[href="#login-pane"]').click gitlab_sign_in(user) expect(current_path).to eq root_path @@ -593,10 +592,16 @@ RSpec.describe 'Login' do describe 'UI tabs and panes' do context 'when no defaults are changed' do - it 'correctly renders tabs and panes' do + it 'does not render any tabs' do visit new_user_session_path - ensure_tab_pane_correctness(['Sign in', 'Register']) + ensure_no_tabs + end + + it 'renders link to sign up path' do + visit new_user_session_path + + expect(page.body).to have_link('Register now', href: new_user_registration_path) end end @@ -607,8 +612,14 @@ RSpec.describe 'Login' do visit new_user_session_path end - it 'correctly renders tabs and panes' do - ensure_tab_pane_correctness(['Sign in']) + it 'does not render any tabs' do + ensure_no_tabs + end + + it 'does not render link to sign up path' do + visit new_user_session_path + + expect(page.body).not_to have_link('Register now', href: new_user_registration_path) end end @@ -644,7 +655,11 @@ RSpec.describe 'Login' do end it 'correctly renders tabs and panes' do - ensure_tab_pane_correctness(['Main LDAP', 'Standard', 'Register']) + ensure_tab_pane_correctness(['Main LDAP', 'Standard']) + end + + it 'renders link to sign up path' do + expect(page.body).to have_link('Register now', href: new_user_registration_path) end end @@ -665,7 +680,7 @@ RSpec.describe 'Login' do end it 'correctly renders tabs and panes' do - ensure_tab_pane_correctness(%w(Crowd Standard Register)) + ensure_tab_pane_correctness(%w(Crowd Standard)) end end end diff --git a/spec/features/users/signup_spec.rb b/spec/features/users/signup_spec.rb index c59121626f0..bb2b465a69a 100644 --- a/spec/features/users/signup_spec.rb +++ b/spec/features/users/signup_spec.rb @@ -2,7 +2,45 @@ require 'spec_helper' -RSpec.shared_examples 'Signup' do +RSpec.shared_examples 'Signup name validation' do |field, max_length, label| + before do + visit new_user_registration_path + end + + describe "#{field} validation", :js do + it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do + fill_in field, with: 'u' * max_length + + expect(find('.name')).not_to have_css '.gl-field-error-outline' + end + + it 'shows an error border if the user\'s fullname contains an emoji' do + simulate_input("##{field}", 'Ehsan 🦋') + + expect(find('.name')).to have_css '.gl-field-error-outline' + end + + it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do + fill_in field, with: 'n' * (max_length + 1) + + expect(find('.name')).to have_css '.gl-field-error-outline' + end + + it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do + fill_in field, with: 'n' * (max_length + 1) + + expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).") + end + + it 'shows an error message if the username contains emojis' do + simulate_input("##{field}", 'Ehsan 🦋') + + expect(page).to have_content("Invalid input, please avoid emojis") + end + end +end + +RSpec.describe 'Signup' do include TermsHelper let(:new_user) { build_stubbed(:user) } @@ -295,64 +333,7 @@ RSpec.shared_examples 'Signup' do expect(created_user.setup_for_company).to be_nil expect(page).to have_current_path(new_project_path) end -end -RSpec.shared_examples 'Signup name validation' do |field, max_length, label| - before do - visit new_user_registration_path - end - - describe "#{field} validation", :js do - it "does not show an error border if the user's fullname length is not longer than #{max_length} characters" do - fill_in field, with: 'u' * max_length - - expect(find('.name')).not_to have_css '.gl-field-error-outline' - end - - it 'shows an error border if the user\'s fullname contains an emoji' do - simulate_input("##{field}", 'Ehsan 🦋') - - expect(find('.name')).to have_css '.gl-field-error-outline' - end - - it "shows an error border if the user\'s fullname is longer than #{max_length} characters" do - fill_in field, with: 'n' * (max_length + 1) - - expect(find('.name')).to have_css '.gl-field-error-outline' - end - - it "shows an error message if the user\'s #{label} is longer than #{max_length} characters" do - fill_in field, with: 'n' * (max_length + 1) - - expect(page).to have_content("#{label} is too long (maximum is #{max_length} characters).") - end - - it 'shows an error message if the username contains emojis' do - simulate_input("##{field}", 'Ehsan 🦋') - - expect(page).to have_content("Invalid input, please avoid emojis") - end - end -end - -RSpec.describe 'With original flow' do - before do - stub_experiment(signup_flow: false) - stub_experiment_for_user(signup_flow: false) - end - - it_behaves_like 'Signup' - it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name' - it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name' -end - -RSpec.describe 'With experimental flow' do - before do - stub_experiment(signup_flow: true) - stub_experiment_for_user(signup_flow: true) - end - - it_behaves_like 'Signup' it_behaves_like 'Signup name validation', 'new_user_first_name', 127, 'First name' it_behaves_like 'Signup name validation', 'new_user_last_name', 127, 'Last name' end diff --git a/spec/frontend/fixtures/static/signin_tabs.html b/spec/frontend/fixtures/static/signin_tabs.html index 247a6b03054..7e66ab9394b 100644 --- a/spec/frontend/fixtures/static/signin_tabs.html +++ b/spec/frontend/fixtures/static/signin_tabs.html @@ -5,7 +5,4 @@
  • Standard
  • -
  • -Register -
  • diff --git a/spec/frontend/notes/mock_data.js b/spec/frontend/notes/mock_data.js index 4ff64abe4cc..7661d51aadf 100644 --- a/spec/frontend/notes/mock_data.js +++ b/spec/frontend/notes/mock_data.js @@ -7,7 +7,7 @@ export const notesDataMock = { newSessionPath: '/users/sign_in?redirect_to_referer=yes', notesPath: '/gitlab-org/gitlab-foss/noteable/issue/98/notes', quickActionsDocsPath: '/help/user/project/quick_actions', - registerPath: '/users/sign_in?redirect_to_referer=yes#register-pane', + registerPath: '/users/sign_up?redirect_to_referer=yes', prerenderedNotesCount: 1, closePath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=close', reopenPath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=reopen', diff --git a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js index 0d9af0cb856..4b50342bf84 100644 --- a/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js +++ b/spec/frontend/pages/sessions/new/preserve_url_fragment_spec.js @@ -14,18 +14,16 @@ describe('preserve_url_fragment', () => { loadFixtures('sessions/new.html'); }); - it('adds the url fragment to all login and sign up form actions', () => { + it('adds the url fragment to the login form actions', () => { preserveUrlFragment('#L65'); expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in#L65'); - expect($('#new_new_user').attr('action')).toBe('http://test.host/users#L65'); }); - it('does not add an empty url fragment to login and sign up form actions', () => { + it('does not add an empty url fragment to the login form actions', () => { preserveUrlFragment(); expect($('#new_user').attr('action')).toBe('http://test.host/users/sign_in'); - expect($('#new_new_user').attr('action')).toBe('http://test.host/users'); }); it('does not add an empty query parameter to OmniAuth login buttons', () => { diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb index 40ffec21b26..2fd2fe66173 100644 --- a/spec/lib/atlassian/jira_connect/client_spec.rb +++ b/spec/lib/atlassian/jira_connect/client_spec.rb @@ -11,6 +11,14 @@ RSpec.describe Atlassian::JiraConnect::Client do Timecop.freeze { example.run } end + describe '.generate_update_sequence_id' do + it 'returns monotonic_time converted it to integer' do + allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(1.0) + + expect(described_class.generate_update_sequence_id).to eq(1) + end + end + describe '#store_dev_info' do it "calls the API with auth headers" do expected_jwt = Atlassian::Jwt.encode( diff --git a/spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb new file mode 100644 index 00000000000..d7672c0baf1 --- /dev/null +++ b/spec/lib/atlassian/jira_connect/serializers/base_entity_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Atlassian::JiraConnect::Serializers::BaseEntity do + let(:update_sequence_id) { nil } + + subject do + described_class.represent( + anything, + update_sequence_id: update_sequence_id + ) + end + + it 'generates the update_sequence_id' do + allow(Atlassian::JiraConnect::Client).to receive(:generate_update_sequence_id).and_return(1) + + expect(subject.value_for(:updateSequenceId)).to eq(1) + end + + context 'with update_sequence_id option' do + let(:update_sequence_id) { 123 } + + it 'uses the custom update_sequence_id' do + expect(subject.value_for(:updateSequenceId)).to eq(123) + end + end +end diff --git a/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb b/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb index 23ba1770827..9100398ecc5 100644 --- a/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb +++ b/spec/lib/atlassian/jira_connect/serializers/repository_entity_spec.rb @@ -3,6 +3,8 @@ require 'spec_helper' RSpec.describe Atlassian::JiraConnect::Serializers::RepositoryEntity do + let(:update_sequence_id) { nil } + subject do project = create(:project, :repository) commits = [project.commit] @@ -13,9 +15,23 @@ RSpec.describe Atlassian::JiraConnect::Serializers::RepositoryEntity do project, commits: commits, branches: branches, - merge_requests: merge_requests + merge_requests: merge_requests, + update_sequence_id: update_sequence_id ).to_json end it { is_expected.to match_schema('jira_connect/repository') } + + context 'with custom update_sequence_id' do + let(:update_sequence_id) { 1.0 } + + it 'passes the update_sequence_id on to the nested entities', :aggregate_failures do + parsed_subject = Gitlab::Json.parse(subject) + + expect(parsed_subject['updateSequenceId']).to eq(update_sequence_id) + expect(parsed_subject['commits'].first['updateSequenceId']).to eq(update_sequence_id) + expect(parsed_subject['branches'].first['updateSequenceId']).to eq(update_sequence_id) + expect(parsed_subject['pullRequests'].first['updateSequenceId']).to eq(update_sequence_id) + end + end end diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 63a050e4f56..243da628204 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -294,19 +294,22 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do create(:project, creator: user) create(:clusters_applications_prometheus, :installed, cluster: cluster) create(:project_tracing_setting) + create(:project_error_tracking_setting) end expect(described_class.usage_activity_by_stage_monitor({})).to include( clusters: 2, clusters_applications_prometheus: 2, operations_dashboard_default_dashboard: 2, - projects_with_tracing_enabled: 2 + projects_with_tracing_enabled: 2, + projects_with_error_tracking_enabled: 2 ) expect(described_class.usage_activity_by_stage_monitor(described_class.last_28_days_time_period)).to include( clusters: 1, clusters_applications_prometheus: 1, operations_dashboard_default_dashboard: 1, - projects_with_tracing_enabled: 1 + projects_with_tracing_enabled: 1, + projects_with_error_tracking_enabled: 1 ) end end diff --git a/spec/services/jira_connect/sync_service_spec.rb b/spec/services/jira_connect/sync_service_spec.rb index e26ca30d0e1..83088bb2e79 100644 --- a/spec/services/jira_connect/sync_service_spec.rb +++ b/spec/services/jira_connect/sync_service_spec.rb @@ -23,7 +23,8 @@ RSpec.describe JiraConnect::SyncService do project: project, commits: commits, branches: [instance_of(Gitlab::Git::Branch)], - merge_requests: merge_requests + merge_requests: merge_requests, + update_sequence_id: anything ).and_return(return_value) end end diff --git a/spec/support/helpers/user_login_helper.rb b/spec/support/helpers/user_login_helper.rb index 925576119bb..47e858cb68c 100644 --- a/spec/support/helpers/user_login_helper.rb +++ b/spec/support/helpers/user_login_helper.rb @@ -8,6 +8,10 @@ module UserLoginHelper ensure_one_active_pane end + def ensure_no_tabs + expect(page.all('[role="tab"]').size).to eq(0) + end + def ensure_tab_labels(tab_names) tab_labels = page.all('[role="tab"]').map(&:text) diff --git a/spec/workers/jira_connect/sync_branch_worker_spec.rb b/spec/workers/jira_connect/sync_branch_worker_spec.rb index 2da3ea9d256..4aa2f89de7b 100644 --- a/spec/workers/jira_connect/sync_branch_worker_spec.rb +++ b/spec/workers/jira_connect/sync_branch_worker_spec.rb @@ -4,7 +4,10 @@ require 'spec_helper' RSpec.describe JiraConnect::SyncBranchWorker do describe '#perform' do - let_it_be(:project) { create(:project, :repository) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :repository, group: group) } + let_it_be(:subscription) { create(:jira_connect_subscription, installation: create(:jira_connect_installation), namespace: group) } + let(:project_id) { project.id } let(:branch_name) { 'master' } let(:commit_shas) { %w(b83d6e3 5a62481) } @@ -13,7 +16,7 @@ RSpec.describe JiraConnect::SyncBranchWorker do def expect_jira_sync_service_execute(args) expect_next_instance_of(JiraConnect::SyncService) do |instance| - expect(instance).to receive(:execute).with(args) + expect(instance).to receive(:execute).with(args.merge(update_sequence_id: nil)) end end @@ -61,5 +64,31 @@ RSpec.describe JiraConnect::SyncBranchWorker do subject end end + + context 'with update_sequence_id' do + let(:update_sequence_id) { 1 } + let(:request_url) { 'https://sample.atlassian.net/rest/devinfo/0.10/bulk' } + let(:request_body) do + { + repositories: [ + Atlassian::JiraConnect::Serializers::RepositoryEntity.represent( + project, + commits: project.commits_by(oids: commit_shas), + branches: [project.repository.find_branch(branch_name)], + update_sequence_id: update_sequence_id + ) + ] + }.to_json + end + + subject { described_class.new.perform(project_id, branch_name, commit_shas, update_sequence_id) } + + it 'sends the reqeust with custom update_sequence_id' do + expect(Atlassian::JiraConnect::Client).to receive(:post) + .with(URI(request_url), headers: anything, body: request_body) + + subject + end + end end end diff --git a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb index 764201e750a..b3c0db4f260 100644 --- a/spec/workers/jira_connect/sync_merge_request_worker_spec.rb +++ b/spec/workers/jira_connect/sync_merge_request_worker_spec.rb @@ -4,14 +4,18 @@ require 'spec_helper' RSpec.describe JiraConnect::SyncMergeRequestWorker do describe '#perform' do - let(:merge_request) { create(:merge_request) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :repository, group: group) } + let_it_be(:subscription) { create(:jira_connect_subscription, installation: create(:jira_connect_installation), namespace: group) } + let_it_be(:merge_request) { create(:merge_request, source_project: project) } + let(:merge_request_id) { merge_request.id } subject { described_class.new.perform(merge_request_id) } it 'calls JiraConnect::SyncService#execute' do expect_next_instance_of(JiraConnect::SyncService) do |service| - expect(service).to receive(:execute).with(merge_requests: [merge_request]) + expect(service).to receive(:execute).with(merge_requests: [merge_request], update_sequence_id: nil) end subject @@ -26,5 +30,30 @@ RSpec.describe JiraConnect::SyncMergeRequestWorker do subject end end + + context 'with update_sequence_id' do + let(:update_sequence_id) { 1 } + let(:request_url) { 'https://sample.atlassian.net/rest/devinfo/0.10/bulk' } + let(:request_body) do + { + repositories: [ + Atlassian::JiraConnect::Serializers::RepositoryEntity.represent( + project, + merge_requests: [merge_request], + update_sequence_id: update_sequence_id + ) + ] + }.to_json + end + + subject { described_class.new.perform(merge_request_id, update_sequence_id) } + + it 'sends the request with custom update_sequence_id' do + expect(Atlassian::JiraConnect::Client).to receive(:post) + .with(URI(request_url), headers: anything, body: request_body) + + subject + end + end end end