Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-06-29 21:07:38 +00:00
parent bc0c5df2f1
commit 97eb4a0095
39 changed files with 542 additions and 349 deletions

View File

@ -333,10 +333,6 @@ Rails/TimeZone:
- 'spec/tooling/rspec_flaky/listener_spec.rb'
- 'spec/tooling/rspec_flaky/report_spec.rb'
# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/325836
RSpec/EmptyLineAfterFinalLetItBe:
Exclude:
RSpec/TimecopFreeze:
Exclude:
- 'ee/spec/controllers/admin/application_settings_controller_spec.rb'

View File

@ -4,12 +4,10 @@ import blankProjectIllustration from '@gitlab/svgs/dist/illustrations/project-cr
import importProjectIllustration from '@gitlab/svgs/dist/illustrations/project-import-sm.svg';
import ciCdProjectIllustration from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg';
import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { experiment } from '~/experimentation/utils';
import { s__ } from '~/locale';
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
import NewProjectPushTipPopover from './new_project_push_tip_popover.vue';
const NEW_REPO_EXPERIMENT = 'new_repo';
const CI_CD_PANEL = 'cicd_for_external_repo';
const PANELS = [
{
@ -79,28 +77,8 @@ export default {
},
computed: {
decoratedPanels() {
const PANEL_TITLES = experiment(NEW_REPO_EXPERIMENT, {
use: () => ({
blank: s__('ProjectsNew|Create blank project'),
import: s__('ProjectsNew|Import project'),
}),
try: () => ({
blank: s__('ProjectsNew|Create blank project/repository'),
import: s__('ProjectsNew|Import project/repository'),
}),
});
return PANELS.map(({ key, title, ...el }) => ({
...el,
title: PANEL_TITLES[key] ?? title,
}));
},
availablePanels() {
return this.isCiCdAvailable
? this.decoratedPanels
: this.decoratedPanels.filter((p) => p.name !== CI_CD_PANEL);
return this.isCiCdAvailable ? PANELS : PANELS.filter((p) => p.name !== CI_CD_PANEL);
},
},
@ -112,7 +90,6 @@ export default {
}
},
},
EXPERIMENT: NEW_REPO_EXPERIMENT,
};
</script>
@ -122,7 +99,6 @@ export default {
:panels="availablePanels"
:jump-to-last-persisted-panel="hasErrors"
:title="s__('ProjectsNew|Create new project')"
:experiment="$options.EXPERIMENT"
persistence-key="new_project_last_active_tab"
@panel-change="resetProjectErrors"
>

View File

@ -16,14 +16,9 @@ export default {
type: Array,
required: true,
},
experiment: {
type: String,
required: false,
default: null,
},
},
created() {
const trackingMixin = Tracking.mixin({ ...gon.tracking_data, experiment: this.experiment });
const trackingMixin = Tracking.mixin();
const trackingInstance = new Vue({
...trackingMixin,
render() {

View File

@ -36,11 +36,6 @@ export default {
type: String,
required: true,
},
experiment: {
type: String,
required: false,
default: null,
},
},
data() {
@ -103,12 +98,7 @@ export default {
</script>
<template>
<welcome-page
v-if="activePanelName === null"
:panels="panels"
:title="title"
:experiment="experiment"
>
<welcome-page v-if="!activePanelName" :panels="panels" :title="title">
<template #footer>
<slot name="welcome-footer"> </slot>
</template>

View File

@ -39,11 +39,6 @@ class ProjectsController < Projects::ApplicationController
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
end
before_action only: [:new] do
# Run experiment before render so it will be written to the `gon` for FE
helpers.new_repo_experiment_text
end
layout :determine_layout
feature_category :projects, [
@ -78,7 +73,6 @@ class ProjectsController < Projects::ApplicationController
@project = ::Projects::CreateService.new(current_user, project_params(attributes: project_params_create_attributes)).execute
if @project.saved?
experiment(:new_repo, user: current_user).track(:project_created)
experiment(:new_project_readme, actor: current_user).track(
:created,
property: active_new_project_tab,

View File

@ -240,8 +240,7 @@ module EventsHelper
DESIGN_ICONS = {
'created' => 'upload',
'updated' => 'pencil',
'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed'],
'archived' => 'archive'
'destroyed' => ICON_NAMES_BY_EVENT_TYPE['destroyed']
}.freeze
def design_event_icon(action, size: 24)

View File

@ -21,13 +21,6 @@ module Nav
}
end
def new_repo_experiment_text
experiment(:new_repo, user: current_user) do |e|
e.use { _('New project') }
e.try { _('New project/repository') }
end.run
end
private
def group_menu_section(group)
@ -37,9 +30,9 @@ module Nav
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_project',
title: new_repo_experiment_text,
title: _('New project/repository'),
href: new_project_path(namespace_id: group.id),
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
data: { track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
)
)
end
@ -129,9 +122,9 @@ module Nav
menu_items.push(
::Gitlab::Nav::TopNavMenuItem.build(
id: 'general_new_project',
title: new_repo_experiment_text,
title: _('New project/repository'),
href: new_project_path,
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
data: { track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
)
)
end

View File

@ -98,7 +98,7 @@ module Nav
builder.add_primary_menu_item_with_shortcut(
active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]),
css_class: 'qa-projects-dropdown',
data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" },
data: { track_label: "projects_dropdown", track_event: "click_dropdown" },
view: PROJECTS_VIEW,
shortcut_href: dashboard_projects_path,
**projects_menu_item_attrs

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module ErrorTracking
def self.table_name_prefix
'error_tracking_'
end
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
class ErrorTracking::Error < ApplicationRecord
belongs_to :project
has_many :events, class_name: 'ErrorTracking::ErrorEvent'
validates :project, presence: true
validates :name, presence: true
validates :description, presence: true
validates :actor, presence: true
end

View File

@ -0,0 +1,11 @@
# frozen_string_literal: true
class ErrorTracking::ErrorEvent < ApplicationRecord
belongs_to :error
validates :payload, json_schema: { filename: 'error_tracking_event_payload' }
validates :error, presence: true
validates :description, presence: true
validates :occurred_at, presence: true
end

View File

@ -24,6 +24,8 @@ module ErrorTracking
self.reactive_cache_key = ->(setting) { [setting.class.model_name.singular, setting.project_id] }
self.reactive_cache_work_type = :external_dependency
self.table_name = 'project_error_tracking_settings'
belongs_to :project
validates :api_url, length: { maximum: 255 }, public_url: { enforce_sanitization: true, ascii_only: true }, allow_nil: true

View File

@ -24,15 +24,14 @@ class Event < ApplicationRecord
left: 9, # User left project
destroyed: 10,
expired: 11, # User left project due to expiry
approved: 12,
archived: 13 # Recoverable deletion
approved: 12
).freeze
private_constant :ACTIONS
WIKI_ACTIONS = [:created, :updated, :destroyed].freeze
DESIGN_ACTIONS = [:created, :updated, :destroyed, :archived].freeze
DESIGN_ACTIONS = [:created, :updated, :destroyed].freeze
TARGET_TYPES = HashWithIndifferentAccess.new(
issue: Issue,
@ -437,8 +436,7 @@ class Event < ApplicationRecord
{
created: _('uploaded'),
updated: _('revised'),
destroyed: _('deleted'),
archived: _('archived')
destroyed: _('deleted')
}
end

View File

@ -0,0 +1,324 @@
{
"description": "Error tracking event payload",
"type": "object",
"required": [],
"properties": {
"event_id": {
"type": "string"
},
"level": {
"type": "string"
},
"timestamp": {
"type": "string"
},
"release": {
"type": "string"
},
"environment": {
"type": "string"
},
"server_name": {
"type": "string"
},
"message": {
"type": "string"
},
"user": {
"type": "object",
"required": [],
"properties": {}
},
"tags": {
"type": "object",
"required": [],
"properties": {
"request_id": {
"type": "string"
}
}
},
"contexts": {
"type": "object",
"required": [],
"properties": {
"os": {
"type": "object",
"required": [],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"build": {
"type": "string"
},
"kernel_version": {
"type": "string"
}
}
},
"runtime": {
"type": "object",
"required": [],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"trace": {
"type": "object",
"required": [],
"properties": {
"trace_id": {
"type": "string"
},
"span_id": {
"type": "string"
},
"parent_span_id": {
"type": "string"
},
"description": {
"type": "string"
},
"op": {
"type": "string"
},
"status": {
"type": "string"
}
}
}
}
},
"fingerprint": {
"type": "array",
"items": {
"type": "string"
}
},
"breadcrumbs": {
"type": "object",
"required": [],
"properties": {
"values": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"category": {
"type": "string"
},
"data": {
"type": "object",
"required": [],
"properties": {
"controller": {
"type": "string"
},
"action": {
"type": "string"
},
"params": {
"type": "object",
"required": [],
"properties": {
"controller": {
"type": "string"
},
"action": {
"type": "string"
}
}
},
"format": {
"type": "string"
},
"method": {
"type": "string"
},
"path": {
"type": "string"
},
"start_timestamp": {
"type": "number"
}
}
},
"level": {
"type": "string"
},
"message": {
"type": "string"
},
"timestamp": {
"type": "number"
},
"type": {
"type": "string"
}
}
}
}
}
},
"transaction": {
"type": "string"
},
"platform": {
"type": "string"
},
"sdk": {
"type": "object",
"required": [],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"request": {
"type": "object",
"required": [],
"properties": {
"url": {
"type": "string"
},
"method": {
"type": "string"
},
"headers": {
"type": "object",
"required": [],
"properties": {
"Host": {
"type": "string"
},
"User-Agent": {
"type": "string"
},
"Accept": {
"type": "string"
},
"Accept-Language": {
"type": "string"
},
"Accept-Encoding": {
"type": "string"
},
"Referer": {
"type": "string"
},
"Turbolinks-Referrer": {
"type": "string"
},
"Connection": {
"type": "string"
},
"X-Request-Id": {
"type": "string"
}
}
},
"env": {
"type": "object",
"required": [],
"properties": {
"SERVER_NAME": {
"type": "string"
},
"SERVER_PORT": {
"type": "string"
}
}
}
}
},
"exception": {
"type": "object",
"required": [],
"properties": {
"values": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"type": {
"type": "string"
},
"value": {
"type": "string"
},
"module": {
"type": "string"
},
"thread_id": {
"type": "number"
},
"stacktrace": {
"type": "object",
"required": [],
"properties": {
"frames": {
"type": "array",
"items": {
"type": "object",
"required": [],
"properties": {
"project_root": {
"type": "string"
},
"abs_path": {
"type": "string"
},
"function": {
"type": "string"
},
"lineno": {
"type": "number"
},
"in_app": {
"type": "string"
},
"filename": {
"type": "string"
},
"pre_context": {
"type": "array",
"items": {
"type": "string"
}
},
"context_line": {
"type": "string"
},
"post_context": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
}
}

View File

@ -6,7 +6,7 @@
- return if menu_sections.empty?
%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }
%li.header-new.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_event: "click_dropdown" } }
= link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do
= sprite_icon('plus-square')
= sprite_icon('chevron-down', css_class: 'caret-down')

View File

@ -4,7 +4,7 @@
-# [1]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56587
%ul.list-unstyled.navbar-sub-nav
- if dashboard_nav_link?(:projects)
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: { track_label: "projects_dropdown", track_event: "click_dropdown", track_experiment: "new_repo" } }) do
= nav_link(path: ['root#index', 'projects#trending', 'projects#starred', 'dashboard/projects#index'], html_options: { id: 'nav-projects-dropdown', class: "home dropdown header-projects", data: { track_label: "projects_dropdown", track_event: "click_dropdown" } }) do
%button{ type: 'button', data: { toggle: "dropdown" } }
= _('Projects')
= sprite_icon('chevron-down', css_class: 'caret-down')

View File

@ -15,21 +15,12 @@
= nav_link(path: 'projects#trending') do
= link_to explore_root_path, data: { track_label: "projects_dropdown_explore_projects", track_event: "click_link" } do
= _('Explore projects')
- experiment(:new_repo, user: current_user) do |e|
- e.use do
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
= link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "create_project_link" } do
= _('Create blank project')
= nav_link(path: 'projects/new#import_project') do
= link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo", qa_selector: "import_project_link" } do
= _('Import project')
- e.try do
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
= link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", track_experiment: "new_repo" } do
= _('Create blank project/repository')
= nav_link(path: 'projects/new#import_project') do
= link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", track_experiment: "new_repo" } do
= _('Import project/repository')
= nav_link(path: 'projects/new#blank_project', html_options: { class: 'gl-border-0 gl-border-t-1 gl-border-solid gl-border-gray-100' }) do
= link_to new_project_path(anchor: 'blank_project'), data: { track_label: "projects_dropdown_blank_project", track_event: "click_link", qa_selector: "create_project_link" } do
= _('Create blank project')
= nav_link(path: 'projects/new#import_project') do
= link_to new_project_path(anchor: 'import_project'), data: { track_label: "projects_dropdown_import_project", track_event: "click_link", qa_selector: "import_project_link" } do
= _('Import project')
= nav_link(path: 'projects/new#create_from_template') do
= link_to new_project_path(anchor: 'create_from_template'), data: { track_label: "projects_dropdown_create_from_template", track_event: "click_link" } do
= _('Create from template')

View File

@ -1,8 +0,0 @@
---
name: new_repo
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55818
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/285153
milestone: '13.11'
type: experiment
group: group::adoption
default_enabled: false

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
class CreateErrorTrackingErrors < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
def up
create_table_with_constraints :error_tracking_errors do |t|
t.references :project, index: true, null: false, foreign_key: { on_delete: :cascade }
t.text :name, null: false
t.text :description, null: false
t.text :actor, null: false
t.datetime_with_timezone :first_seen_at, null: false, default: -> { 'NOW()' }
t.datetime_with_timezone :last_seen_at, null: false, default: -> { 'NOW()' }
t.text :platform
t.text_limit :name, 255
t.text_limit :description, 1024
t.text_limit :actor, 255
t.text_limit :platform, 255
t.timestamps_with_timezone
end
end
def down
drop_table :error_tracking_errors
end
end

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
class CreateErrorTrackingErrorEvents < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
def up
create_table_with_constraints :error_tracking_error_events do |t|
t.references :error,
index: true,
null: false,
foreign_key: { on_delete: :cascade, to_table: :error_tracking_errors }
t.text :description, null: false
t.text :environment
t.text :level
t.datetime_with_timezone :occurred_at, null: false
t.jsonb :payload, null: false, default: {}
t.text_limit :description, 255
t.text_limit :environment, 255
t.text_limit :level, 255
t.timestamps_with_timezone
end
end
def down
drop_table :error_tracking_error_events
end
end

View File

@ -0,0 +1 @@
1a930fec524c91c5d382c40514d0d1943e59514f5dbd8588595363c24819b8d0

View File

@ -0,0 +1 @@
df9e976b0f294284ad9e9b617da42310c83cb1acc6db6ea00ea93c49c2310a1c

View File

@ -12732,6 +12732,56 @@ CREATE SEQUENCE epics_id_seq
ALTER SEQUENCE epics_id_seq OWNED BY epics.id;
CREATE TABLE error_tracking_error_events (
id bigint NOT NULL,
error_id bigint NOT NULL,
description text NOT NULL,
environment text,
level text,
occurred_at timestamp with time zone NOT NULL,
payload jsonb DEFAULT '{}'::jsonb NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
CONSTRAINT check_92ecc3077b CHECK ((char_length(description) <= 255)),
CONSTRAINT check_c67d5b8007 CHECK ((char_length(level) <= 255)),
CONSTRAINT check_f4b52474ad CHECK ((char_length(environment) <= 255))
);
CREATE SEQUENCE error_tracking_error_events_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE error_tracking_error_events_id_seq OWNED BY error_tracking_error_events.id;
CREATE TABLE error_tracking_errors (
id bigint NOT NULL,
project_id bigint NOT NULL,
name text NOT NULL,
description text NOT NULL,
actor text NOT NULL,
first_seen_at timestamp with time zone DEFAULT now() NOT NULL,
last_seen_at timestamp with time zone DEFAULT now() NOT NULL,
platform text,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
CONSTRAINT check_18a758e537 CHECK ((char_length(name) <= 255)),
CONSTRAINT check_b5cb4d3888 CHECK ((char_length(actor) <= 255)),
CONSTRAINT check_c739788b12 CHECK ((char_length(description) <= 1024)),
CONSTRAINT check_fe99886883 CHECK ((char_length(platform) <= 255))
);
CREATE SEQUENCE error_tracking_errors_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER SEQUENCE error_tracking_errors_id_seq OWNED BY error_tracking_errors.id;
CREATE TABLE events (
id integer NOT NULL,
project_id integer,
@ -19887,6 +19937,10 @@ ALTER TABLE ONLY epic_user_mentions ALTER COLUMN id SET DEFAULT nextval('epic_us
ALTER TABLE ONLY epics ALTER COLUMN id SET DEFAULT nextval('epics_id_seq'::regclass);
ALTER TABLE ONLY error_tracking_error_events ALTER COLUMN id SET DEFAULT nextval('error_tracking_error_events_id_seq'::regclass);
ALTER TABLE ONLY error_tracking_errors ALTER COLUMN id SET DEFAULT nextval('error_tracking_errors_id_seq'::regclass);
ALTER TABLE ONLY events ALTER COLUMN id SET DEFAULT nextval('events_id_seq'::regclass);
ALTER TABLE ONLY evidences ALTER COLUMN id SET DEFAULT nextval('evidences_id_seq'::regclass);
@ -21197,6 +21251,12 @@ ALTER TABLE ONLY epic_user_mentions
ALTER TABLE ONLY epics
ADD CONSTRAINT epics_pkey PRIMARY KEY (id);
ALTER TABLE ONLY error_tracking_error_events
ADD CONSTRAINT error_tracking_error_events_pkey PRIMARY KEY (id);
ALTER TABLE ONLY error_tracking_errors
ADD CONSTRAINT error_tracking_errors_pkey PRIMARY KEY (id);
ALTER TABLE ONLY events
ADD CONSTRAINT events_pkey PRIMARY KEY (id);
@ -23343,6 +23403,10 @@ CREATE INDEX index_epics_on_start_date_sourcing_epic_id ON epics USING btree (st
CREATE INDEX index_epics_on_start_date_sourcing_milestone_id ON epics USING btree (start_date_sourcing_milestone_id);
CREATE INDEX index_error_tracking_error_events_on_error_id ON error_tracking_error_events USING btree (error_id);
CREATE INDEX index_error_tracking_errors_on_project_id ON error_tracking_errors USING btree (project_id);
CREATE INDEX index_esc_protected_branches_on_external_status_check_id ON external_status_checks_protected_branches USING btree (external_status_check_id);
CREATE INDEX index_esc_protected_branches_on_protected_branch_id ON external_status_checks_protected_branches USING btree (protected_branch_id);
@ -26560,6 +26624,9 @@ ALTER TABLE ONLY packages_debian_group_component_files
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 error_tracking_error_events
ADD CONSTRAINT fk_rails_2c096c0076 FOREIGN KEY (error_id) REFERENCES error_tracking_errors(id) ON DELETE CASCADE;
ALTER TABLE ONLY onboarding_progresses
ADD CONSTRAINT fk_rails_2ccfd420cc FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@ -26968,6 +27035,9 @@ ALTER TABLE ONLY plan_limits
ALTER TABLE ONLY operations_feature_flags_issues
ADD CONSTRAINT fk_rails_6a8856ca4f FOREIGN KEY (feature_flag_id) REFERENCES operations_feature_flags(id) ON DELETE CASCADE;
ALTER TABLE ONLY error_tracking_errors
ADD CONSTRAINT fk_rails_6b41f837ba FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY prometheus_alerts
ADD CONSTRAINT fk_rails_6d9b283465 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;

View File

@ -14378,7 +14378,6 @@ Event action.
| Value | Description |
| ----- | ----------- |
| <a id="eventactionapproved"></a>`APPROVED` | Approved action. |
| <a id="eventactionarchived"></a>`ARCHIVED` | Archived action. |
| <a id="eventactionclosed"></a>`CLOSED` | Closed action. |
| <a id="eventactioncommented"></a>`COMMENTED` | Commented action. |
| <a id="eventactioncreated"></a>`CREATED` | Created action. |

View File

@ -9093,9 +9093,6 @@ msgstr ""
msgid "Create blank project"
msgstr ""
msgid "Create blank project/repository"
msgstr ""
msgid "Create branch"
msgstr ""
@ -16503,9 +16500,6 @@ msgstr ""
msgid "Import project members"
msgstr ""
msgid "Import project/repository"
msgstr ""
msgid "Import projects from Bitbucket"
msgstr ""
@ -25964,9 +25958,6 @@ msgstr ""
msgid "ProjectsNew|Create blank project"
msgstr ""
msgid "ProjectsNew|Create blank project/repository"
msgstr ""
msgid "ProjectsNew|Create from template"
msgstr ""
@ -25982,9 +25973,6 @@ msgstr ""
msgid "ProjectsNew|Import project"
msgstr ""
msgid "ProjectsNew|Import project/repository"
msgstr ""
msgid "ProjectsNew|Initialize repository with a README"
msgstr ""

View File

@ -459,12 +459,6 @@ RSpec.describe ProjectsController do
post :create, params: { project: project_params }
end
it 'tracks a created event for the new_repo experiment', :experiment do
expect(experiment(:new_repo, :candidate)).to track(:project_created).on_next_instance
post :create, params: { project: project_params }
end
end
describe 'POST #archive' do

View File

@ -17,7 +17,6 @@ FactoryBot.define do
trait(:left) { action { :left } }
trait(:destroyed) { action { :destroyed } }
trait(:expired) { action { :expired } }
trait(:archived) { action { :archived } }
trait(:approved) { action { :approved } }
factory :closed_issue_event do

View File

@ -447,35 +447,6 @@ RSpec.describe 'Group' do
end
end
describe 'new_repo experiment' do
let_it_be(:group) { create_default(:group) }
it 'when in candidate renders "project/repository"' do
stub_experiments(new_repo: :candidate)
visit group_path(group)
find('li.header-new.dropdown').click
page.within('li.header-new.dropdown') do
expect(page).to have_selector('a', text: 'New project/repository')
end
end
it 'when in control renders "project/repository"' do
stub_experiments(new_repo: :control)
visit group_path(group)
find('li.header-new.dropdown').click
page.within('li.header-new.dropdown') do
expect(page).to have_selector('a', text: 'New project')
expect(page).to have_no_selector('a', text: 'New project/repository')
end
end
end
def remove_with_confirm(button_text, confirm_with)
click_button button_text
fill_in 'confirm_name_input', with: confirm_with

View File

@ -8,7 +8,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
let_it_be(:uploader) { create(:user) }
let_it_be(:editor) { create(:user) }
let_it_be(:deleter) { create(:user) }
let_it_be(:archiver) { create(:user) }
def design_activity(user, action)
[user.name, user.to_reference, action, 'design'].join(' ')
@ -24,7 +23,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
create(:design_event, :created, author: uploader, **common_attrs)
create(:design_event, :updated, author: editor, **common_attrs)
create(:design_event, :destroyed, author: deleter, **common_attrs)
create(:design_event, :archived, author: archiver, **common_attrs)
end
before do
@ -39,7 +37,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
expect(page).to have_content(design_activity(uploader, 'uploaded'))
expect(page).to have_content(design_activity(editor, 'revised'))
expect(page).to have_content(design_activity(deleter, 'deleted'))
expect(page).to have_content(design_activity(archiver, 'archived'))
end
it 'allows filtering out the design events', :aggregate_failures do
@ -48,7 +45,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
expect(page).not_to have_content(design_activity(uploader, 'uploaded'))
expect(page).not_to have_content(design_activity(editor, 'revised'))
expect(page).not_to have_content(design_activity(deleter, 'deleted'))
expect(page).not_to have_content(design_activity(archiver, 'archived'))
end
it 'allows filtering in the design events', :aggregate_failures do
@ -58,7 +54,6 @@ RSpec.describe 'Projects > Activity > User sees design Activity', :js do
expect(page).to have_content(design_activity(uploader, 'uploaded'))
expect(page).to have_content(design_activity(editor, 'revised'))
expect(page).to have_content(design_activity(deleter, 'deleted'))
expect(page).to have_content(design_activity(archiver, 'archived'))
end
end

View File

@ -14,75 +14,6 @@ RSpec.describe 'New project', :js do
sign_in(user)
end
context 'new repo experiment', :experiment do
it 'when in control renders "project"' do
stub_experiments(new_repo: :control)
visit new_project_path
find('li.header-new.dropdown').click
page.within('li.header-new.dropdown') do
expect(page).to have_selector('a', text: 'New project')
expect(page).to have_no_selector('a', text: 'New project/repository')
end
expect(page).to have_selector('h3', text: 'Create blank project')
expect(page).to have_no_selector('h3', text: 'Create blank project/repository')
end
it 'when in candidate renders "project/repository"' do
stub_experiments(new_repo: :candidate)
visit new_project_path
find('li.header-new.dropdown').click
page.within('li.header-new.dropdown') do
expect(page).to have_selector('a', text: 'New project/repository')
end
expect(page).to have_selector('h3', text: 'Create blank project/repository')
end
it 'when in control it renders "project" in the new projects dropdown' do
stub_experiments(new_repo: :control)
visit new_project_path
open_top_nav_projects
within_top_nav do
if Feature.enabled?(:combined_menu, default_enabled: :yaml)
expect(page).to have_selector('a', text: 'Create new project')
expect(page).to have_no_selector('a', text: 'Create blank project/repository')
else
expect(page).to have_selector('a', text: 'Create blank project')
expect(page).to have_selector('a', text: 'Import project')
expect(page).to have_no_selector('a', text: 'Create blank project/repository')
expect(page).to have_no_selector('a', text: 'Import project/repository')
end
end
end
it 'when in candidate it renders "project/repository" in the new projects dropdown' do
stub_experiments(new_repo: :candidate)
visit new_project_path
open_top_nav_projects
within_top_nav do
if Feature.enabled?(:combined_menu, default_enabled: :yaml)
expect(page).to have_selector('a', text: 'Create new project')
else
expect(page).to have_selector('a', text: 'Create blank project/repository')
expect(page).to have_selector('a', text: 'Import project/repository')
end
end
end
end
it 'shows a message if multiple levels are restricted' do
Gitlab::CurrentSettings.update!(
restricted_visibility_levels: [Gitlab::VisibilityLevel::PRIVATE, Gitlab::VisibilityLevel::INTERNAL]

View File

@ -1,13 +1,10 @@
import { shallowMount } from '@vue/test-utils';
import { assignGitlabExperiment } from 'helpers/experimentation_helper';
import App from '~/pages/projects/new/components/app.vue';
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
describe('Experimental new project creation app', () => {
let wrapper;
const findNewNamespacePage = () => wrapper.findComponent(NewNamespacePage);
const createComponent = (propsData) => {
wrapper = shallowMount(App, { propsData });
};
@ -16,36 +13,6 @@ describe('Experimental new project creation app', () => {
wrapper.destroy();
});
describe('new_repo experiment', () => {
it('passes new_repo experiment', () => {
createComponent();
expect(findNewNamespacePage().props().experiment).toBe('new_repo');
});
describe('when in the candidate variant', () => {
assignGitlabExperiment('new_repo', 'candidate');
it('has "repository" in the panel title', () => {
createComponent();
expect(findNewNamespacePage().props().panels[0].title).toBe(
'Create blank project/repository',
);
});
});
describe('when in the control variant', () => {
assignGitlabExperiment('new_repo', 'control');
it('has "project" in the panel title', () => {
createComponent();
expect(findNewNamespacePage().props().panels[0].title).toBe('Create blank project');
});
});
});
it('passes custom new project guideline text to underlying component', () => {
const DEMO_GUIDELINES = 'Demo guidelines';
const guidelineSelector = '#new-project-guideline';

View File

@ -1,8 +1,6 @@
import { GlAlert, GlToggle, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import MockAxiosAdapter from 'axios-mock-adapter';
import CcValidationRequiredAlert from 'ee_component/billings/components/cc_validation_required_alert.vue';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
import SharedRunnersToggleComponent from '~/projects/settings/components/shared_runners_toggle.vue';
@ -31,7 +29,6 @@ describe('projects/settings/components/shared_runners', () => {
const findErrorAlert = () => wrapper.find(GlAlert);
const findSharedRunnersToggle = () => wrapper.find(GlToggle);
const findToggleTooltip = () => wrapper.find(GlTooltip);
const findCcValidationRequiredAlert = () => wrapper.findComponent(CcValidationRequiredAlert);
const getToggleValue = () => findSharedRunnersToggle().props('value');
const isToggleLoading = () => findSharedRunnersToggle().props('isLoading');
const isToggleDisabled = () => findSharedRunnersToggle().props('disabled');
@ -158,40 +155,4 @@ describe('projects/settings/components/shared_runners', () => {
});
});
});
describe('with credit card validation required and shared runners DISABLED', () => {
beforeEach(() => {
window.gon = {
subscriptions_url: TEST_HOST,
payment_form_url: TEST_HOST,
};
createComponent({
isCreditCardValidationRequired: true,
isEnabled: false,
});
});
it('toggle should not be visible', () => {
expect(findSharedRunnersToggle().exists()).toBe(false);
});
it('credit card validation component should exist', () => {
expect(findCcValidationRequiredAlert().exists()).toBe(true);
expect(findCcValidationRequiredAlert().text()).toBe(
SharedRunnersToggleComponent.i18n.REQUIRES_VALIDATION_TEXT,
);
});
describe('when credit card is validated', () => {
it('should show the toggle button', async () => {
findCcValidationRequiredAlert().vm.$emit('verifiedCreditCard');
await waitForPromises();
expect(findSharedRunnersToggle().exists()).toBe(true);
expect(getToggleValue()).toBe(false);
expect(isToggleDisabled()).toBe(false);
});
});
});
});

View File

@ -1,12 +1,8 @@
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { mockTracking } from 'helpers/tracking_helper';
import { TRACKING_CONTEXT_SCHEMA } from '~/experimentation/constants';
import { getExperimentData } from '~/experimentation/utils';
import WelcomePage from '~/vue_shared/new_namespace/components/welcome.vue';
jest.mock('~/experimentation/utils', () => ({ getExperimentData: jest.fn() }));
describe('Welcome page', () => {
let wrapper;
let trackingSpy;
@ -28,7 +24,6 @@ describe('Welcome page', () => {
beforeEach(() => {
trackingSpy = mockTracking('_category_', document, jest.spyOn);
trackingSpy.mockImplementation(() => {});
getExperimentData.mockReturnValue(undefined);
});
afterEach(() => {
@ -38,7 +33,7 @@ describe('Welcome page', () => {
});
it('tracks link clicks', async () => {
createComponent({ propsData: { experiment: 'foo', panels: [{ name: 'test', href: '#' }] } });
createComponent({ propsData: { panels: [{ name: 'test', href: '#' }] } });
const link = wrapper.find('a');
link.trigger('click');
await nextTick();
@ -47,25 +42,6 @@ describe('Welcome page', () => {
});
});
it('adds experiment data if in experiment', async () => {
const mockExperimentData = 'data';
getExperimentData.mockReturnValue(mockExperimentData);
createComponent({ propsData: { experiment: 'foo', panels: [{ name: 'test', href: '#' }] } });
const link = wrapper.find('a');
link.trigger('click');
await nextTick();
return wrapper.vm.$nextTick().then(() => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_tab', {
label: 'test',
context: {
data: mockExperimentData,
schema: TRACKING_CONTEXT_SCHEMA,
},
});
});
});
it('renders footer slot if provided', () => {
const DUMMY = 'Test message';
createComponent({

View File

@ -37,13 +37,6 @@ describe('Experimental new project creation app', () => {
window.location.hash = '';
});
it('passes experiment to welcome component if provided', () => {
const EXPERIMENT = 'foo';
createComponent({ propsData: { experiment: EXPERIMENT } });
expect(findWelcomePage().props().experiment).toBe(EXPERIMENT);
});
describe('with empty hash', () => {
beforeEach(() => {
createComponent();

View File

@ -13,7 +13,6 @@ RSpec.describe Nav::NewDropdownHelper do
let(:with_can_create_project) { false }
let(:with_can_create_group) { false }
let(:with_can_create_snippet) { false }
let(:with_new_repo_experiment) { :control }
let(:with_invite_members_experiment) { false }
let(:with_invite_members_experiment_enabled) { false }
@ -29,7 +28,6 @@ RSpec.describe Nav::NewDropdownHelper do
end
before do
stub_experiments(new_repo: with_new_repo_experiment)
allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment }
allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled }
allow(helper).to receive(:tracking_label) { 'test_tracking_label' }
@ -43,19 +41,6 @@ RSpec.describe Nav::NewDropdownHelper do
allow(user).to receive(:can?).with(:create_snippet) { with_can_create_snippet }
end
shared_examples 'new repo experiment shared example' do |title|
let(:with_new_repo_experiment) { :candidate }
it 'has experiment project title' do
expect(subject[:menu_sections]).to match(
expected_menu_section(
title: title,
menu_item: a_hash_including(title: 'New project/repository')
)
)
end
end
shared_examples 'invite member link shared example' do
it 'shows invite member link' do
expect(subject[:menu_sections]).to eq(
@ -117,15 +102,13 @@ RSpec.describe Nav::NewDropdownHelper do
title: 'GitLab',
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'general_new_project',
title: 'New project',
title: 'New project/repository',
href: '/projects/new',
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
data: { track_event: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' }
)
)
)
end
it_behaves_like 'new repo experiment shared example', 'GitLab'
end
context 'when can create group' do
@ -193,15 +176,13 @@ RSpec.describe Nav::NewDropdownHelper do
title: 'This group',
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'new_project',
title: 'New project',
title: 'New project/repository',
href: "/projects/new?namespace_id=#{group.id}",
data: { track_experiment: 'new_repo', track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
data: { track_event: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' }
)
)
)
end
it_behaves_like 'new repo experiment shared example', 'This group'
end
context 'when can create subgroup' do

View File

@ -143,7 +143,6 @@ RSpec.describe Nav::TopNavHelper do
css_class: 'qa-projects-dropdown',
data: {
track_event: 'click_dropdown',
track_experiment: 'new_repo',
track_label: 'projects_dropdown'
},
icon: 'project',

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ErrorTracking::ErrorEvent, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:error) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:description) }
it { is_expected.to validate_presence_of(:occurred_at) }
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe ErrorTracking::Error, type: :model do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:events) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_presence_of(:description) }
it { is_expected.to validate_presence_of(:actor) }
end
end

View File

@ -978,14 +978,13 @@ RSpec.describe Event do
describe '#action_name' do
it 'handles all valid design events' do
created, updated, destroyed, archived = %i[created updated destroyed archived].map do |trait|
created, updated, destroyed = %i[created updated destroyed].map do |trait|
build(:design_event, trait).action_name
end
expect(created).to eq('uploaded')
expect(updated).to eq('revised')
expect(destroyed).to eq('deleted')
expect(archived).to eq('archived')
end
it 'handles correct push_action' do