Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss6
-rw-r--r--app/finders/merge_requests_finder.rb2
-rw-r--r--app/models/ci/build.rb8
-rw-r--r--app/models/namespace.rb2
-rw-r--r--app/models/namespace_onboarding_action.rb36
-rw-r--r--app/models/onboarding_progress.rb65
-rw-r--r--app/services/groups/create_service.rb1
-rw-r--r--app/services/merge_requests/after_create_service.rb2
-rw-r--r--app/services/onboarding_progress_service.rb2
-rw-r--r--app/services/post_receive_service.rb2
-rw-r--r--app/views/layouts/nav/_breadcrumbs.html.haml2
-rw-r--r--app/views/profiles/chat_names/index.html.haml2
-rw-r--r--changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml5
-rw-r--r--changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml5
-rw-r--r--changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml5
-rw-r--r--changelogs/unreleased/yo-master-patch-07160.yml5
-rw-r--r--config/feature_flags/development/cd_skipped_deployment_status.yml7
-rw-r--r--config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml6
-rw-r--r--db/migrate/20201230180202_create_onboarding_progress.rb36
-rw-r--r--db/schema_migrations/202012301802021
-rw-r--r--db/structure.sql40
-rw-r--r--doc/development/geo/framework.md2
-rw-r--r--package.json2
-rw-r--r--spec/controllers/repositories/git_http_controller_spec.rb2
-rw-r--r--spec/factories/namespace_onboarding_actions.rb8
-rw-r--r--spec/factories/onboarding_progresses.rb7
-rw-r--r--spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap1
-rw-r--r--spec/frontend/blob/pipeline_tour_success_modal_spec.js10
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap1
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js2
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap16
-rw-r--r--spec/frontend/pipelines/test_reports/test_case_details_spec.js2
-rw-r--r--spec/frontend/profile/account/components/update_username_spec.js2
-rw-r--r--spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap1
-rw-r--r--spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap67
-rw-r--r--spec/frontend/projects/components/shared/delete_button_spec.js16
-rw-r--r--spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap1
-rw-r--r--spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap2
-rw-r--r--spec/models/ci/build_spec.rb22
-rw-r--r--spec/models/namespace_onboarding_action_spec.rb79
-rw-r--r--spec/models/namespace_spec.rb2
-rw-r--r--spec/models/onboarding_progress_spec.rb107
-rw-r--r--spec/services/groups/create_service_spec.rb8
-rw-r--r--spec/services/members/create_service_spec.rb20
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb14
-rw-r--r--spec/services/onboarding_progress_service_spec.rb28
-rw-r--r--spec/services/post_receive_service_spec.rb11
-rw-r--r--spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb18
-rw-r--r--spec/workers/namespaces/onboarding_user_added_worker_spec.rb10
-rw-r--r--yarn.lock8
51 files changed, 420 insertions, 291 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 0bcc88f64d3..428bc196899 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-42f8c9df6f29d8983c0f976b352129ec91499667
+04496625daa52aaa82fe4140d898258e7e6fda22
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index 48252762546..745d469e3e8 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -436,11 +436,7 @@
padding: 6px 16px;
margin: 0 0 0 -15px;
height: 46px;
-
- i {
- font-size: 20px;
- color: $gl-text-color-secondary;
- }
+ color: $gl-text-color;
@include media-breakpoint-down(sm) {
display: flex;
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index 87c190bdc45..9f9e2afa7fe 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -57,7 +57,7 @@ class MergeRequestsFinder < IssuableFinder
end
def params_class
- MergeRequestsFinder::Params
+ MergeRequestsFinder.const_get(:Params, false) # rubocop: disable CodeReuse/Finder
end
def filter_items(_items)
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index efe5789e49a..e9128252eb2 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -389,12 +389,8 @@ module Ci
end
after_transition any => [:skipped, :canceled] do |build, transition|
- if Feature.enabled?(:cd_skipped_deployment_status, build.project)
- if transition.to_name == :skipped
- build.deployment&.skip
- else
- build.deployment&.cancel
- end
+ if transition.to_name == :skipped
+ build.deployment&.skip
else
build.deployment&.cancel
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 02ea8948419..6f7b377ee52 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -28,7 +28,7 @@ class Namespace < ApplicationRecord
has_many :runner_namespaces, inverse_of: :namespace, class_name: 'Ci::RunnerNamespace'
has_many :runners, through: :runner_namespaces, source: :runner, class_name: 'Ci::Runner'
- has_many :namespace_onboarding_actions
+ has_one :onboarding_progress
# This should _not_ be `inverse_of: :namespace`, because that would also set
# `user.namespace` when this user creates a group with themselves as `owner`.
diff --git a/app/models/namespace_onboarding_action.rb b/app/models/namespace_onboarding_action.rb
deleted file mode 100644
index 2b0d6cad02d..00000000000
--- a/app/models/namespace_onboarding_action.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class NamespaceOnboardingAction < ApplicationRecord
- belongs_to :namespace, optional: false
-
- validates :action, presence: true
-
- ACTIONS = {
- subscription_created: 1,
- git_write: 2,
- merge_request_created: 3,
- git_read: 4,
- pipeline_created: 5,
- user_added: 6
- }.freeze
-
- # The monitoring window prevents the recording of a namespace_onboarding_action if a namespace is created before this
- # time span. We are not interested in older namspaces, because the purpose of this table is to monitor and act on the
- # progress of newly created namespaces or namespaces that already have at least one recorded action.
- MONITORING_WINDOW = 90.days
-
- enum action: ACTIONS
-
- class << self
- def completed?(namespace, action)
- where(namespace: namespace, action: action).exists?
- end
-
- def create_action(namespace, action)
- return unless namespace.root?
- return if namespace.created_at < MONITORING_WINDOW.ago && !namespace.namespace_onboarding_actions.exists?
-
- NamespaceOnboardingAction.safe_find_or_create_by(namespace: namespace, action: action)
- end
- end
-end
diff --git a/app/models/onboarding_progress.rb b/app/models/onboarding_progress.rb
new file mode 100644
index 00000000000..419bbd595e9
--- /dev/null
+++ b/app/models/onboarding_progress.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+class OnboardingProgress < ApplicationRecord
+ belongs_to :namespace, optional: false
+
+ validate :namespace_is_root_namespace
+
+ ACTIONS = [
+ :git_pull,
+ :git_write,
+ :merge_request_created,
+ :pipeline_created,
+ :user_added,
+ :trial_started,
+ :subscription_created,
+ :required_mr_approvals_enabled,
+ :code_owners_enabled,
+ :scoped_label_created,
+ :security_scan_enabled,
+ :issue_auto_closed,
+ :repository_imported,
+ :repository_mirrored
+ ].freeze
+
+ class << self
+ def onboard(namespace)
+ return unless root_namespace?(namespace)
+
+ safe_find_or_create_by(namespace: namespace)
+ end
+
+ def register(namespace, action)
+ return unless root_namespace?(namespace) && ACTIONS.include?(action)
+
+ action_column = column_name(action)
+ onboarding_progress = find_by(namespace: namespace, action_column => nil)
+ onboarding_progress&.update!(action_column => Time.current)
+ end
+
+ def completed?(namespace, action)
+ return unless root_namespace?(namespace) && ACTIONS.include?(action)
+
+ action_column = column_name(action)
+ where(namespace: namespace).where.not(action_column => nil).exists?
+ end
+
+ private
+
+ def column_name(action)
+ :"#{action}_at"
+ end
+
+ def root_namespace?(namespace)
+ namespace && namespace.root?
+ end
+ end
+
+ private
+
+ def namespace_is_root_namespace
+ return unless namespace
+
+ errors.add(:namespace, _('must be a root namespace')) if namespace.has_parent?
+ end
+end
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index 52600f5b88f..06a3b31c665 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -35,6 +35,7 @@ module Groups
@group.add_owner(current_user)
@group.create_namespace_settings
Service.create_from_active_default_integrations(@group, :group_id)
+ OnboardingProgress.onboard(@group)
end
end
diff --git a/app/services/merge_requests/after_create_service.rb b/app/services/merge_requests/after_create_service.rb
index 5313afd62b4..03fcb5a4c1b 100644
--- a/app/services/merge_requests/after_create_service.rb
+++ b/app/services/merge_requests/after_create_service.rb
@@ -13,7 +13,7 @@ module MergeRequests
merge_request.diffs(include_stats: false).write_cache
merge_request.create_cross_references!(current_user)
- NamespaceOnboardingAction.create_action(merge_request.target_project.namespace, :merge_request_created)
+ OnboardingProgressService.new(merge_request.target_project.namespace).execute(action: :merge_request_created)
end
end
end
diff --git a/app/services/onboarding_progress_service.rb b/app/services/onboarding_progress_service.rb
index fe00c96ed4c..241bd8a01ca 100644
--- a/app/services/onboarding_progress_service.rb
+++ b/app/services/onboarding_progress_service.rb
@@ -8,6 +8,6 @@ class OnboardingProgressService
def execute(action:)
return unless @namespace
- NamespaceOnboardingAction.create_action(@namespace, action)
+ OnboardingProgress.register(@namespace, action)
end
end
diff --git a/app/services/post_receive_service.rb b/app/services/post_receive_service.rb
index bd9588844ad..84d9db5435b 100644
--- a/app/services/post_receive_service.rb
+++ b/app/services/post_receive_service.rb
@@ -94,7 +94,7 @@ class PostReceiveService
end
def record_onboarding_progress
- NamespaceOnboardingAction.create_action(project.namespace, :git_write)
+ OnboardingProgressService.new(project.namespace).execute(action: :git_write)
end
end
diff --git a/app/views/layouts/nav/_breadcrumbs.html.haml b/app/views/layouts/nav/_breadcrumbs.html.haml
index 43f1011a85b..dd2c5e2a19e 100644
--- a/app/views/layouts/nav/_breadcrumbs.html.haml
+++ b/app/views/layouts/nav/_breadcrumbs.html.haml
@@ -8,7 +8,7 @@
- if defined?(@left_sidebar)
= button_tag class: 'toggle-mobile-nav', type: 'button' do
%span.sr-only= _("Open sidebar")
- = sprite_icon('hamburger')
+ = sprite_icon('hamburger', size: 18)
.breadcrumbs-links.js-title-container{ data: { qa_selector: 'breadcrumb_links_content' } }
%ul.list-unstyled.breadcrumbs-list.js-breadcrumbs-list
- unless hide_top_links
diff --git a/app/views/profiles/chat_names/index.html.haml b/app/views/profiles/chat_names/index.html.haml
index e0b0f839455..782850afcda 100644
--- a/app/views/profiles/chat_names/index.html.haml
+++ b/app/views/profiles/chat_names/index.html.haml
@@ -9,7 +9,7 @@
= _('You can see your chat accounts.')
.col-lg-8
- %h5 Active chat names (#{@chat_names.size})
+ %h5.gl-mt-0 Active chat names (#{@chat_names.size})
- if @chat_names.present?
.table-responsive
diff --git a/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml b/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml
new file mode 100644
index 00000000000..2688be6609f
--- /dev/null
+++ b/changelogs/unreleased/294127-follow-up-investigate-whether-we-should-convert-namespace_onboardi.yml
@@ -0,0 +1,5 @@
+---
+title: Change onboarding actions table to use one record per namespace
+merge_request: 50711
+author:
+type: changed
diff --git a/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml b/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml
new file mode 100644
index 00000000000..f968a43485f
--- /dev/null
+++ b/changelogs/unreleased/fix-color-of-hamburger-in-darkmode.yml
@@ -0,0 +1,5 @@
+---
+title: Fix color of hamburger in dark mode
+merge_request: 51168
+author: Kev @KevSlashNull
+type: fixed
diff --git a/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml b/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml
new file mode 100644
index 00000000000..6edfa7c9713
--- /dev/null
+++ b/changelogs/unreleased/remove-feature-flag-cd_skipped_deployment_status.yml
@@ -0,0 +1,5 @@
+---
+title: Add skipped status to deployments
+merge_request: 51068
+author:
+type: added
diff --git a/changelogs/unreleased/yo-master-patch-07160.yml b/changelogs/unreleased/yo-master-patch-07160.yml
new file mode 100644
index 00000000000..de1a072869d
--- /dev/null
+++ b/changelogs/unreleased/yo-master-patch-07160.yml
@@ -0,0 +1,5 @@
+---
+title: Add margin to user chat settings
+merge_request: 51282
+author: Yogi (@yo)
+type: fixed
diff --git a/config/feature_flags/development/cd_skipped_deployment_status.yml b/config/feature_flags/development/cd_skipped_deployment_status.yml
deleted file mode 100644
index 45d9538ebfc..00000000000
--- a/config/feature_flags/development/cd_skipped_deployment_status.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-name: cd_skipped_deployment_status
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46614
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/283884
-milestone: '13.6'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml
index b284a0e2f78..d20cb10fcda 100644
--- a/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml
+++ b/config/feature_flags/experiment/invite_members_version_a_experiment_percentage.yml
@@ -1,8 +1,8 @@
---
name: invite_members_version_a_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45689/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/219239
-milestone: '13.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33210
+rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/299
+milestone: '13.1'
type: experiment
group: group::expansion
default_enabled: false
diff --git a/db/migrate/20201230180202_create_onboarding_progress.rb b/db/migrate/20201230180202_create_onboarding_progress.rb
new file mode 100644
index 00000000000..b9fe64eb19d
--- /dev/null
+++ b/db/migrate/20201230180202_create_onboarding_progress.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class CreateOnboardingProgress < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ create_table :onboarding_progresses do |t|
+ t.references :namespace, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
+ t.timestamps_with_timezone null: false
+ t.datetime_with_timezone :git_pull_at
+ t.datetime_with_timezone :git_write_at
+ t.datetime_with_timezone :merge_request_created_at
+ t.datetime_with_timezone :pipeline_created_at
+ t.datetime_with_timezone :user_added_at
+ t.datetime_with_timezone :trial_started_at
+ t.datetime_with_timezone :subscription_created_at
+ t.datetime_with_timezone :required_mr_approvals_enabled_at
+ t.datetime_with_timezone :code_owners_enabled_at
+ t.datetime_with_timezone :scoped_label_created_at
+ t.datetime_with_timezone :security_scan_enabled_at
+ t.datetime_with_timezone :issue_auto_closed_at
+ t.datetime_with_timezone :repository_imported_at
+ t.datetime_with_timezone :repository_mirrored_at
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :onboarding_progresses
+ end
+ end
+end
diff --git a/db/schema_migrations/20201230180202 b/db/schema_migrations/20201230180202
new file mode 100644
index 00000000000..62a0e277a55
--- /dev/null
+++ b/db/schema_migrations/20201230180202
@@ -0,0 +1 @@
+c2766b50914c6b4d8c96fb958cdfb67f0d29e40df45654c35d62792c272e3d5a \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 0a66608ba32..bba1aee901d 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -14491,6 +14491,36 @@ CREATE SEQUENCE oauth_openid_requests_id_seq
ALTER SEQUENCE oauth_openid_requests_id_seq OWNED BY oauth_openid_requests.id;
+CREATE TABLE onboarding_progresses (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ git_pull_at timestamp with time zone,
+ git_write_at timestamp with time zone,
+ merge_request_created_at timestamp with time zone,
+ pipeline_created_at timestamp with time zone,
+ user_added_at timestamp with time zone,
+ trial_started_at timestamp with time zone,
+ subscription_created_at timestamp with time zone,
+ required_mr_approvals_enabled_at timestamp with time zone,
+ code_owners_enabled_at timestamp with time zone,
+ scoped_label_created_at timestamp with time zone,
+ security_scan_enabled_at timestamp with time zone,
+ issue_auto_closed_at timestamp with time zone,
+ repository_imported_at timestamp with time zone,
+ repository_mirrored_at timestamp with time zone
+);
+
+CREATE SEQUENCE onboarding_progresses_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE onboarding_progresses_id_seq OWNED BY onboarding_progresses.id;
+
CREATE TABLE open_project_tracker_data (
id bigint NOT NULL,
service_id integer NOT NULL,
@@ -18715,6 +18745,8 @@ ALTER TABLE ONLY oauth_applications ALTER COLUMN id SET DEFAULT nextval('oauth_a
ALTER TABLE ONLY oauth_openid_requests ALTER COLUMN id SET DEFAULT nextval('oauth_openid_requests_id_seq'::regclass);
+ALTER TABLE ONLY onboarding_progresses ALTER COLUMN id SET DEFAULT nextval('onboarding_progresses_id_seq'::regclass);
+
ALTER TABLE ONLY open_project_tracker_data ALTER COLUMN id SET DEFAULT nextval('open_project_tracker_data_id_seq'::regclass);
ALTER TABLE ONLY operations_feature_flag_scopes ALTER COLUMN id SET DEFAULT nextval('operations_feature_flag_scopes_id_seq'::regclass);
@@ -20052,6 +20084,9 @@ ALTER TABLE ONLY oauth_applications
ALTER TABLE ONLY oauth_openid_requests
ADD CONSTRAINT oauth_openid_requests_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY onboarding_progresses
+ ADD CONSTRAINT onboarding_progresses_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY open_project_tracker_data
ADD CONSTRAINT open_project_tracker_data_pkey PRIMARY KEY (id);
@@ -22254,6 +22289,8 @@ CREATE INDEX index_on_users_lower_username ON users USING btree (lower((username
CREATE INDEX index_on_users_name_lower ON users USING btree (lower((name)::text));
+CREATE UNIQUE INDEX index_onboarding_progresses_on_namespace_id ON onboarding_progresses USING btree (namespace_id);
+
CREATE INDEX index_open_project_tracker_data_on_service_id ON open_project_tracker_data USING btree (service_id);
CREATE INDEX index_operations_feature_flags_issues_on_issue_id ON operations_feature_flags_issues USING btree (issue_id);
@@ -24465,6 +24502,9 @@ ALTER TABLE ONLY geo_repository_updated_events
ALTER TABLE ONLY boards_epic_board_labels
ADD CONSTRAINT fk_rails_2bedeb8799 FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;
+ALTER TABLE ONLY onboarding_progresses
+ ADD CONSTRAINT fk_rails_2ccfd420cc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY protected_branch_unprotect_access_levels
ADD CONSTRAINT fk_rails_2d2aba21ef FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md
index 4aa857ba77f..148953dc418 100644
--- a/doc/development/geo/framework.md
+++ b/doc/development/geo/framework.md
@@ -287,7 +287,7 @@ For example, to add support for files referenced by a `Widget` model with a
t.datetime_with_timezone :created_at, null: false
t.text :last_sync_failure
- t.index :widget_id, name: :index_widget_registry_on_widget_id
+ t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true
t.index :retry_at
t.index :state
end
diff --git a/package.json b/package.json
index ac5cf111e6c..516d8f4c565 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.178.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "25.4.0",
+ "@gitlab/ui": "25.7.2",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-4",
"@rails/ujs": "^6.0.3-4",
diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb
index 551abf9241d..34052496871 100644
--- a/spec/controllers/repositories/git_http_controller_spec.rb
+++ b/spec/controllers/repositories/git_http_controller_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Repositories::GitHttpController do
}.from(0).to(1)
end
- it 'records a namespace onboarding progress action' do
+ it 'records an onboarding progress action' do
expect_next_instance_of(OnboardingProgressService) do |service|
expect(service).to receive(:execute).with(action: :git_read)
end
diff --git a/spec/factories/namespace_onboarding_actions.rb b/spec/factories/namespace_onboarding_actions.rb
deleted file mode 100644
index aca62013b57..00000000000
--- a/spec/factories/namespace_onboarding_actions.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :namespace_onboarding_action do
- namespace
- action { :subscription_created }
- end
-end
diff --git a/spec/factories/onboarding_progresses.rb b/spec/factories/onboarding_progresses.rb
new file mode 100644
index 00000000000..e39bad91b19
--- /dev/null
+++ b/spec/factories/onboarding_progresses.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :onboarding_progress do
+ namespace
+ end
+end
diff --git a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
index 8948a9926bb..1eb9ccc9c6c 100644
--- a/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
+++ b/spec/frontend/add_context_commits_modal/components/__snapshots__/add_context_commits_modal_spec.js.snap
@@ -4,6 +4,7 @@ exports[`AddContextCommitsModal renders modal with 2 tabs 1`] = `
<gl-modal-stub
body-class="add-review-item pt-0"
cancel-variant="light"
+ dismisslabel="Close"
modalclass=""
modalid="add-review-item"
ok-disabled="true"
diff --git a/spec/frontend/blob/pipeline_tour_success_modal_spec.js b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
index 75a8994be4d..d4562019302 100644
--- a/spec/frontend/blob/pipeline_tour_success_modal_spec.js
+++ b/spec/frontend/blob/pipeline_tour_success_modal_spec.js
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import Cookies from 'js-cookie';
import { GlSprintf, GlModal, GlLink } from '@gitlab/ui';
import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
+import { stubComponent } from 'helpers/stub_component';
import pipelineTourSuccess from '~/blob/pipeline_tour_success_modal.vue';
import modalProps from './pipeline_tour_success_mock_data';
@@ -15,7 +16,14 @@ describe('PipelineTourSuccessModal', () => {
wrapper = shallowMount(pipelineTourSuccess, {
propsData: modalProps,
stubs: {
- GlModal,
+ GlModal: stubComponent(GlModal, {
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <slot></slot>
+ <slot name="modal-footer"></slot>
+ </div>`,
+ }),
GlSprintf,
GlEmoji,
},
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
index f0eb54c1b3a..79ad5ad1bb9 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
@@ -52,6 +52,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
</gl-button-stub>
<gl-modal-stub
+ dismisslabel="Close"
modalclass=""
modalid="resetWebhookModal"
ok-title="Reset webhook URL"
diff --git a/spec/frontend/invite_members/components/invite_members_modal_spec.js b/spec/frontend/invite_members/components/invite_members_modal_spec.js
index 4eb1db70b11..fc039bdf6da 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -68,7 +68,7 @@ describe('InviteMembersModal', () => {
});
it('renders the modal with the correct title', () => {
- expect(wrapper.attributes('title')).toBe('Invite team members');
+ expect(wrapper.find(GlModal).props('title')).toBe('Invite team members');
});
it('renders the Cancel button text correctly', () => {
diff --git a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
index c51130dae00..b2df1ac5ab6 100644
--- a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
+++ b/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -34,7 +34,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -95,7 +95,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Composer packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -156,7 +156,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Conan packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -217,7 +217,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Generic packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -278,7 +278,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no Maven packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -339,7 +339,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no NPM packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -400,7 +400,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no NuGet packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
@@ -461,7 +461,7 @@ exports[`packages_list_app renders 1`] = `
class="svg-250 svg-content"
>
<img
- alt="There are no PyPI packages yet"
+ alt=""
class="gl-max-w-full"
src="helpSvg"
/>
diff --git a/spec/frontend/pipelines/test_reports/test_case_details_spec.js b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
index 9e66012818e..bfb8b43778d 100644
--- a/spec/frontend/pipelines/test_reports/test_case_details_spec.js
+++ b/spec/frontend/pipelines/test_reports/test_case_details_spec.js
@@ -44,7 +44,7 @@ describe('Test case details', () => {
});
it('renders the test case classname as modal title', () => {
- expect(findModal().attributes('title')).toBe(defaultTestCase.classname);
+ expect(findModal().props('title')).toBe(defaultTestCase.classname);
});
it('renders the test case name', () => {
diff --git a/spec/frontend/profile/account/components/update_username_spec.js b/spec/frontend/profile/account/components/update_username_spec.js
index 45e5e0f885f..91c3c81ab30 100644
--- a/spec/frontend/profile/account/components/update_username_spec.js
+++ b/spec/frontend/profile/account/components/update_username_spec.js
@@ -84,7 +84,7 @@ describe('UpdateUsername component', () => {
it('confirmation modal contains proper header and body', async () => {
const { modal } = findElements();
- expect(modal.attributes('title')).toBe('Change username?');
+ expect(modal.props('title')).toBe('Change username?');
expect(modal.text()).toContain(
`You are going to change the username ${defaultProps.initialUsername} to ${newUsername}`,
);
diff --git a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
index 4eb5060cb0a..0b9f095a700 100644
--- a/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/__snapshots__/project_delete_button_spec.js.snap
@@ -31,6 +31,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
<gl-modal-stub
actioncancel="[object Object]"
actionprimary="[object Object]"
+ dismisslabel="Close"
footer-class="gl-bg-gray-10 gl-p-5"
modalclass=""
modalid="fakeUniqueId"
diff --git a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
index 4630415f61c..dd54db7dc0a 100644
--- a/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
+++ b/spec/frontend/projects/components/shared/__snapshots__/delete_button_spec.js.snap
@@ -29,24 +29,12 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
Delete project
</gl-button-stub>
- <b-modal-stub
- canceltitle="Cancel"
- cancelvariant="secondary"
- footerclass="gl-bg-gray-10 gl-p-5"
- headerclosecontent="&times;"
- headercloselabel="Close"
- id="delete-project-modal-2"
- ignoreenforcefocusselector=""
- lazy="true"
- modalclass="gl-modal,"
- oktitle="OK"
- okvariant="danger"
- size="sm"
- title=""
- titleclass="gl-text-red-500"
- titletag="h4"
+ <div
+ footer-class="gl-bg-gray-10 gl-p-5"
+ ok-variant="danger"
+ title-class="gl-text-red-500"
>
-
+ Delete project. Are you ABSOLUTELY SURE?
<div>
<p
@@ -70,49 +58,6 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
/>
</div>
-
- <template />
-
- <template>
- Delete project. Are you ABSOLUTELY SURE?
- </template>
-
- <template />
-
- <template />
-
- <template />
-
- <template>
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-modal-action-cancel"
- icon=""
- size="medium"
- variant="default"
- >
-
- Cancel, keep project
-
- </gl-button-stub>
-
- <!---->
-
- <gl-button-stub
- buttontextclasses=""
- category="primary"
- class="js-modal-action-primary"
- disabled="true"
- icon=""
- size="medium"
- variant="danger"
- >
-
- Yes, delete project
-
- </gl-button-stub>
- </template>
- </b-modal-stub>
+ </div>
</form>
`;
diff --git a/spec/frontend/projects/components/shared/delete_button_spec.js b/spec/frontend/projects/components/shared/delete_button_spec.js
index a6394a50011..cf7e41a2df2 100644
--- a/spec/frontend/projects/components/shared/delete_button_spec.js
+++ b/spec/frontend/projects/components/shared/delete_button_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { GlModal } from '@gitlab/ui';
+import { stubComponent } from 'helpers/stub_component';
import SharedDeleteButton from '~/projects/components/shared/delete_button.vue';
jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' }));
@@ -17,12 +18,19 @@ describe('Project remove modal', () => {
formPath: 'some/path',
};
- const createComponent = (data = {}) => {
+ const createComponent = (data = {}, stubs = {}) => {
wrapper = shallowMount(SharedDeleteButton, {
propsData: defaultProps,
data: () => data,
stubs: {
- GlModal,
+ GlModal: stubComponent(GlModal, {
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <slot></slot>
+ </div>`,
+ }),
+ ...stubs,
},
});
};
@@ -52,7 +60,7 @@ describe('Project remove modal', () => {
describe('when the user input does not match the confirmPhrase', () => {
beforeEach(() => {
- createComponent({ userInput: 'bar' });
+ createComponent({ userInput: 'bar' }, { GlModal });
});
it('the confirm button is disabled', () => {
@@ -62,7 +70,7 @@ describe('Project remove modal', () => {
describe('when the user input matches the confirmPhrase', () => {
beforeEach(() => {
- createComponent({ userInput: defaultProps.confirmPhrase });
+ createComponent({ userInput: defaultProps.confirmPhrase }, { GlModal });
});
it('the confirm button is not disabled', () => {
diff --git a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
index 02d5ca6bdb3..bd05eb69080 100644
--- a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
+++ b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
@@ -60,6 +60,7 @@ exports[`self monitor component When the self monitor project has not been creat
<gl-modal-stub
cancel-title="Cancel"
category="primary"
+ dismisslabel="Close"
modalclass=""
modalid="delete-self-monitor-modal"
ok-title="Delete project"
diff --git a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
index 6b3d65ff037..4b827301943 100644
--- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
+++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
@@ -3,7 +3,7 @@
exports[`EmptyStateComponent should render content 1`] = `
"<section class=\\"row empty-state text-center\\">
<div class=\\"col-12\\">
- <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"Getting started with serverless\\" class=\\"gl-max-w-full\\"></div>
+ <div class=\\"svg-250 svg-content\\"><img src=\\"/image.svg\\" alt=\\"\\" class=\\"gl-max-w-full\\"></div>
</div>
<div class=\\"col-12\\">
<div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\">
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index bb3228c2bf0..e18abcc2c7a 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1183,26 +1183,12 @@ RSpec.describe Ci::Build do
end
context 'when transits to skipped' do
- context 'when cd_skipped_deployment_status is disabled' do
- before do
- stub_feature_flags(cd_skipped_deployment_status: false)
- build.skip!
- end
-
- it 'transits deployment status to canceled' do
- expect(deployment).to be_canceled
- end
+ before do
+ build.skip!
end
- context 'when cd_skipped_deployment_status is enabled' do
- before do
- stub_feature_flags(cd_skipped_deployment_status: project)
- build.skip!
- end
-
- it 'transits deployment status to skipped' do
- expect(deployment).to be_skipped
- end
+ it 'transits deployment status to skipped' do
+ expect(deployment).to be_skipped
end
end
diff --git a/spec/models/namespace_onboarding_action_spec.rb b/spec/models/namespace_onboarding_action_spec.rb
deleted file mode 100644
index aba6b2061c3..00000000000
--- a/spec/models/namespace_onboarding_action_spec.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe NamespaceOnboardingAction do
- let(:namespace) { create(:namespace) }
-
- describe 'associations' do
- it { is_expected.to belong_to(:namespace).required }
- end
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:action) }
- end
-
- describe '.completed?' do
- let(:action) { :subscription_created }
-
- subject { described_class.completed?(namespace, action) }
-
- context 'action created for the namespace' do
- before do
- create(:namespace_onboarding_action, namespace: namespace, action: action)
- end
-
- it { is_expected.to eq(true) }
- end
-
- context 'action created for another namespace' do
- before do
- create(:namespace_onboarding_action, namespace: build(:namespace), action: action)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- describe '.create_action' do
- let(:action) { :subscription_created }
-
- subject(:create_action) { described_class.create_action(namespace, action) }
-
- it 'creates the action for the namespace just once' do
- expect { create_action }.to change { count_namespace_actions }.by(1)
-
- expect { create_action }.to change { count_namespace_actions }.by(0)
- end
-
- context 'when the namespace is created outside the monitoring window' do
- let(:namespace) { create(:namespace, created_at: (NamespaceOnboardingAction::MONITORING_WINDOW + 1.day).ago) }
-
- it 'does not create an action for the namespace' do
- expect { create_action }.not_to change { count_namespace_actions }
- end
-
- context 'when an action has already been recorded for the namespace' do
- before do
- described_class.create!(namespace: namespace, action: :git_write)
- end
-
- it 'creates an action for the namespace' do
- expect { create_action }.to change { count_namespace_actions }.by(1)
- end
- end
- end
-
- context 'when the namespace is not a root' do
- let(:namespace) { create(:namespace, parent: build(:namespace)) }
-
- it 'does not create an action for the namespace' do
- expect { create_action }.not_to change { count_namespace_actions }
- end
- end
-
- def count_namespace_actions
- described_class.where(namespace: namespace, action: action).count
- end
- end
-end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 1c72c1fc6a6..a3c0a43115e 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -19,8 +19,8 @@ RSpec.describe Namespace do
it { is_expected.to have_one :aggregation_schedule }
it { is_expected.to have_one :namespace_settings }
it { is_expected.to have_many :custom_emoji }
- it { is_expected.to have_many :namespace_onboarding_actions }
it { is_expected.to have_one :package_setting_relation }
+ it { is_expected.to have_one :onboarding_progress }
end
describe 'validations' do
diff --git a/spec/models/onboarding_progress_spec.rb b/spec/models/onboarding_progress_spec.rb
new file mode 100644
index 00000000000..bd951846bb8
--- /dev/null
+++ b/spec/models/onboarding_progress_spec.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe OnboardingProgress do
+ let(:namespace) { create(:namespace) }
+ let(:action) { :subscription_created }
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:namespace).required }
+ end
+
+ describe 'validations' do
+ describe 'namespace_is_root_namespace' do
+ subject(:onboarding_progress) { build(:onboarding_progress, namespace: namespace)}
+
+ context 'when associated namespace is root' do
+ it { is_expected.to be_valid }
+ end
+
+ context 'when associated namespace is not root' do
+ let(:namespace) { build(:group, :nested) }
+
+ it 'is invalid' do
+ expect(onboarding_progress).to be_invalid
+ expect(onboarding_progress.errors[:namespace]).to include('must be a root namespace')
+ end
+ end
+ end
+ end
+
+ describe '.onboard' do
+ subject(:onboard) { described_class.onboard(namespace) }
+
+ it 'adds a record for the namespace' do
+ expect { onboard }.to change(described_class, :count).from(0).to(1)
+ end
+
+ context 'when not given a namespace' do
+ let(:namespace) { nil }
+
+ it 'does not add a record for the namespace' do
+ expect { onboard }.not_to change(described_class, :count).from(0)
+ end
+ end
+
+ context 'when not given a root namespace' do
+ let(:namespace) { create(:namespace, parent: build(:namespace)) }
+
+ it 'does not add a record for the namespace' do
+ expect { onboard }.not_to change(described_class, :count).from(0)
+ end
+ end
+ end
+
+ describe '.register' do
+ subject(:register_action) { described_class.register(namespace, action) }
+
+ context 'when the namespace was onboarded' do
+ before do
+ described_class.onboard(namespace)
+ end
+
+ it 'registers the action for the namespace' do
+ expect { register_action }.to change { described_class.completed?(namespace, action) }.from(false).to(true)
+ end
+
+ context 'when the action does not exist' do
+ let(:action) { :foo }
+
+ it 'does not register the action for the namespace' do
+ expect { register_action }.not_to change { described_class.completed?(namespace, action) }.from(nil)
+ end
+ end
+ end
+
+ context 'when the namespace was not onboarded' do
+ it 'does not register the action for the namespace' do
+ expect { register_action }.not_to change { described_class.completed?(namespace, action) }.from(false)
+ end
+ end
+ end
+
+ describe '.completed?' do
+ subject { described_class.completed?(namespace, action) }
+
+ context 'when the namespace has not yet been onboarded' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when the namespace has been onboarded but not registered the action yet' do
+ before do
+ described_class.onboard(namespace)
+ end
+
+ it { is_expected.to eq(false) }
+
+ context 'when the action has been registered' do
+ before do
+ described_class.register(namespace, action)
+ end
+
+ it { is_expected.to eq(true) }
+ end
+ end
+ end
+end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index 4f5bc3a3d5a..f0cd42c1948 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -63,6 +63,10 @@ RSpec.describe Groups::CreateService, '#execute' do
end
it { is_expected.to be_persisted }
+
+ it 'adds an onboarding progress record' do
+ expect { subject }.to change(OnboardingProgress, :count).from(0).to(1)
+ end
end
context 'when user can not create a group' do
@@ -84,6 +88,10 @@ RSpec.describe Groups::CreateService, '#execute' do
end
it { is_expected.to be_persisted }
+
+ it 'does not add an onboarding progress record' do
+ expect { subject }.not_to change(OnboardingProgress, :count).from(0)
+ end
end
context 'as guest' do
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index 7fd6b3e5b8d..50efee9f43c 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -13,14 +13,20 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
subject(:execute_service) { described_class.new(user, params).execute(source) }
before do
- source.is_a?(Project) ? source.add_maintainer(user) : source.add_owner(user)
+ if source.is_a?(Project)
+ source.add_maintainer(user)
+ OnboardingProgress.onboard(source.namespace)
+ else
+ source.add_owner(user)
+ OnboardingProgress.onboard(source)
+ end
end
context 'when passing valid parameters' do
it 'adds a user to members' do
expect(execute_service[:status]).to eq(:success)
expect(source.users).to include member
- expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(true)
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(true)
end
context 'when executing on a group' do
@@ -29,7 +35,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
it 'adds a user to members' do
expect(execute_service[:status]).to eq(:success)
expect(source.users).to include member
- expect(NamespaceOnboardingAction.completed?(source, :user_added)).to be(true)
+ expect(OnboardingProgress.completed?(source, :user_added)).to be(true)
end
end
end
@@ -41,7 +47,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to be_present
expect(source.users).not_to include member
- expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false)
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
@@ -52,7 +58,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to be_present
expect(source.users).not_to include member
- expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false)
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
@@ -63,7 +69,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to include("#{member.username}: Access level is not included in the list")
expect(source.users).not_to include member
- expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false)
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
@@ -73,7 +79,7 @@ RSpec.describe Members::CreateService, :clean_gitlab_redis_shared_state, :sideki
it 'does not add a member' do
expect(execute_service[:status]).to eq(:error)
expect(execute_service[:message]).to eq('Invite email has already been taken')
- expect(NamespaceOnboardingAction.completed?(source.namespace, :user_added)).to be(false)
+ expect(OnboardingProgress.completed?(source.namespace, :user_added)).to be(false)
end
end
end
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index bdc064a6269..9ae310d8cee 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe MergeRequests::AfterCreateService do
+ include AfterNextHelpers
+
let_it_be(:merge_request) { create(:merge_request) }
subject(:after_create_service) do
@@ -64,11 +66,15 @@ RSpec.describe MergeRequests::AfterCreateService do
execute_service
end
- it 'records a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(merge_request.target_project.namespace, :merge_request_created).and_call_original
+ it 'registers an onboarding progress action' do
+ OnboardingProgress.onboard(merge_request.target_project.namespace)
+
+ expect_next(OnboardingProgressService, merge_request.target_project.namespace)
+ .to receive(:execute).with(action: :merge_request_created).and_call_original
+
+ execute_service
- expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1)
+ expect(OnboardingProgress.completed?(merge_request.target_project.namespace, :merge_request_created)).to be(true)
end
end
end
diff --git a/spec/services/onboarding_progress_service_spec.rb b/spec/services/onboarding_progress_service_spec.rb
index de4c0d2a3ba..340face4ae8 100644
--- a/spec/services/onboarding_progress_service_spec.rb
+++ b/spec/services/onboarding_progress_service_spec.rb
@@ -11,32 +11,38 @@ RSpec.describe OnboardingProgressService do
subject(:execute_service) { described_class.new(namespace).execute(action: :subscription_created) }
context 'when the namespace is a root' do
- it 'records a namespace onboarding progress action fot the given namespace' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(namespace, :subscription_created).and_call_original
+ before do
+ OnboardingProgress.onboard(namespace)
+ end
+
+ it 'registers a namespace onboarding progress action for the given namespace' do
+ execute_service
- expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1)
+ expect(OnboardingProgress.completed?(namespace, :subscription_created)).to eq(true)
end
end
context 'when the namespace is not the root' do
let(:root_namespace) { build(:namespace) }
- it 'records a namespace onboarding progress action for the root namespace' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(root_namespace, :subscription_created).and_call_original
+ before do
+ OnboardingProgress.onboard(root_namespace)
+ end
+
+ it 'registers a namespace onboarding progress action for the root namespace' do
+ execute_service
- expect { execute_service }.to change(NamespaceOnboardingAction, :count).by(1)
+ expect(OnboardingProgress.completed?(root_namespace, :subscription_created)).to eq(true)
end
end
context 'when no namespace is passed' do
let(:namespace) { nil }
- it 'does not record a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).not_to receive(:create_action)
-
+ it 'does not register a namespace onboarding progress action' do
execute_service
+
+ expect(OnboardingProgress.completed?(root_namespace, :subscription_created)).to be(nil)
end
end
end
diff --git a/spec/services/post_receive_service_spec.rb b/spec/services/post_receive_service_spec.rb
index 4e303bfc20a..6e2cd7edf04 100644
--- a/spec/services/post_receive_service_spec.rb
+++ b/spec/services/post_receive_service_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe PostReceiveService do
include Gitlab::Routing
+ include AfterNextHelpers
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
@@ -46,8 +47,8 @@ RSpec.describe PostReceiveService do
expect(subject).to be_empty
end
- it 'does not record a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).not_to receive(:create_action)
+ it 'does not record an onboarding progress action' do
+ expect_next(OnboardingProgressService).not_to receive(:execute)
subject
end
@@ -87,9 +88,9 @@ RSpec.describe PostReceiveService do
expect(response.reference_counter_decreased).to be(true)
end
- it 'records a namespace onboarding progress action' do
- expect(NamespaceOnboardingAction).to receive(:create_action)
- .with(project.namespace, :git_write)
+ it 'records an onboarding progress action' do
+ expect_next(OnboardingProgressService, project.namespace)
+ .to receive(:execute).with(action: :git_write)
subject
end
diff --git a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
index 240a0b69834..f1789fa8fbd 100644
--- a/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
+++ b/spec/workers/namespaces/onboarding_pipeline_created_worker_spec.rb
@@ -7,20 +7,26 @@ RSpec.describe Namespaces::OnboardingPipelineCreatedWorker, '#perform' do
let_it_be(:ci_pipeline) { create(:ci_pipeline) }
- it 'records the event' do
+ before do
+ OnboardingProgress.onboard(ci_pipeline.project.namespace)
+ end
+
+ it 'registers an onboarding progress action' do
expect_next(OnboardingProgressService, ci_pipeline.project.namespace)
.to receive(:execute).with(action: :pipeline_created).and_call_original
- expect do
- subject.perform(ci_pipeline.project.namespace_id)
- end.to change(NamespaceOnboardingAction, :count).by(1)
+ subject.perform(ci_pipeline.project.namespace_id)
+
+ expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(true)
end
context "when a namespace doesn't exist" do
- it "does nothing" do
+ it 'does not register an onboarding progress action' do
expect_next(OnboardingProgressService, ci_pipeline.project.namespace).not_to receive(:execute)
- expect { subject.perform(nil) }.not_to change(NamespaceOnboardingAction, :count)
+ subject.perform(nil)
+
+ expect(OnboardingProgress.completed?(ci_pipeline.project.namespace, :pipeline_created)).to eq(false)
end
end
end
diff --git a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
index 03c668259f8..a773e160fab 100644
--- a/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
+++ b/spec/workers/namespaces/onboarding_user_added_worker_spec.rb
@@ -7,10 +7,16 @@ RSpec.describe Namespaces::OnboardingUserAddedWorker, '#perform' do
let_it_be(:group) { create(:group) }
- it 'records the event' do
+ before do
+ OnboardingProgress.onboard(group)
+ end
+
+ it 'registers an onboarding progress action' do
expect_next(OnboardingProgressService, group)
.to receive(:execute).with(action: :user_added).and_call_original
- expect { subject.perform(group.id) }.to change(NamespaceOnboardingAction, :count).by(1)
+ subject.perform(group.id)
+
+ expect(OnboardingProgress.completed?(group, :user_added)).to be(true)
end
end
diff --git a/yarn.lock b/yarn.lock
index 1520955baa6..df422680d02 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -876,10 +876,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
-"@gitlab/ui@25.4.0":
- version "25.4.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.4.0.tgz#67bfd2a905097fc4cec0272665c36c722b3475c9"
- integrity sha512-/dffpdyDcX102wWTbzDQOmOGfAEyDitRWCBOk2U+WRKPJIsWYtZuw40putwNA/gUUE1U08TPHf3sGSLzwIKZPA==
+"@gitlab/ui@25.7.2":
+ version "25.7.2"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-25.7.2.tgz#50271f99818645f9bc7ef675c08f9bf1bae54293"
+ integrity sha512-hgM9JHesIqnDujjJ16BHFQWYwzWd9php8xElhkGUdKWGV+PVw9TVdYcKfkIAb3TXtb9551uXN0Jv6wH5DRJyXw==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"