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:
authorGitLab Bot <gitlab-bot@gitlab.com>2024-01-19 21:09:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2024-01-19 21:09:33 +0300
commitd1be3e6f776e1c77976537548c1daa9af2fb2650 (patch)
tree387d3c8f06e18bbfa24a4b0b015a7245e166927c
parent8f3a9dbb94b5a9ae4570a22bbc2a75e7572407c8 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop.yml6
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/batch_comments/components/submit_dropdown.vue2
-rw-r--r--app/assets/javascripts/ci/catalog/components/list/catalog_tabs.vue4
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_note.vue8
-rw-r--r--app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue134
-rw-r--r--app/assets/javascripts/ml/model_registry/components/candidate_list.vue21
-rw-r--r--app/assets/javascripts/ml/model_registry/components/model_row.vue33
-rw-r--r--app/assets/javascripts/ml/model_registry/components/model_version_list.vue21
-rw-r--r--app/assets/javascripts/ml/model_registry/components/searchable_list.vue87
-rw-r--r--app/assets/javascripts/ml/model_registry/graphql/queries/get_models.query.graphql46
-rw-r--r--app/assets/javascripts/ml/model_registry/translations.js5
-rw-r--r--app/assets/javascripts/organizations/shared/components/new_edit_form.vue1
-rw-r--r--app/assets/javascripts/organizations/show/components/organization_avatar.vue4
-rw-r--r--app/assets/javascripts/work_items/components/notes/work_item_note.vue8
-rw-r--r--app/components/pajamas/avatar_component.rb1
-rw-r--r--app/controllers/admin/application_settings_controller.rb4
-rw-r--r--app/controllers/projects/ml/models_controller.rb12
-rw-r--r--app/graphql/resolvers/ml/find_models_resolver.rb2
-rw-r--r--app/graphql/resolvers/ml/model_detail_resolver.rb2
-rw-r--r--app/graphql/types/ci/pipeline_type.rb3
-rw-r--r--app/graphql/types/projects/service_type_enum.rb2
-rw-r--r--app/helpers/projects/ml/model_registry_helper.rb30
-rw-r--r--app/models/ci/pipeline.rb4
-rw-r--r--app/models/commit.rb2
-rw-r--r--app/models/integration.rb46
-rw-r--r--app/models/integrations/beyond_identity.rb54
-rw-r--r--app/models/project.rb6
-rw-r--r--app/models/repository.rb26
-rw-r--r--app/services/ci/create_web_ide_terminal_service.rb2
-rw-r--r--app/services/gpg_keys/create_service.rb16
-rw-r--r--app/services/gpg_keys/validate_integrations_service.rb33
-rw-r--r--app/views/projects/ml/models/index.html.haml2
-rw-r--r--app/views/shared/icons/_abuse_reports.svg1
-rw-r--r--app/views/shared/icons/_access_tokens.svg1
-rw-r--r--app/views/shared/icons/_account.svg1
-rw-r--r--app/views/shared/icons/_appearance.svg1
-rw-r--r--app/views/shared/icons/_applications.svg1
-rw-r--r--app/views/shared/icons/_authentication_log.svg1
-rw-r--r--app/views/shared/icons/_chat.svg1
-rw-r--r--app/views/shared/icons/_collapse.svg.erb1
-rw-r--r--app/views/shared/icons/_container_registry.svg1
-rw-r--r--app/views/shared/icons/_dev_ops_report_no_index.svg64
-rw-r--r--app/views/shared/icons/_doc_text.svg1
-rw-r--r--app/views/shared/icons/_ellipsis_v.svg1
-rw-r--r--app/views/shared/icons/_emails.svg1
-rw-r--r--app/views/shared/icons/_gitea_logo.svg.erb1
-rw-r--r--app/views/shared/icons/_go_logo.svg.erb1
-rw-r--r--app/views/shared/icons/_group.svg.erb13
-rw-r--r--app/views/shared/icons/_i2p_step_1.svg12
-rw-r--r--app/views/shared/icons/_i2p_step_10.svg12
-rw-r--r--app/views/shared/icons/_i2p_step_2.svg5
-rw-r--r--app/views/shared/icons/_i2p_step_3.svg12
-rw-r--r--app/views/shared/icons/_i2p_step_4.svg6
-rw-r--r--app/views/shared/icons/_i2p_step_5.svg5
-rw-r--r--app/views/shared/icons/_i2p_step_6.svg15
-rw-r--r--app/views/shared/icons/_i2p_step_7.svg7
-rw-r--r--app/views/shared/icons/_i2p_step_8.svg4
-rw-r--r--app/views/shared/icons/_i2p_step_9.svg4
-rw-r--r--app/views/shared/icons/_icon_action_cancel.svg1
-rw-r--r--app/views/shared/icons/_icon_action_play.svg1
-rw-r--r--app/views/shared/icons/_icon_action_retry.svg1
-rw-r--r--app/views/shared/icons/_icon_action_stop.svg1
-rw-r--r--app/views/shared/icons/_icon_arrow_circle_o_right.svg2
-rw-r--r--app/views/shared/icons/_icon_arrow_right.svg.erb1
-rw-r--r--app/views/shared/icons/_icon_autodevops.svg54
-rw-r--r--app/views/shared/icons/_icon_calendar.svg1
-rw-r--r--app/views/shared/icons/_icon_check_square_o.svg2
-rw-r--r--app/views/shared/icons/_icon_clock_o.svg1
-rw-r--r--app/views/shared/icons/_icon_clone.svg2
-rw-r--r--app/views/shared/icons/_icon_close.svg1
-rw-r--r--app/views/shared/icons/_icon_code_fork.svg2
-rw-r--r--app/views/shared/icons/_icon_comment_o.svg2
-rw-r--r--app/views/shared/icons/_icon_customization.svg1
-rw-r--r--app/views/shared/icons/_icon_cycle_analytics_overview.svg81
-rw-r--r--app/views/shared/icons/_icon_cycle_analytics_splash.svg1
-rw-r--r--app/views/shared/icons/_icon_edit.svg2
-rw-r--r--app/views/shared/icons/_icon_empty_metrics.svg5
-rw-r--r--app/views/shared/icons/_icon_eye.svg2
-rw-r--r--app/views/shared/icons/_icon_eye_slash.svg2
-rw-r--r--app/views/shared/icons/_icon_fork.svg1
-rw-r--r--app/views/shared/icons/_icon_history.svg1
-rw-r--r--app/views/shared/icons/_icon_hourglass.svg1
-rw-r--r--app/views/shared/icons/_icon_lock.svg25
-rw-r--r--app/views/shared/icons/_icon_merge.svg1
-rw-r--r--app/views/shared/icons/_icon_merged.svg2
-rw-r--r--app/views/shared/icons/_icon_mr_issue.svg1
-rw-r--r--app/views/shared/icons/_icon_no_data.svg27
-rw-r--r--app/views/shared/icons/_icon_no_wrap.svg3
-rw-r--r--app/views/shared/icons/_icon_pencil.svg2
-rw-r--r--app/views/shared/icons/_icon_play.svg1
-rw-r--r--app/views/shared/icons/_icon_random.svg2
-rw-r--r--app/views/shared/icons/_icon_service_desk.svg1
-rw-r--r--app/views/shared/icons/_icon_soft_wrap.svg3
-rw-r--r--app/views/shared/icons/_icon_status_canceled.svg1
-rw-r--r--app/views/shared/icons/_icon_status_canceled_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_closed.svg1
-rw-r--r--app/views/shared/icons/_icon_status_created.svg1
-rw-r--r--app/views/shared/icons/_icon_status_created_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_failed.svg1
-rw-r--r--app/views/shared/icons/_icon_status_failed_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_manual.svg1
-rw-r--r--app/views/shared/icons/_icon_status_manual_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_open.svg1
-rw-r--r--app/views/shared/icons/_icon_status_pending.svg1
-rw-r--r--app/views/shared/icons/_icon_status_pending_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_running.svg1
-rw-r--r--app/views/shared/icons/_icon_status_running_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_scheduled.svg1
-rw-r--r--app/views/shared/icons/_icon_status_scheduled_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_skipped.svg1
-rw-r--r--app/views/shared/icons/_icon_status_skipped_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_status_success.svg1
-rw-r--r--app/views/shared/icons/_icon_status_warning.svg1
-rw-r--r--app/views/shared/icons/_icon_status_warning_borderless.svg1
-rw-r--r--app/views/shared/icons/_icon_stopwatch.svg1
-rw-r--r--app/views/shared/icons/_icon_tags.svg2
-rw-r--r--app/views/shared/icons/_icon_terminal.svg1
-rw-r--r--app/views/shared/icons/_icon_trash_o.svg1
-rw-r--r--app/views/shared/icons/_icon_user.svg1
-rw-r--r--app/views/shared/icons/_key.svg1
-rw-r--r--app/views/shared/icons/_labels.svg1
-rw-r--r--app/views/shared/icons/_lock.svg1
-rw-r--r--app/views/shared/icons/_members.svg1
-rw-r--r--app/views/shared/icons/_messages.svg1
-rw-r--r--app/views/shared/icons/_monitoring.svg1
-rw-r--r--app/views/shared/icons/_notifications.svg1
-rw-r--r--app/views/shared/icons/_overview.svg1
-rw-r--r--app/views/shared/icons/_pipeline.svg1
-rw-r--r--app/views/shared/icons/_plus_square.svg1
-rw-r--r--app/views/shared/icons/_preferences.svg1
-rw-r--r--app/views/shared/icons/_profile.svg1
-rw-r--r--app/views/shared/icons/_project.svg1
-rw-r--r--app/views/shared/icons/_scroll_down.svg5
-rw-r--r--app/views/shared/icons/_scroll_up.svg1
-rw-r--r--app/views/shared/icons/_service_templates.svg1
-rw-r--r--app/views/shared/icons/_settings.svg1
-rw-r--r--app/views/shared/icons/_snippets.svg1
-rw-r--r--app/views/shared/icons/_spam_logs.svg1
-rw-r--r--app/views/shared/icons/_system_hooks.svg1
-rw-r--r--app/views/shared/icons/_todo_done.svg1
-rw-r--r--app/views/shared/icons/_wiki.svg1
-rw-r--r--app/workers/click_house/event_paths_consistency_cron_worker.rb2
-rw-r--r--app/workers/projects/git_garbage_collect_worker.rb8
-rw-r--r--config/feature_flags/gitlab_com_derisk/determine_blank_ref_based_on_gitaly_object_format.yml (renamed from config/feature_flags/gitlab_com_derisk/reorder_garbage_collection_calls.yml)8
-rw-r--r--config/initializers/1_settings.rb3
-rw-r--r--config/initializers/7_prometheus_metrics.rb5
-rw-r--r--config/initializers/7_redis.rb2
-rw-r--r--config/metrics/counts_all/20240117153239_instances_beyond_identity_active.yml21
-rw-r--r--config/metrics/counts_all/20240117153516_groups_inheriting_beyond_identity_active.yml21
-rw-r--r--config/metrics/counts_all/20240117153519_groups_beyond_identity_active.yml21
-rw-r--r--config/metrics/counts_all/20240117153523_projects_inheriting_beyond_identity_active.yml21
-rw-r--r--config/metrics/counts_all/20240117153527_projects_beyond_identity_active.yml21
-rw-r--r--db/docs/integrations.yml1
-rw-r--r--doc/api/graphql/reference/index.md24
-rw-r--r--doc/development/documentation/styleguide/index.md4
-rw-r--r--doc/development/documentation/styleguide/word_list.md14
-rw-r--r--doc/install/index.md2
-rw-r--r--doc/user/project/integrations/beyond_identity.md35
-rw-r--r--lib/gitlab/beyond_identity/client.rb41
-rw-r--r--lib/gitlab/git.rb2
-rw-r--r--lib/gitlab/git/diff.rb4
-rw-r--r--lib/gitlab/git/repository.rb6
-rw-r--r--lib/gitlab/patch/database_config.rb9
-rw-r--r--lib/gitlab/redis/wrapper.rb9
-rw-r--r--locale/gitlab.pot32
-rw-r--r--package.json2
-rw-r--r--qa/Gemfile2
-rw-r--r--qa/Gemfile.lock6
-rw-r--r--qa/qa/page/organization/new.rb25
-rw-r--r--qa/qa/page/organization/show.rb18
-rw-r--r--qa/qa/page/sub_menus/create_new_menu.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/organization/create_organization_spec.rb37
-rw-r--r--rubocop/cop/migration/async_post_migrate_only.rb32
-rw-r--r--spec/controllers/groups/settings/integrations_controller_spec.rb8
-rw-r--r--spec/factories/integrations.rb7
-rw-r--r--spec/features/admin/integrations/instance_integrations_spec.rb6
-rw-r--r--spec/frontend/ci/catalog/components/list/catalog_tabs_spec.js8
-rw-r--r--spec/frontend/design_management/components/design_notes/design_note_spec.js27
-rw-r--r--spec/frontend/ml/model_registry/apps/index_ml_models_spec.js243
-rw-r--r--spec/frontend/ml/model_registry/components/model_row_spec.js33
-rw-r--r--spec/frontend/ml/model_registry/components/searchable_list_spec.js94
-rw-r--r--spec/frontend/ml/model_registry/graphql_mock_data.js61
-rw-r--r--spec/frontend/work_items/components/notes/work_item_note_spec.js19
-rw-r--r--spec/graphql/resolvers/ml/find_models_resolver_spec.rb20
-rw-r--r--spec/graphql/resolvers/ml/model_detail_resolver_spec.rb15
-rw-r--r--spec/helpers/avatars_helper_spec.rb1
-rw-r--r--spec/helpers/projects/ml/model_registry_helper_spec.rb37
-rw-r--r--spec/lib/gitlab/beyond_identity/client_spec.rb81
-rw-r--r--spec/lib/gitlab/git_spec.rb16
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/instrumentation/connection_pool_spec.rb4
-rw-r--r--spec/lib/gitlab/patch/database_config_spec.rb16
-rw-r--r--spec/models/integration_spec.rb41
-rw-r--r--spec/models/integrations/beyond_identity_spec.rb62
-rw-r--r--spec/models/project_spec.rb15
-rw-r--r--spec/models/repository_spec.rb77
-rw-r--r--spec/requests/api/integrations_spec.rb2
-rw-r--r--spec/requests/projects/ml/models_controller_spec.rb69
-rw-r--r--spec/rubocop/cop/migration/async_post_migrate_only_spec.rb56
-rw-r--r--spec/services/gpg_keys/create_service_spec.rb14
-rw-r--r--spec/services/gpg_keys/validate_integrations_service_spec.rb60
-rw-r--r--spec/support/shared_examples/redis/redis_shared_examples.rb11
-rw-r--r--spec/workers/click_house/event_paths_consistency_cron_worker_spec.rb8
-rw-r--r--spec/workers/projects/git_garbage_collect_worker_spec.rb18
-rw-r--r--yarn.lock8
208 files changed, 1860 insertions, 820 deletions
diff --git a/.rubocop.yml b/.rubocop.yml
index d776a79a80d..63eed0ce458 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -883,6 +883,12 @@ Migration/SchemaAdditionMethodsNoPost:
- db/post_migrate/*.rb
EnforcedSince: 20221024034228
+Migration/AsyncPostMigrateOnly:
+ Enabled: true
+ Include:
+ - db/**/*.rb
+ EnforcedSince: 20240115115029
+
Gitlab/RailsLogger:
Exclude:
- 'spec/**/*.rb'
diff --git a/Gemfile b/Gemfile
index 5df6c951fff..6dd8d6fe19d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -361,7 +361,7 @@ gem 'sentry-sidekiq', '~> 5.10.0', feature_category: :error_tracking
# PostgreSQL query parsing
#
-gem 'pg_query', '~> 4.2.3' # rubocop:todo Gemfile/MissingFeatureCategory
+gem 'pg_query', '~> 5.1.0', feature_category: :database
gem 'gitlab-schema-validation', path: 'gems/gitlab-schema-validation' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'gitlab-http', path: 'gems/gitlab-http' # rubocop:todo Gemfile/MissingFeatureCategory
diff --git a/Gemfile.checksum b/Gemfile.checksum
index d867f9ff2c9..2753440f1cd 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -454,7 +454,7 @@
{"name":"pastel","version":"0.8.0","platform":"ruby","checksum":"481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75"},
{"name":"peek","version":"1.1.0","platform":"ruby","checksum":"d6501ead8cde46d8d8ed0d59eb6f0ba713d0a41c11a2c4a81447b2dce37b3ecc"},
{"name":"pg","version":"1.5.4","platform":"ruby","checksum":"04f7b247151c639a0b955d8e5a9a41541343f4640aa3c2bdf749a872c339d25d"},
-{"name":"pg_query","version":"4.2.3","platform":"ruby","checksum":"1cc9955c7bce8e51e1abc11f1952e3d9d0f1cd4c16c58c56ec75d5aaf1cfd697"},
+{"name":"pg_query","version":"5.1.0","platform":"ruby","checksum":"b7f7f47c864f08ccbed46a8244906fb6ee77ee344fd27250717963928c93145d"},
{"name":"plist","version":"3.7.0","platform":"ruby","checksum":"703ca90a7cb00e8263edd03da2266627f6741d280c910abbbac07c95ffb2f073"},
{"name":"png_quantizator","version":"0.2.1","platform":"ruby","checksum":"6023d4d064125c3a7e02929c95b7320ed6ac0d7341f9e8de0c9ea6576ef3106b"},
{"name":"premailer","version":"1.16.0","platform":"ruby","checksum":"03e4402c448e6bae13fb5f6301a8bde4f3508e1bff90ae7c0972c7be94694786"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 4940a03d49e..eb876ae267d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1242,7 +1242,7 @@ GEM
peek (1.1.0)
railties (>= 4.0.0)
pg (1.5.4)
- pg_query (4.2.3)
+ pg_query (5.1.0)
google-protobuf (>= 3.22.3)
plist (3.7.0)
png_quantizator (0.2.1)
@@ -2024,7 +2024,7 @@ DEPENDENCIES
parslet (~> 1.8)
peek (~> 1.1)
pg (~> 1.5.4)
- pg_query (~> 4.2.3)
+ pg_query (~> 5.1.0)
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)
prometheus-client-mmap (~> 1.1)
diff --git a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
index b5cb1862b45..4f541eaa8bb 100644
--- a/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
+++ b/app/assets/javascripts/batch_comments/components/submit_dropdown.vue
@@ -208,7 +208,7 @@ export default {
@hidden="setDropdownVisible(false)"
>
<template #toggle>
- <gl-button variant="info" category="primary">
+ <gl-button variant="confirm" category="primary">
{{ __('Finish review') }}
<gl-icon class="dropdown-chevron" name="chevron-up" />
</gl-button>
diff --git a/app/assets/javascripts/ci/catalog/components/list/catalog_tabs.vue b/app/assets/javascripts/ci/catalog/components/list/catalog_tabs.vue
index f43255ab76b..47795106e05 100644
--- a/app/assets/javascripts/ci/catalog/components/list/catalog_tabs.vue
+++ b/app/assets/javascripts/ci/catalog/components/list/catalog_tabs.vue
@@ -30,9 +30,9 @@ export default {
count: this.resourceCounts.all,
},
{
- text: s__('CiCatalog|Your resources'),
+ text: s__('CiCatalog|Your groups'),
scope: SCOPE.namespaces,
- testId: 'resources-your-tab',
+ testId: 'resources-group-tab',
count: this.resourceCounts.namespaces,
},
];
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_note.vue b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
index b247f17fd97..022c5981d32 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_note.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_note.vue
@@ -8,6 +8,7 @@ import {
GlTooltipDirective,
} from '@gitlab/ui';
import { produce } from 'immer';
+import { isEmpty } from 'lodash';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import SafeHtml from '~/vue_shared/directives/safe_html';
import { getIdFromGraphQLId, convertToGraphQLId } from '~/graphql_shared/utils';
@@ -101,7 +102,10 @@ export default {
});
},
author() {
- return this.note.author;
+ return this.note.author || {};
+ },
+ hasAuthor() {
+ return !isEmpty(this.author);
},
authorId() {
return getIdFromGraphQLId(this.author.id);
@@ -274,6 +278,7 @@ export default {
<div class="gl-display-flex gl-justify-content-space-between">
<div>
<gl-link
+ v-if="hasAuthor"
v-once
:href="author.webUrl"
class="js-user-link link-inherit-color"
@@ -285,6 +290,7 @@ export default {
<span v-if="author.status_tooltip_html" v-safe-html="author.status_tooltip_html"></span>
<span class="note-headline-light">@{{ author.username }}</span>
</gl-link>
+ <span v-else>{{ __('A deleted user') }}</span>
<span class="note-headline-light note-headline-meta">
<span class="system-note-message"> <slot></slot> </span>
<gl-link
diff --git a/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue b/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue
index 59b68fc0063..7a04ccfe163 100644
--- a/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue
+++ b/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue
@@ -1,32 +1,29 @@
<script>
-import { isEmpty } from 'lodash';
-import { GlBadge, GlButton, GlTooltipDirective } from '@gitlab/ui';
-import Pagination from '~/vue_shared/components/incubation/pagination.vue';
+import { GlExperimentBadge, GlButton } from '@gitlab/ui';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import { helpPagePath } from '~/helpers/help_page_helper';
+import * as Sentry from '~/sentry/sentry_browser_wrapper';
import EmptyState from '../components/empty_state.vue';
import * as i18n from '../translations';
-import { BASE_SORT_FIELDS, MODEL_ENTITIES } from '../constants';
-import SearchBar from '../components/search_bar.vue';
+import { BASE_SORT_FIELDS, GRAPHQL_PAGE_SIZE, MODEL_ENTITIES } from '../constants';
import ModelRow from '../components/model_row.vue';
import ActionsDropdown from '../components/actions_dropdown.vue';
+import getModelsQuery from '../graphql/queries/get_models.query.graphql';
+import { makeLoadModelErrorMessage } from '../translations';
+import SearchableList from '../components/searchable_list.vue';
export default {
name: 'IndexMlModels',
components: {
- Pagination,
ModelRow,
- SearchBar,
MetadataItem,
TitleArea,
- GlBadge,
- EmptyState,
+ GlExperimentBadge,
GlButton,
+ EmptyState,
ActionsDropdown,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
+ SearchableList,
},
provide() {
return {
@@ -34,23 +31,14 @@ export default {
};
},
props: {
- models: {
- type: Array,
- required: true,
- },
- pageInfo: {
- type: Object,
+ projectPath: {
+ type: String,
required: true,
},
createModelPath: {
type: String,
required: true,
},
- modelCount: {
- type: Number,
- required: false,
- default: 0,
- },
canWriteModelRegistry: {
type: Boolean,
required: false,
@@ -62,9 +50,68 @@ export default {
default: '',
},
},
+ apollo: {
+ models: {
+ query: getModelsQuery,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data?.project?.mlModels ?? [];
+ },
+ error(error) {
+ this.handleError(error);
+ },
+ },
+ },
+ data() {
+ return {
+ models: [],
+ errorMessage: undefined,
+ };
+ },
computed: {
- hasModels() {
- return !isEmpty(this.models);
+ pageInfo() {
+ return this.models?.pageInfo ?? {};
+ },
+ items() {
+ return this.models?.nodes ?? [];
+ },
+ count() {
+ return this.models?.count ?? 0;
+ },
+ isLoading() {
+ return this.$apollo.queries.models.loading;
+ },
+ queryVariables() {
+ return {
+ fullPath: this.projectPath,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+ },
+ },
+ methods: {
+ fetchPage(variables) {
+ const vars = {
+ ...this.queryVariables,
+ ...variables,
+ name: variables.name,
+ orderBy: variables.orderBy?.toUpperCase() || 'CREATED_AT',
+ sort: variables.sort?.toUpperCase() || 'DESC',
+ };
+
+ this.$apollo.queries.models
+ .fetchMore({
+ variables: vars,
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ return fetchMoreResult;
+ },
+ })
+ .catch(this.handleError);
+ },
+ handleError(error) {
+ this.errorMessage = makeLoadModelErrorMessage(error.message);
+ Sentry.captureException(error);
},
},
i18n,
@@ -80,28 +127,39 @@ export default {
<template #title>
<div class="gl-flex-grow-1 gl-display-flex gl-align-items-center">
<span>{{ $options.i18n.TITLE_LABEL }}</span>
- <gl-badge variant="neutral" class="gl-mx-4" size="lg" :href="$options.docHref">
- {{ __('Experiment') }}
- </gl-badge>
+ <gl-experiment-badge :help-page-url="$options.docHref" />
</div>
</template>
<template #metadata-models-count>
- <metadata-item icon="machine-learning" :text="$options.i18n.modelsCountLabel(modelCount)" />
+ <metadata-item icon="machine-learning" :text="$options.i18n.modelsCountLabel(count)" />
</template>
<template #right-actions>
- <gl-button v-if="canWriteModelRegistry" :href="createModelPath">{{
- $options.i18n.CREATE_MODEL_LABEL
- }}</gl-button>
+ <gl-button
+ v-if="canWriteModelRegistry"
+ :href="createModelPath"
+ data-testid="create-model-button"
+ >{{ $options.i18n.CREATE_MODEL_LABEL }}</gl-button
+ >
<actions-dropdown />
</template>
</title-area>
- <template v-if="hasModels">
- <search-bar :sortable-fields="$options.sortableFields" />
- <model-row v-for="model in models" :key="model.name" :model="model" />
- <pagination v-bind="pageInfo" />
- </template>
+ <searchable-list
+ show-search
+ :page-info="pageInfo"
+ :items="items"
+ :error-message="errorMessage"
+ :is-loading="isLoading"
+ :sortable-fields="$options.sortableFields"
+ @fetch-page="fetchPage"
+ >
+ <template #empty-state>
+ <empty-state :entity-type="$options.modelEntity" />
+ </template>
- <empty-state v-else :entity-type="$options.modelEntity" />
+ <template #item="{ item }">
+ <model-row :model="item" />
+ </template>
+ </searchable-list>
</div>
</template>
diff --git a/app/assets/javascripts/ml/model_registry/components/candidate_list.vue b/app/assets/javascripts/ml/model_registry/components/candidate_list.vue
index fca4462d7d2..d05a827c545 100644
--- a/app/assets/javascripts/ml/model_registry/components/candidate_list.vue
+++ b/app/assets/javascripts/ml/model_registry/components/candidate_list.vue
@@ -35,8 +35,7 @@ export default {
return data.mlModel?.candidates ?? {};
},
error(error) {
- this.errorMessage = makeLoadCandidatesErrorMessage(error.message);
- Sentry.captureException(error);
+ this.handleError(error);
},
},
},
@@ -67,12 +66,18 @@ export default {
...newPageInfo,
};
- this.$apollo.queries.candidates.fetchMore({
- variables,
- updateQuery: (previousResult, { fetchMoreResult }) => {
- return fetchMoreResult;
- },
- });
+ this.$apollo.queries.candidates
+ .fetchMore({
+ variables,
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ return fetchMoreResult;
+ },
+ })
+ .catch(this.handleError);
+ },
+ handleError(error) {
+ this.errorMessage = makeLoadCandidatesErrorMessage(error.message);
+ Sentry.captureException(error);
},
},
i18n: {
diff --git a/app/assets/javascripts/ml/model_registry/components/model_row.vue b/app/assets/javascripts/ml/model_registry/components/model_row.vue
index 15be7bd0b47..49f72c7cef2 100644
--- a/app/assets/javascripts/ml/model_registry/components/model_row.vue
+++ b/app/assets/javascripts/ml/model_registry/components/model_row.vue
@@ -1,11 +1,14 @@
<script>
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlTruncate } from '@gitlab/ui';
import { s__, n__ } from '~/locale';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
export default {
name: 'MlModelRow',
components: {
GlLink,
+ ListItem,
+ GlTruncate,
},
props: {
model: {
@@ -15,7 +18,7 @@ export default {
},
computed: {
hasVersions() {
- return this.model.version != null;
+ return this.model.versionCount > 0;
},
modelVersionCountMessage() {
if (!this.model.versionCount) return s__('MlModelRegistry|No registered versions');
@@ -31,15 +34,23 @@ export default {
</script>
<template>
- <div class="gl-border-b-solid gl-border-b-1 gl-border-b-gray-100 gl-py-3">
- <gl-link :href="model.path" class="gl-text-body gl-font-weight-bold gl-line-height-24">
- {{ model.name }}
- </gl-link>
+ <list-item v-bind="$attrs">
+ <template #left-primary>
+ <div class="gl-display-flex gl-align-items-center">
+ <gl-link class="gl-text-body" :href="model._links.showPath">
+ <gl-truncate :text="model.name" />
+ </gl-link>
+ </div>
+ </template>
- <div class="gl-text-secondary">
- <gl-link v-if="hasVersions" :href="model.versionPath">{{ model.version }}</gl-link>
+ <template #left-secondary>
+ <div class="gl-text-secondary">
+ <gl-link v-if="hasVersions" :href="model.latestVersion._links.showPath">{{
+ model.latestVersion.version
+ }}</gl-link>
- {{ modelVersionCountMessage }}
- </div>
- </div>
+ {{ modelVersionCountMessage }}
+ </div>
+ </template>
+ </list-item>
</template>
diff --git a/app/assets/javascripts/ml/model_registry/components/model_version_list.vue b/app/assets/javascripts/ml/model_registry/components/model_version_list.vue
index 5a649a9596a..ea5258a299e 100644
--- a/app/assets/javascripts/ml/model_registry/components/model_version_list.vue
+++ b/app/assets/javascripts/ml/model_registry/components/model_version_list.vue
@@ -36,8 +36,7 @@ export default {
return data.mlModel?.versions ?? {};
},
error(error) {
- this.errorMessage = makeLoadVersionsErrorMessage(error.message);
- Sentry.captureException(error);
+ this.handleError(error);
},
},
},
@@ -68,12 +67,18 @@ export default {
...pageInfo,
};
- this.$apollo.queries.modelVersions.fetchMore({
- variables,
- updateQuery: (previousResult, { fetchMoreResult }) => {
- return fetchMoreResult;
- },
- });
+ this.$apollo.queries.modelVersions
+ .fetchMore({
+ variables,
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ return fetchMoreResult;
+ },
+ })
+ .catch(this.handleError);
+ },
+ handleError(error) {
+ this.errorMessage = makeLoadVersionsErrorMessage(error.message);
+ Sentry.captureException(error);
},
},
modelVersionEntity: MODEL_ENTITIES.modelVersion,
diff --git a/app/assets/javascripts/ml/model_registry/components/searchable_list.vue b/app/assets/javascripts/ml/model_registry/components/searchable_list.vue
index 05062ae6fbf..1ff8cc578a1 100644
--- a/app/assets/javascripts/ml/model_registry/components/searchable_list.vue
+++ b/app/assets/javascripts/ml/model_registry/components/searchable_list.vue
@@ -2,11 +2,14 @@
import { GlAlert } from '@gitlab/ui';
import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
-import { GRAPHQL_PAGE_SIZE } from '~/ml/model_registry/constants';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import { GRAPHQL_PAGE_SIZE, LIST_KEY_CREATED_AT } from '~/ml/model_registry/constants';
+import { queryToObject, setUrlParams, updateHistory } from '~/lib/utils/url_utility';
+import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
export default {
name: 'SearchableList',
- components: { PackagesListLoader, RegistryList, GlAlert },
+ components: { PackagesListLoader, RegistryList, RegistrySearch, GlAlert },
props: {
items: {
type: Array,
@@ -26,30 +29,92 @@ export default {
required: false,
default: '',
},
+ showSearch: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ sortableFields: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
+ data() {
+ const query = queryToObject(window.location.search);
+
+ const filter = query.name ? [{ value: { data: query.name }, type: FILTERED_SEARCH_TERM }] : [];
+
+ const orderBy = query.orderBy || LIST_KEY_CREATED_AT;
+
+ return {
+ filters: filter,
+ sorting: {
+ orderBy,
+ sort: (query.sort || 'desc').toLowerCase(),
+ },
+ };
},
computed: {
isListEmpty() {
return this.items.length === 0;
},
+ parsedQuery() {
+ const name = this.filters
+ .map((f) => f.value.data)
+ .join(' ')
+ .trim();
+
+ const filterByQuery = name === '' ? {} : { name };
+
+ return { ...filterByQuery, ...this.sorting };
+ },
+ },
+ created() {
+ this.nextPage();
},
methods: {
prevPage() {
- const pageInfo = {
+ const variables = {
first: null,
last: GRAPHQL_PAGE_SIZE,
before: this.pageInfo.startCursor,
+ ...this.parsedQuery,
};
- this.$emit('fetch-page', pageInfo);
+ this.fetchPage(variables);
},
nextPage() {
- const pageInfo = {
+ const variables = {
first: GRAPHQL_PAGE_SIZE,
last: null,
after: this.pageInfo.endCursor,
+ ...this.parsedQuery,
};
- this.$emit('fetch-page', pageInfo);
+ this.fetchPage(variables);
+ },
+ fetchPage(variables) {
+ updateHistory({
+ url: setUrlParams(variables, window.location.href, true),
+ title: document.title,
+ replace: true,
+ });
+
+ this.$emit('fetch-page', variables);
+ },
+ submitFilters() {
+ this.fetchPage(this.parsedQuery);
+ },
+ updateFilters(newValue) {
+ this.filters = newValue;
+ },
+ updateSorting(newValue) {
+ this.sorting = { ...this.sorting, ...newValue };
+ },
+ updateSortingAndEmitUpdate(newValue) {
+ this.updateSorting(newValue);
+ this.submitFilters();
},
},
};
@@ -57,6 +122,16 @@ export default {
<template>
<div>
+ <registry-search
+ v-if="showSearch"
+ :filters="filters"
+ :sorting="sorting"
+ :sortable-fields="sortableFields"
+ @sorting:changed="updateSortingAndEmitUpdate"
+ @filter:changed="updateFilters"
+ @filter:submit="submitFilters"
+ @filter:clear="filters = []"
+ />
<packages-list-loader v-if="isLoading" />
<gl-alert v-else-if="errorMessage" variant="danger" :dismissible="false">
{{ errorMessage }}
diff --git a/app/assets/javascripts/ml/model_registry/graphql/queries/get_models.query.graphql b/app/assets/javascripts/ml/model_registry/graphql/queries/get_models.query.graphql
new file mode 100644
index 00000000000..a9559bd7f5d
--- /dev/null
+++ b/app/assets/javascripts/ml/model_registry/graphql/queries/get_models.query.graphql
@@ -0,0 +1,46 @@
+#import "~/graphql_shared/fragments/page_info.fragment.graphql"
+
+query getModels(
+ $fullPath: ID!
+ $name: String
+ $orderBy: MlModelsOrderBy
+ $sort: SortDirectionEnum
+ $first: Int
+ $last: Int
+ $after: String
+ $before: String
+) {
+ project(fullPath: $fullPath) {
+ id
+ mlModels(
+ name: $name
+ orderBy: $orderBy
+ sort: $sort
+ after: $after
+ before: $before
+ first: $first
+ last: $last
+ ) {
+ count
+ nodes {
+ id
+ name
+ versionCount
+ createdAt
+ latestVersion {
+ id
+ version
+ _links {
+ showPath
+ }
+ }
+ _links {
+ showPath
+ }
+ }
+ pageInfo {
+ ...PageInfo
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/ml/model_registry/translations.js b/app/assets/javascripts/ml/model_registry/translations.js
index 006142979e2..9d3e1e7badb 100644
--- a/app/assets/javascripts/ml/model_registry/translations.js
+++ b/app/assets/javascripts/ml/model_registry/translations.js
@@ -47,6 +47,11 @@ export const makeLoadVersionsErrorMessage = (message) =>
message,
});
+export const makeLoadModelErrorMessage = (message) =>
+ sprintf(s__('MlModelRegistry|Failed to load model with error: %{message}'), {
+ message,
+ });
+
export const NO_CANDIDATES_LABEL = s__('MlModelRegistry|This model has no candidates');
export const makeLoadCandidatesErrorMessage = (message) =>
sprintf(s__('MlModelRegistry|Failed to load model candidates with error: %{message}'), {
diff --git a/app/assets/javascripts/organizations/shared/components/new_edit_form.vue b/app/assets/javascripts/organizations/shared/components/new_edit_form.vue
index 49519369e9a..46808eefa4e 100644
--- a/app/assets/javascripts/organizations/shared/components/new_edit_form.vue
+++ b/app/assets/javascripts/organizations/shared/components/new_edit_form.vue
@@ -103,6 +103,7 @@ export default {
inputAttrs: {
class: !this.fieldsToRender.includes(FORM_FIELD_ID) ? 'gl-md-form-input-lg' : null,
placeholder: s__('Organization|My organization'),
+ 'data-testid': 'organization-name',
},
},
[FORM_FIELD_ID]: {
diff --git a/app/assets/javascripts/organizations/show/components/organization_avatar.vue b/app/assets/javascripts/organizations/show/components/organization_avatar.vue
index d569af3e9b4..f24eea76d3d 100644
--- a/app/assets/javascripts/organizations/show/components/organization_avatar.vue
+++ b/app/assets/javascripts/organizations/show/components/organization_avatar.vue
@@ -48,7 +48,9 @@ export default {
/>
<div class="gl-ml-3">
<div class="gl-display-flex gl-align-items-center">
- <h1 class="gl-m-0 gl-font-size-h1">{{ organization.name }}</h1>
+ <h1 class="gl-m-0 gl-font-size-h1" data-testid="organization-name">
+ {{ organization.name }}
+ </h1>
<gl-icon
v-gl-tooltip="visibilityTooltip"
:name="visibilityIcon"
diff --git a/app/assets/javascripts/work_items/components/notes/work_item_note.vue b/app/assets/javascripts/work_items/components/notes/work_item_note.vue
index 11aecc65803..077b2075d88 100644
--- a/app/assets/javascripts/work_items/components/notes/work_item_note.vue
+++ b/app/assets/javascripts/work_items/components/notes/work_item_note.vue
@@ -1,4 +1,5 @@
<script>
+import { isEmpty } from 'lodash';
import { GlAvatarLink, GlAvatar } from '@gitlab/ui';
import * as Sentry from '~/sentry/sentry_browser_wrapper';
import toast from '~/vue_shared/plugins/global_toast';
@@ -108,7 +109,10 @@ export default {
};
},
author() {
- return this.note.author;
+ return this.note.author || {};
+ },
+ hasAuthor() {
+ return !isEmpty(this.author);
},
authorId() {
return getIdFromGraphQLId(this.author.id);
@@ -352,7 +356,7 @@ export default {
:show-edit="hasAdminPermission"
:note-id="note.id"
:is-author-an-assignee="isAuthorAnAssignee"
- :show-assign-unassign="canSetWorkItemMetadata"
+ :show-assign-unassign="canSetWorkItemMetadata && hasAuthor"
:can-report-abuse="!isCurrentUserAuthorOfNote"
:is-work-item-author="isWorkItemAuthor"
:work-item-type="workItemType"
diff --git a/app/components/pajamas/avatar_component.rb b/app/components/pajamas/avatar_component.rb
index 0821818103a..6baa085e3b4 100644
--- a/app/components/pajamas/avatar_component.rb
+++ b/app/components/pajamas/avatar_component.rb
@@ -29,6 +29,7 @@ module Pajamas
def avatar_classes
classes = ["gl-avatar", "gl-avatar-s#{@size}", @class]
classes.push("gl-avatar-circle") if @item.is_a?(User) || @item.is_a?(AvatarEmail)
+ classes.push("gl-rounded-base!") if @item.is_a?(Project) || @item.is_a?(Group)
unless src
classes.push("gl-avatar-identicon")
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index cd099173718..7bd1ce56669 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -53,7 +53,9 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def integrations
return not_found unless instance_level_integrations?
- @integrations = Integration.find_or_initialize_all_non_project_specific(Integration.for_instance).sort_by(&:title)
+ @integrations = Integration.find_or_initialize_all_non_project_specific(
+ Integration.for_instance, include_instance_specific: true
+ ).sort_by(&:title)
end
def update
diff --git a/app/controllers/projects/ml/models_controller.rb b/app/controllers/projects/ml/models_controller.rb
index 2dff3ec3325..1c5d773bc7d 100644
--- a/app/controllers/projects/ml/models_controller.rb
+++ b/app/controllers/projects/ml/models_controller.rb
@@ -10,17 +10,7 @@ module Projects
MAX_MODELS_PER_PAGE = 20
- def index
- find_params = params
- .transform_keys(&:underscore)
- .permit(:name, :order_by, :sort)
-
- finder = ::Projects::Ml::ModelFinder.new(@project, find_params)
-
- @paginator = finder.execute.keyset_paginate(cursor: params[:cursor], per_page: MAX_MODELS_PER_PAGE)
-
- @model_count = finder.count
- end
+ def index; end
def new; end
diff --git a/app/graphql/resolvers/ml/find_models_resolver.rb b/app/graphql/resolvers/ml/find_models_resolver.rb
index b9901100e22..3816b17f3a0 100644
--- a/app/graphql/resolvers/ml/find_models_resolver.rb
+++ b/app/graphql/resolvers/ml/find_models_resolver.rb
@@ -20,7 +20,7 @@ module Resolvers
description: 'Ordering column. Default is desc.'
def resolve(**args)
- return unless current_user.can?(:read_model_registry, object)
+ return unless Ability.allowed?(current_user, :read_model_registry, object)
find_params = {
name: args[:name],
diff --git a/app/graphql/resolvers/ml/model_detail_resolver.rb b/app/graphql/resolvers/ml/model_detail_resolver.rb
index 01c025c1d8a..7a5fe7821ea 100644
--- a/app/graphql/resolvers/ml/model_detail_resolver.rb
+++ b/app/graphql/resolvers/ml/model_detail_resolver.rb
@@ -13,7 +13,7 @@ module Resolvers
def resolve(id:)
Gitlab::Graphql::Lazy.with_value(find_object(id: id)) do |ml_model|
- ml_model if current_user.can?(:read_model_registry, ml_model&.project)
+ ml_model if Ability.allowed?(current_user, :read_model_registry, ml_model&.project)
end
end
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index 65244235e10..c84864dcb9f 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -31,7 +31,8 @@ module Types
end
field :before_sha, GraphQL::Types::String, null: true,
- description: 'Base SHA of the source branch.'
+ description: 'Base SHA of the source branch.',
+ calls_gitaly: true
field :complete, GraphQL::Types::Boolean, null: false, method: :complete?,
description: 'Indicates if a pipeline is complete.'
diff --git a/app/graphql/types/projects/service_type_enum.rb b/app/graphql/types/projects/service_type_enum.rb
index fd88fa957e7..7a8863c7d67 100644
--- a/app/graphql/types/projects/service_type_enum.rb
+++ b/app/graphql/types/projects/service_type_enum.rb
@@ -17,7 +17,7 @@ module Types
# This prepend must stay here because the dynamic block below depends on it.
prepend_mod # rubocop: disable Cop/InjectEnterpriseEditionModule
- ::Integration.available_integration_names(include_dev: false).each do |name|
+ ::Integration.available_integration_names(include_instance_specific: false, include_dev: false).each do |name|
type = "#{name.camelize}Service"
domain_value = Integration.integration_name_to_type(name)
value type.underscore.upcase, value: domain_value, description: type_description(name, type)
diff --git a/app/helpers/projects/ml/model_registry_helper.rb b/app/helpers/projects/ml/model_registry_helper.rb
new file mode 100644
index 00000000000..828ae088b1b
--- /dev/null
+++ b/app/helpers/projects/ml/model_registry_helper.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Projects
+ module Ml
+ module ModelRegistryHelper
+ require 'json'
+
+ def index_ml_model_data(project, user)
+ data = {
+ projectPath: project.full_path,
+ create_model_path: new_project_ml_model_path(project),
+ can_write_model_registry: user&.can?(:write_model_registry, project),
+ mlflow_tracking_url: mlflow_tracking_url(project)
+ }
+
+ Gitlab::Json.generate(data.deep_transform_keys { |k| k.to_s.camelize(:lower) })
+ end
+
+ private
+
+ def mlflow_tracking_url(project)
+ path = api_v4_projects_ml_mlflow_api_2_0_mlflow_registered_models_create_path(id: project.id)
+
+ path = path.delete_suffix('registered-models/create')
+
+ expose_url(path)
+ end
+ end
+ end
+end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 1bf4d585e1c..a3520df68d5 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -620,7 +620,7 @@ module Ci
end
def valid_commit_sha
- if self.sha == Gitlab::Git::SHA1_BLANK_SHA
+ if Gitlab::Git.blank_ref?(self.sha)
self.errors.add(:sha, " cant be 00000000 (branch removal)")
end
end
@@ -674,7 +674,7 @@ module Ci
end
def before_sha
- super || Gitlab::Git::SHA1_BLANK_SHA
+ super || project.repository.blank_ref
end
def short_sha
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 9c8d7604031..312b1b3f70f 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -359,7 +359,7 @@ class Commit
def diff_refs
Gitlab::Diff::DiffRefs.new(
- base_sha: self.parent_id || Gitlab::Git::SHA1_BLANK_SHA,
+ base_sha: self.parent_id || container.repository.blank_ref,
head_sha: self.sha
)
end
diff --git a/app/models/integration.rb b/app/models/integration.rb
index 8ebf24b1663..aa02db949bf 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -26,6 +26,10 @@ class Integration < ApplicationRecord
unify_circuit webex_teams youtrack zentao
].freeze
+ INSTANCE_SPECIFIC_INTEGRATION_NAMES = %w[
+ beyond_identity
+ ].freeze
+
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/345677
PROJECT_SPECIFIC_INTEGRATION_NAMES = %w[
apple_app_store gitlab_slack_application google_play jenkins
@@ -124,9 +128,14 @@ class Integration < ApplicationRecord
scope :with_default_settings, -> { where.not(inherit_from_id: nil) }
scope :with_custom_settings, -> { where(inherit_from_id: nil) }
scope :for_group, ->(group) {
- where(group_id: group, type: available_integration_types(include_project_specific: false))
- }
- scope :for_instance, -> { where(instance: true, type: available_integration_types(include_project_specific: false)) }
+ types = available_integration_types(include_project_specific: false, include_instance_specific: false)
+ where(group_id: group, type: types)
+ }
+
+ scope :for_instance, -> {
+ types = available_integration_types(include_project_specific: false, include_instance_specific: true)
+ where(instance: true, type: types)
+ }
scope :push_hooks, -> { where(push_events: true, active: true) }
scope :tag_push_hooks, -> { where(tag_push_events: true, active: true) }
@@ -270,17 +279,18 @@ class Integration < ApplicationRecord
end
def self.find_or_initialize_non_project_specific_integration(name, instance: false, group_id: nil)
- return unless name.in?(available_integration_names(include_project_specific: false))
+ return unless name.in?(available_integration_names(include_project_specific: false,
+ include_instance_specific: instance))
integration_name_to_model(name).find_or_initialize_by(instance: instance, group_id: group_id)
end
- def self.find_or_initialize_all_non_project_specific(scope)
- scope + build_nonexistent_integrations_for(scope)
+ def self.find_or_initialize_all_non_project_specific(scope, include_instance_specific: false)
+ scope + build_nonexistent_integrations_for(scope, include_instance_specific: include_instance_specific)
end
- def self.build_nonexistent_integrations_for(scope)
- nonexistent_integration_types_for(scope).map do |type|
+ def self.build_nonexistent_integrations_for(...)
+ nonexistent_integration_types_for(...).map do |type|
integration_type_to_model(type).new
end
end
@@ -288,19 +298,25 @@ class Integration < ApplicationRecord
# Returns a list of integration types that do not exist in the given scope.
# Example: ["AsanaService", ...]
- def self.nonexistent_integration_types_for(scope)
+ def self.nonexistent_integration_types_for(scope, include_instance_specific: false)
# Using #map instead of #pluck to save one query count. This is because
# ActiveRecord loaded the object here, so we don't need to query again later.
- available_integration_types(include_project_specific: false) - scope.map(&:type)
+ available_integration_types(
+ include_project_specific: false,
+ include_instance_specific: include_instance_specific
+ ) - scope.map(&:type)
end
private_class_method :nonexistent_integration_types_for
# Returns a list of available integration names.
# Example: ["asana", ...]
- def self.available_integration_names(include_project_specific: true, include_dev: true)
+ def self.available_integration_names(
+ include_project_specific: true, include_dev: true, include_instance_specific: true
+ )
names = integration_names
names += project_specific_integration_names if include_project_specific
names += dev_integration_names if include_dev
+ names += instance_specific_integration_names if include_instance_specific
names.sort_by(&:downcase)
end
@@ -309,6 +325,10 @@ class Integration < ApplicationRecord
INTEGRATION_NAMES
end
+ def self.instance_specific_integration_names
+ INSTANCE_SPECIFIC_INTEGRATION_NAMES
+ end
+
def self.dev_integration_names
return [] unless Gitlab.dev_or_test_env?
@@ -323,8 +343,8 @@ class Integration < ApplicationRecord
# Returns a list of available integration types.
# Example: ["Integrations::Asana", ...]
- def self.available_integration_types(include_project_specific: true, include_dev: true)
- available_integration_names(include_project_specific: include_project_specific, include_dev: include_dev).map do
+ def self.available_integration_types(...)
+ available_integration_names(...).map do
integration_name_to_type(_1)
end
end
diff --git a/app/models/integrations/beyond_identity.rb b/app/models/integrations/beyond_identity.rb
new file mode 100644
index 00000000000..b170c50d0da
--- /dev/null
+++ b/app/models/integrations/beyond_identity.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Integrations
+ class BeyondIdentity < Integration
+ validates :token, presence: true, if: :activated?
+
+ field :token,
+ type: :password,
+ title: 'API token',
+ help: -> {
+ s_('BeyondIdentityService|API Token. User must have access to `git-commit-signing` endpoint.')
+ },
+ non_empty_password_title: -> { s_('ProjectService|Enter new API token') },
+ non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API token.') },
+ description: -> {
+ s_('BeyondIdentityService|API Token. User must have access to `git-commit-signing` endpoint.')
+ },
+ required: true
+
+ def self.title
+ 'Beyond Identity'
+ end
+
+ def self.description
+ s_('BeyondIdentity|Verify that GPG keys are authorized by Beyond Identity Authenticator.')
+ end
+
+ def self.help
+ docs_link = ActionController::Base.helpers.link_to(
+ _('Learn more'),
+ Rails.application.routes.url_helpers.help_page_url('user/project/integrations/beyond_identity'),
+ target: '_blank', rel: 'noopener noreferrer')
+
+ format(_('Verify that GPG keys are authorized by Beyond Identity Authenticator. %{docs_link}').html_safe, # rubocop:disable Rails/OutputSafety -- It is fine to call html_safe here
+ docs_link: docs_link.html_safe) # rubocop:disable Rails/OutputSafety -- It is fine to call html_safe here
+ end
+
+ def self.to_param
+ 'beyond_identity'
+ end
+
+ def self.supported_events
+ %w[]
+ end
+
+ def inheritable?
+ false
+ end
+
+ def execute(params)
+ ::Gitlab::BeyondIdentity::Client.new(self).execute(params)
+ end
+ end
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 8ad463f1511..f541e0003cb 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -200,6 +200,7 @@ class Project < ApplicationRecord
has_one :asana_integration, class_name: 'Integrations::Asana'
has_one :assembla_integration, class_name: 'Integrations::Assembla'
has_one :bamboo_integration, class_name: 'Integrations::Bamboo'
+ has_one :beyond_identity_integration, class_name: 'Integrations::BeyondIdentity'
has_one :bugzilla_integration, class_name: 'Integrations::Bugzilla'
has_one :buildkite_integration, class_name: 'Integrations::Buildkite'
has_one :campfire_integration, class_name: 'Integrations::Campfire'
@@ -1725,7 +1726,7 @@ class Project < ApplicationRecord
def find_or_initialize_integrations
Integration
- .available_integration_names
+ .available_integration_names(include_instance_specific: false)
.difference(disabled_integrations)
.map { find_or_initialize_integration(_1) }
.sort_by(&:title)
@@ -1742,7 +1743,8 @@ class Project < ApplicationRecord
end
def find_or_initialize_integration(name)
- return if disabled_integrations.include?(name) || Integration.available_integration_names.exclude?(name)
+ return if disabled_integrations.include?(name)
+ return if Integration.available_integration_names(include_instance_specific: false).exclude?(name)
find_integration(integrations, name) || build_from_instance(name) || build_integration(name)
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 5ab35ed1ef9..b9918e35fed 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1281,11 +1281,27 @@ class Repository
def object_format
return unless exists?
- case raw.object_format
- when :OBJECT_FORMAT_SHA1
- FORMAT_SHA1
- when :OBJECT_FORMAT_SHA256
- FORMAT_SHA256
+ cache_key = "object_format:#{full_path}"
+
+ request_store_cache.fetch(cache_key) do
+ case raw.object_format
+ when :OBJECT_FORMAT_SHA1
+ FORMAT_SHA1
+ when :OBJECT_FORMAT_SHA256
+ FORMAT_SHA256
+ end
+ end
+ end
+
+ def blank_ref
+ return Gitlab::Git::SHA1_BLANK_SHA unless exists? &&
+ Feature.enabled?(:determine_blank_ref_based_on_gitaly_object_format, project, type: :gitlab_com_derisk)
+
+ case object_format
+ when FORMAT_SHA1
+ Gitlab::Git::SHA1_BLANK_SHA
+ when FORMAT_SHA256
+ Gitlab::Git::SHA256_BLANK_SHA
end
end
diff --git a/app/services/ci/create_web_ide_terminal_service.rb b/app/services/ci/create_web_ide_terminal_service.rb
index ce4400e9f4f..9cfba0cbee6 100644
--- a/app/services/ci/create_web_ide_terminal_service.rb
+++ b/app/services/ci/create_web_ide_terminal_service.rb
@@ -52,7 +52,7 @@ module Ci
ref: ref,
sha: sha,
tag: false,
- before_sha: Gitlab::Git::SHA1_BLANK_SHA
+ before_sha: project.repository.blank_ref
)
end
diff --git a/app/services/gpg_keys/create_service.rb b/app/services/gpg_keys/create_service.rb
index ab8b12732d7..c061c92df3e 100644
--- a/app/services/gpg_keys/create_service.rb
+++ b/app/services/gpg_keys/create_service.rb
@@ -3,15 +3,25 @@
module GpgKeys
class CreateService < Keys::BaseService
def execute
- key = create(params)
+ key = user.gpg_keys.build(params)
+
+ return key unless validate(key)
+
+ create(key)
+
notification_service.new_gpg_key(key) if key.persisted?
key
end
private
- def create(params)
- user.gpg_keys.create(params)
+ def validate(key)
+ GpgKeys::ValidateIntegrationsService.new(key).execute
+ end
+
+ def create(key)
+ key.save
+ key
end
end
end
diff --git a/app/services/gpg_keys/validate_integrations_service.rb b/app/services/gpg_keys/validate_integrations_service.rb
new file mode 100644
index 00000000000..f593eb6925a
--- /dev/null
+++ b/app/services/gpg_keys/validate_integrations_service.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module GpgKeys
+ class ValidateIntegrationsService < Keys::BaseService
+ ValidationError = Class.new(StandardError)
+
+ def initialize(key)
+ @key = key
+ end
+
+ def execute
+ return false unless key.valid?
+
+ validate_beyond_identity!
+
+ key.errors.empty?
+ end
+
+ private
+
+ attr_reader :key
+
+ def validate_beyond_identity!
+ integration = Integrations::BeyondIdentity.for_instance.first
+
+ return unless integration&.activated?
+
+ integration.execute({ key_id: key.primary_keyid, committer_email: key.user.email })
+ rescue ::Gitlab::BeyondIdentity::Client::Error => e
+ key.errors.add(:base, "BeyondIdentity: #{e.message}")
+ end
+ end
+end
diff --git a/app/views/projects/ml/models/index.html.haml b/app/views/projects/ml/models/index.html.haml
index ba695bce435..1e6a268ed5c 100644
--- a/app/views/projects/ml/models/index.html.haml
+++ b/app/views/projects/ml/models/index.html.haml
@@ -1,4 +1,4 @@
- breadcrumb_title s_('ModelRegistry|Model registry')
- page_title s_('ModelRegistry|Model registry')
-= render(Projects::Ml::ModelsIndexComponent.new(project: @project, current_user: current_user, paginator: @paginator, model_count: @model_count))
+#js-index-ml-models{ data: { view_model: index_ml_model_data(@project, @current_user) } }
diff --git a/app/views/shared/icons/_abuse_reports.svg b/app/views/shared/icons/_abuse_reports.svg
deleted file mode 100644
index fb16b269150..00000000000
--- a/app/views/shared/icons/_abuse_reports.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-2.163-3.275a2.499 2.499 0 0 1 4.343.03.5.5 0 0 1-.871.49 1.5 1.5 0 0 0-2.607-.018.5.5 0 1 1-.865-.502zM5 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
diff --git a/app/views/shared/icons/_access_tokens.svg b/app/views/shared/icons/_access_tokens.svg
deleted file mode 100644
index 07ea6dab715..00000000000
--- a/app/views/shared/icons/_access_tokens.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="m13 2h-10c-1.7 0-3 1.3-3 3v6c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-6c0-1.7-1.3-3-3-3m1 9c0 .6-.4 1-1 1h-10c-.6 0-1-.4-1-1v-6c0-.6.4-1 1-1h10c.6 0 1 .4 1 1v6"/><circle cx="4" cy="8" r="1"/><circle cx="8" cy="8" r="1"/><circle cx="12" cy="8" r="1"/></svg>
diff --git a/app/views/shared/icons/_account.svg b/app/views/shared/icons/_account.svg
deleted file mode 100644
index d47e4f59914..00000000000
--- a/app/views/shared/icons/_account.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="m6.8 8c-.3 0-.5 0-.8 0-5 0-6 2.7-6 4.5s.1 2.5 6 2.5c.6 0 1.1 0 1.5 0-1-1.1-1.5-2.5-1.5-4 0-1.1.3-2.1.8-3"/><circle cx="6" cy="4" r="3"/><path d="m15.9 11.5l-.9-.6c0-.3-.1-.7-.2-.9l.6-.9c.1-.1.1-.2 0-.3l-.4-.5c-.1-.1-.2-.1-.3-.1l-.9.4c-.3-.2-.5-.3-.9-.4l-.3-1c0-.1-.1-.2-.2-.2h-.6c-.1 0-.2.1-.2.2l-.3 1c-.3.1-.6.2-.9.4l-1.1-.4c-.1 0-.2 0-.3.1l-.4.5c0 .1 0 .2 0 .3l.6.9c-.1.3-.2.6-.2.9l-.9.5c-.1.1-.1.2-.1.3l.1.6c0 .1.1.2.2.2l1.1.1c.1.2.3.4.5.6l-.2 1.2c0 .1 0 .2.1.3l.6.3c.1 0 .2 0 .3-.1l.9-.9c.2 0 .4 0 .6 0l.9.9c.1.1.2.1.3 0l.6-.3c.1 0 .2-.2.1-.3l-.1-1.1c.2-.2.4-.4.5-.6l1.1-.1c.1 0 .2-.1.2-.2l.1-.6c.1-.1.1-.2 0-.2m-3.9.5c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1"/></svg>
diff --git a/app/views/shared/icons/_appearance.svg b/app/views/shared/icons/_appearance.svg
deleted file mode 100644
index 8ffeb780cb4..00000000000
--- a/app/views/shared/icons/_appearance.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M11.161 12.456l.232.121c.1.053.175.094.249.137.53.318.844.75.857 1.402.012 1.397-1.116 1.756-3.12 1.858-.411.022-.744.026-1.38.026A8 8 0 0 1 0 8a8 8 0 0 1 8-8c4.417 0 7.998 3.582 7.998 7.977.06 2.621-1.312 3.586-4.48 3.648-.602.008-1.068.043-1.4.104.228.192.598.47 1.043.727zm-3.287-.943c-.019-1.495 1.228-1.856 3.611-1.888C13.67 9.582 14.028 9.33 13.998 8A6 6 0 1 0 8 14c.603 0 .91-.004 1.277-.023.172-.009.332-.02.478-.035-1.172-.738-1.868-1.47-1.88-2.43zM6 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm6 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm-2-3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zM4 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
diff --git a/app/views/shared/icons/_applications.svg b/app/views/shared/icons/_applications.svg
deleted file mode 100644
index 65442867174..00000000000
--- a/app/views/shared/icons/_applications.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M1 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 1v2h2V1H7zm0 5h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm6-6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1zm0 6h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zm0 1v2h2V7h-2zM1 12h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm0 1v2h2v-2H1zm6-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zm6 0h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/></svg>
diff --git a/app/views/shared/icons/_authentication_log.svg b/app/views/shared/icons/_authentication_log.svg
deleted file mode 100644
index 0beb84c2912..00000000000
--- a/app/views/shared/icons/_authentication_log.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4zm1 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm0 3a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-5h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm0 3h3a1 1 0 0 1 0 2H8a1 1 0 1 1 0-2zm-3 5a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3-2h3a1 1 0 0 1 0 2H8a1 1 0 0 1 0-2z"/></svg>
diff --git a/app/views/shared/icons/_chat.svg b/app/views/shared/icons/_chat.svg
deleted file mode 100644
index 0c474c9f980..00000000000
--- a/app/views/shared/icons/_chat.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M5.414 12l-3.707 3.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586z"/></svg>
diff --git a/app/views/shared/icons/_collapse.svg.erb b/app/views/shared/icons/_collapse.svg.erb
deleted file mode 100644
index 917753fb343..00000000000
--- a/app/views/shared/icons/_collapse.svg.erb
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="<%= size %>" height="<%= size %>" viewBox="0 0 9 13"><path d="M2.57568253,6.49866948 C2.50548852,6.57199715 2.44637866,6.59708255 2.39835118,6.57392645 C2.3503237,6.55077034 2.32631032,6.48902165 2.32631032,6.38867852 L2.32631032,-2.13272614 C2.32631032,-2.23306927 2.3503237,-2.29481796 2.39835118,-2.31797406 C2.44637866,-2.34113017 2.50548852,-2.31604477 2.57568253,-2.24271709 L6.51022184,1.86747129 C6.53977721,1.8983461 6.56379059,1.93500939 6.5822627,1.97746225 L6.5822627,2.27849013 C6.56379059,2.31708364 6.53977721,2.35374693 6.51022184,2.38848109 L2.57568253,6.49866948 Z" transform="translate(4.454287, 2.127976) rotate(90.000000) translate(-4.454287, -2.127976) "></path><path d="M3.74312342,2.09553332 C3.74312342,1.99519019 3.77821989,1.9083561 3.8484139,1.83502843 C3.91860791,1.76170075 4.00173115,1.72503747 4.09778611,1.72503747 L4.80711151,1.72503747 C4.90316647,1.72503747 4.98628971,1.76170075 5.05648372,1.83502843 C5.12667773,1.9083561 5.16177421,1.99519019 5.16177421,2.09553332 L5.16177421,10.2464421 C5.16177421,10.3467853 5.12667773,10.4336194 5.05648372,10.506947 C4.98628971,10.5802747 4.90316647,10.616938 4.80711151,10.616938 L4.09778611,10.616938 C4.00173115,10.616938 3.91860791,10.5802747 3.8484139,10.506947 C3.77821989,10.4336194 3.74312342,10.3467853 3.74312342,10.2464421 L3.74312342,2.09553332 Z" transform="translate(4.452449, 6.170988) rotate(-90.000000) translate(-4.452449, -6.170988) "></path><path d="M2.57568253,14.6236695 C2.50548852,14.6969971 2.44637866,14.7220826 2.39835118,14.6989264 C2.3503237,14.6757703 2.32631032,14.6140216 2.32631032,14.5136785 L2.32631032,5.99227386 C2.32631032,5.89193073 2.3503237,5.83018204 2.39835118,5.80702594 C2.44637866,5.78386983 2.50548852,5.80895523 2.57568253,5.88228291 L6.51022184,9.99247129 C6.53977721,10.0233461 6.56379059,10.0600094 6.5822627,10.1024622 L6.5822627,10.4034901 C6.56379059,10.4420836 6.53977721,10.4787469 6.51022184,10.5134811 L2.57568253,14.6236695 Z" transform="translate(4.454287, 10.252976) scale(1, -1) rotate(90.000000) translate(-4.454287, -10.252976) "></path></svg>
diff --git a/app/views/shared/icons/_container_registry.svg b/app/views/shared/icons/_container_registry.svg
deleted file mode 100644
index 56d62aab670..00000000000
--- a/app/views/shared/icons/_container_registry.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m16 11.764v-8.764c0-1.657-1.343-3-3-3h-10c-1.657 0-3 1.343-3 3v8.764c.531-.475 1.232-.764 2-.764v-8c0-.552.448-1 1-1h10c.552 0 1 .448 1 1v8c.768 0 1.469.289 2 .764m-14 .236h12c1.105 0 2 .895 2 2 0 1.105-.895 2-2 2h-12c-1.105 0-2-.895-2-2 0-1.105.895-2 2-2m10 1c-.552 0-1 .448-1 1 0 .552.448 1 1 1 .552 0 1-.448 1-1 0-.552-.448-1-1-1"/></svg>
diff --git a/app/views/shared/icons/_dev_ops_report_no_index.svg b/app/views/shared/icons/_dev_ops_report_no_index.svg
deleted file mode 100644
index 0577efca93f..00000000000
--- a/app/views/shared/icons/_dev_ops_report_no_index.svg
+++ /dev/null
@@ -1,64 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="360" height="200" viewBox="0 0 360 200">
- <g fill="none" fill-rule="evenodd" transform="translate(3 11)">
- <rect width="110" height="168" x="6" y="8" fill="#000" fill-opacity=".02" rx="10"/>
- <g transform="translate(0 2)">
- <rect width="110" height="168" fill="#FFF" rx="10"/>
- <path fill="#EEE" fill-rule="nonzero" d="M2 10.006v147.988C2 162.42 5.58 166 10.005 166h89.99c4.42 0 8.005-3.586 8.005-8.006V10.006C108 5.58 104.42 2 99.995 2h-89.99C5.585 2 2 5.586 2 10.006zm-4 0C-2 3.376 3.377-2 10.005-2h89.99C106.628-2 112 3.37 112 10.006v147.988c0 6.63-5.377 12.006-12.005 12.006h-89.99C3.372 170-2 164.63-2 157.994V10.006z"/>
- <g transform="translate(19 80)">
- <rect width="24" height="4" y="10" fill="#F0EDF8" rx="2"/>
- <rect width="14" height="4" x="5" fill="#6B4FBB" rx="2"/>
- </g>
- <g transform="translate(67 80)">
- <rect width="24" height="4" y="10" fill="#F0EDF8" rx="2"/>
- <rect width="14" height="4" x="5" fill="#6B4FBB" rx="2"/>
- </g>
- <g transform="translate(36 40)">
- <rect width="22" height="4" x="8" fill="#FEE1D3" rx="2"/>
- <rect width="38" height="4" y="12" fill="#FB722E" rx="2"/>
- </g>
- <path fill="#EEE" d="M2 12h106v4H2z"/>
- </g>
- <g transform="translate(122)">
- <rect width="110" height="168" x="2" y="2" fill="#FFF" rx="10"/>
- <path fill="#EEE" fill-rule="nonzero" d="M4 12.006c0-2.208.896-4.27 2.457-5.77.796-.766.82-2.032.055-2.828-.766-.796-2.032-.82-2.828-.055C1.347 5.6 0 8.7 0 12.006c0 1.105.895 2 2 2s2-.895 2-2zM14.388 4h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm17.51.227c2.115.514 3.93 1.88 5.022 3.756.556.955 1.78 1.28 2.735.724.954-.556 1.278-1.78.723-2.735-1.636-2.813-4.356-4.86-7.534-5.632-1.073-.26-2.155.397-2.416 1.47-.26 1.074.397 2.156 1.47 2.417zM110 16.78v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm-.024 17.844c-.17 2.186-1.227 4.18-2.903 5.558-.853.702-.976 1.962-.275 2.815.7.854 1.962.977 2.815.275 2.51-2.062 4.096-5.056 4.35-8.338.086-1.1-.737-2.063-1.838-2.15-1.102-.084-2.064.74-2.15 1.84zM98.826 168h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-17.334-.4c-2.063-.68-3.77-2.186-4.71-4.143-.477-.996-1.67-1.416-2.667-.938-.996.476-1.416 1.67-.938 2.667 1.41 2.936 3.964 5.19 7.063 6.21 1.05.347 2.18-.223 2.526-1.272.346-1.05-.224-2.18-1.274-2.526zM4 154.434v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2z"/>
- <g transform="translate(21 82)">
- <rect width="24" height="4" y="10" fill="#F0EDF8" rx="2"/>
- <rect width="14" height="4" x="5" fill="#C3B8E3" rx="2"/>
- </g>
- <g transform="translate(69 82)">
- <rect width="24" height="4" y="10" fill="#F0EDF8" rx="2"/>
- <rect width="14" height="4" x="5" fill="#C3B8E3" rx="2"/>
- </g>
- <path fill="#FEE1D3" d="M44 44c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C44.894 46 44 45.112 44 44zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C54.894 46 54 45.112 54 44zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C64.894 46 64 45.112 64 44zM34 56c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C34.894 58 34 57.112 34 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C44.894 58 44 57.112 44 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C54.894 58 54 57.112 54 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C64.894 58 64 57.112 64 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C74.894 58 74 57.112 74 56z"/>
- <rect width="8" height="4" x="8" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="21" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="34" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="47" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="60" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="73" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="86" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="99" y="14" fill="#EEE" rx="2"/>
- </g>
- <g transform="translate(243)">
- <rect width="110" height="168" x="2" y="2" fill="#FFF" rx="10"/>
- <path fill="#EEE" fill-rule="nonzero" d="M4 12.006c0-2.208.896-4.27 2.457-5.77.796-.766.82-2.032.055-2.828-.766-.796-2.032-.82-2.828-.055C1.347 5.6 0 8.7 0 12.006c0 1.105.895 2 2 2s2-.895 2-2zM14.388 4h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm18 0h8c1.104 0 2-.895 2-2s-.896-2-2-2h-8c-1.105 0-2 .895-2 2s.895 2 2 2zm17.51.227c2.115.514 3.93 1.88 5.022 3.756.556.955 1.78 1.28 2.735.724.954-.556 1.278-1.78.723-2.735-1.636-2.813-4.356-4.86-7.534-5.632-1.073-.26-2.155.397-2.416 1.47-.26 1.074.397 2.156 1.47 2.417zM110 16.78v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm0 18v8c0 1.104.895 2 2 2s2-.896 2-2v-8c0-1.105-.895-2-2-2s-2 .895-2 2zm-.024 17.844c-.17 2.186-1.227 4.18-2.903 5.558-.853.702-.976 1.962-.275 2.815.7.854 1.962.977 2.815.275 2.51-2.062 4.096-5.056 4.35-8.338.086-1.1-.737-2.063-1.838-2.15-1.102-.084-2.064.74-2.15 1.84zM98.826 168h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-18 0h-8c-1.104 0-2 .895-2 2s.896 2 2 2h8c1.105 0 2-.895 2-2s-.895-2-2-2zm-17.334-.4c-2.063-.68-3.77-2.186-4.71-4.143-.477-.996-1.67-1.416-2.667-.938-.996.476-1.416 1.67-.938 2.667 1.41 2.936 3.964 5.19 7.063 6.21 1.05.347 2.18-.223 2.526-1.272.346-1.05-.224-2.18-1.274-2.526zM4 154.434v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2zm0-18v-8c0-1.104-.895-2-2-2s-2 .896-2 2v8c0 1.105.895 2 2 2s2-.895 2-2z"/>
- <path fill="#FEE1D3" d="M44 44c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C44.894 46 44 45.112 44 44zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C54.894 46 54 45.112 54 44zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C64.894 46 64 45.112 64 44zM34 56c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C34.894 58 34 57.112 34 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C44.894 58 44 57.112 44 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C54.894 58 54 57.112 54 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C64.894 58 64 57.112 64 56zm10 0c0-1.105.898-2 1.998-2h2.004c1.104 0 1.998.888 1.998 2 0 1.105-.898 2-1.998 2h-2.004C74.894 58 74 57.112 74 56z"/>
- <g transform="translate(21 82)">
- <rect width="24" height="4" y="10" fill="#F0EDF8" rx="2"/>
- <rect width="14" height="4" x="5" fill="#C3B8E3" rx="2"/>
- </g>
- <g transform="translate(69 82)">
- <rect width="24" height="4" y="10" fill="#F0EDF8" rx="2"/>
- <rect width="14" height="4" x="5" fill="#C3B8E3" rx="2"/>
- </g>
- <rect width="8" height="4" x="8" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="21" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="34" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="47" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="60" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="73" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="86" y="14" fill="#EEE" rx="2"/>
- <rect width="8" height="4" x="99" y="14" fill="#EEE" rx="2"/>
- </g>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_doc_text.svg b/app/views/shared/icons/_doc_text.svg
deleted file mode 100644
index 92902a5b449..00000000000
--- a/app/views/shared/icons/_doc_text.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V7h-3a2 2 0 0 1-2-2V2zm2 .414V5h2.586L10 2.414zM5 0h4.586A2 2 0 0 1 11 .586L14.414 4A2 2 0 0 1 15 5.414V12a4 4 0 0 1-4 4H5a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4zm.5 11h5a.5.5 0 1 1 0 1h-5a.5.5 0 1 1 0-1zm0-2h5a.5.5 0 1 1 0 1h-5a.5.5 0 0 1 0-1zm0-2h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1 0-1z"/></svg>
diff --git a/app/views/shared/icons/_ellipsis_v.svg b/app/views/shared/icons/_ellipsis_v.svg
deleted file mode 100644
index 9117a9bb9ec..00000000000
--- a/app/views/shared/icons/_ellipsis_v.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1600 1600"><path d="M1088 1248v192q0 40-28 68t-68 28H800q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h192q40 0 68 28t28 68zm0-512v192q0 40-28 68t-68 28H800q-40 0-68-28t-28-68V736q0-40 28-68t68-28h192q40 0 68 28t28 68zm0-512v192q0 40-28 68t-68 28H800q-40 0-68-28t-28-68V224q0-40 28-68t68-28h192q40 0 68 28t28 68z"/></svg>
diff --git a/app/views/shared/icons/_emails.svg b/app/views/shared/icons/_emails.svg
deleted file mode 100644
index 3ebc64bb03e..00000000000
--- a/app/views/shared/icons/_emails.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 4a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1H3zm0-2h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3z"/><path d="M3.212 4L8 8.31 12.788 4H3.212zm6.126 5.796a2 2 0 0 1-2.676 0L.183 3.965A3.001 3.001 0 0 1 3 2h10c1.293 0 2.395.818 2.817 1.965l-6.48 5.83z"/></svg>
diff --git a/app/views/shared/icons/_gitea_logo.svg.erb b/app/views/shared/icons/_gitea_logo.svg.erb
deleted file mode 100644
index c8ddbc5535e..00000000000
--- a/app/views/shared/icons/_gitea_logo.svg.erb
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!-- Created with Inkscape (http://www.inkscape.org/) --><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="<%= size %>" height="<%= size %>" viewBox="0 0 135.46667 135.46667" version="1.1" id="svg8" sodipodi:docname="logo.svg" inkscape:version="0.92.1 r15371" inkscape:export-filename="" inkscape:export-xdpi="48.000004" inkscape:export-ydpi="48.000004" style="zoom: 1;"><defs id="defs2"></defs><sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:zoom="0.70710678" inkscape:cx="418.13805" inkscape:cy="177.57445" inkscape:document-units="mm" inkscape:current-layer="layer2" showgrid="false" units="px" width="256px" showguides="false" inkscape:window-width="1920" inkscape:window-height="1137" inkscape:window-x="1912" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:pagecheckerboard="false" inkscape:measure-start="283.373,243.952" inkscape:measure-end="290.267,236.527"><sodipodi:guide position="0,0" orientation="0,512" id="guide3699" inkscape:locked="false"></sodipodi:guide><sodipodi:guide position="135.46667,0" orientation="-512,0" id="guide3701" inkscape:locked="false"></sodipodi:guide><sodipodi:guide position="135.46667,135.46667" orientation="0,-512" id="guide3703" inkscape:locked="false"></sodipodi:guide><sodipodi:guide position="0,135.46667" orientation="512,0" id="guide3705" inkscape:locked="false"></sodipodi:guide></sodipodi:namedview><metadata id="metadata5"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"></dc:type><dc:title></dc:title></cc:Work></rdf:RDF></metadata><g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(0,-161.53334)" style="display:inline"><path d="M27.709937,195.15095 c-9.546573,-0.0272 -22.3392732,6.79805 -21.6317552,23.90397 c1.105534,26.72889 25.4565952,29.20839 35.1916502,29.42301 c1.068023,5.01357 12.521798,22.30563 21.001818,23.21667 h37.15277 c22.27763,-1.66785 38.9607,-75.75671 26.59321,-76.03825 c-46.781583,2.47691 -49.995146,2.13838 -88.599758,0 c-2.495053,-0.0266 -5.972321,-0.49474 -9.707935,-0.5054 z m2.491319,9.45886 c1.351378,13.69267 3.555849,21.70359 8.018216,33.94345 c-11.382872,-1.50473 -21.069822,-5.22443 -22.851515,-19.10984 c-0.950962,-7.4112 2.390428,-15.16769 14.833299,-14.83361 z " id="path3722" sodipodi:nodetypes="sscccccsccsc" inkscape:connector-curvature="0" style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"></path></g><g inkscape:groupmode="layer" id="layer2" inkscape:label="Layer 2" style="display:inline"><rect style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.24757317;stroke-opacity:1" id="rect4599" width="34.762054" height="34.762054" x="87.508659" y="18.291576" transform="rotate(25.914715)" ry="5.4825778"></rect><path style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26644793px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 79.804947,57.359056 3.241146,1.609954 V 35.255731 h -3.262698 z" id="path4525" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"></path></g><g inkscape:groupmode="layer" id="layer3" inkscape:label="Layer 3" style="display:inline"><g style="display:inline" id="g4539"><circle style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" id="path4606" cy="90.077766" r="3.4745038" cx="49.064713" transform="rotate(-19.796137)"></circle><circle style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" id="path4606-3" cy="102.1049" r="3.4745038" cx="36.810425" transform="rotate(-19.796137)"></circle><circle style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1" id="path4606-1" cy="111.43928" r="3.4745038" cx="46.484283" transform="rotate(-19.796137)"></circle><rect height="27.261492" style="fill:#000;fill-opacity:1;stroke:none;stroke-width:0.27444693;stroke-opacity:1" x="97.333458" y="18.061695" id="rect4629-8" width="2.6726954" transform="rotate(26.024158)"></rect><path d="M76.558096,68.116343 c12.97589,6.395378 13.012989,4.101862 4.890858,20.907244 " id="path4514" sodipodi:nodetypes="cc" inkscape:connector-curvature="0" style="fill:none;stroke:#000;stroke-width:2.68000007;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"></path></g></g></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_go_logo.svg.erb b/app/views/shared/icons/_go_logo.svg.erb
deleted file mode 100644
index 5052651c110..00000000000
--- a/app/views/shared/icons/_go_logo.svg.erb
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="<%= size %>" height="<%= size %>" viewBox="0 0 16 16"><g fill-rule="evenodd" transform="translate(0 1)"><path d="m14 15.01h1v-8.02c0-3.862-3.134-6.991-7-6.991-3.858 0-7 3.13-7 6.991v8.02h1v-8.02c0-3.306 2.691-5.991 6-5.991 3.314 0 6 2.682 6 5.991v8.02m-10.52-13.354c-.366-.402-.894-.655-1.48-.655-1.105 0-2 .895-2 2 0 .868.552 1.606 1.325 1.883.102-.321.226-.631.371-.93-.403-.129-.695-.507-.695-.953 0-.552.448-1 1-1 .306 0 .58.138.764.354.222-.25.461-.483.717-.699m9.04-.002c.366-.401.893-.653 1.479-.653 1.105 0 2 .895 2 2 0 .867-.552 1.606-1.324 1.883-.101-.321-.225-.632-.37-.931.403-.129.694-.507.694-.952 0-.552-.448-1-1-1-.305 0-.579.137-.762.353-.222-.25-.461-.483-.717-.699"/><path d="m5.726 7.04h1.557v.124c0 .283-.033.534-.1.752-.065.202-.175.391-.33.566-.35.394-.795.591-1.335.591-.527 0-.979-.19-1.355-.571-.376-.382-.564-.841-.564-1.377 0-.547.191-1.01.574-1.391.382-.382.848-.574 1.396-.574.295 0 .57.06.825.181.244.12.484.316.72.586l-.405.388c-.309-.412-.686-.618-1.13-.618-.399 0-.733.138-1 .413-.27.27-.405.609-.405 1.015 0 .42.151.766.452 1.037.282.252.587.378.915.378.28 0 .531-.094.754-.283.223-.19.347-.418.373-.683h-.94v-.535m2.884.061c0-.53.194-.986.583-1.367.387-.381.853-.571 1.396-.571.537 0 .998.192 1.382.576.386.384.578.845.578 1.384 0 .542-.194 1-.581 1.379-.389.379-.858.569-1.408.569-.487 0-.923-.168-1.311-.505-.426-.373-.64-.861-.64-1.465m.574.007c0 .417.14.759.42 1.028.278.269.6.403.964.403.395 0 .729-.137 1-.41.272-.277.408-.613.408-1.01 0-.402-.134-.739-.403-1.01-.267-.273-.597-.41-.991-.41-.392 0-.723.137-.993.41-.27.27-.405.604-.405 1m-.184 3.918c.525.026.812.063.812.063.271.025.324-.096.116-.273 0 0-.775-.813-1.933-.813-1.159 0-1.923.813-1.923.813-.211.174-.153.3.12.273 0 0 .286-.037.81-.063v.477c0 .268.224.5.5.5.268 0 .5-.223.5-.498v-.252.25c0 .268.224.5.5.5.268 0 .5-.223.5-.498v-.478m-1-1.023c.552 0 1-.224 1-.5 0-.276-.448-.5-1-.5-.552 0-1 .224-1 .5 0 .276.448.5 1 .5"/></g></svg>
diff --git a/app/views/shared/icons/_group.svg.erb b/app/views/shared/icons/_group.svg.erb
deleted file mode 100644
index 53635016900..00000000000
--- a/app/views/shared/icons/_group.svg.erb
+++ /dev/null
@@ -1,13 +0,0 @@
-<svg width="<%= size %>" height="<%= size %>" viewBox="0 0 16 16">
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Group" fill="#303030">
- <path d="M15.6667,10.0105 L10.3337,10.0105 C10.1497,10.0105 9.9997,10.1775 9.9997,10.3845 L9.9997,15.6145 C9.9997,15.8215 10.1497,15.9885 10.3337,15.9885 L15.6667,15.9885 C15.8507,15.9885 15.9997,15.8215 15.9997,15.6145 L15.9997,10.3845 C15.9997,10.1775 15.8507,10.0105 15.6667,10.0105 L15.6667,10.0105 L15.6667,10.0105 Z M11.9997,14.0105 L13.9997,14.0105 L13.9997,12.0105 L11.9997,12.0105 L11.9997,14.0105 L11.9997,14.0105 Z" id="Fill-11"></path>
- <path d="M5.6667,10.0105 L0.3337,10.0105 C0.1497,10.0105 -0.0003,10.1775 -0.0003,10.3845 L-0.0003,15.6145 C-0.0003,15.8215 0.1497,15.9885 0.3337,15.9885 L5.6667,15.9885 C5.8507,15.9885 5.9997,15.8215 5.9997,15.6145 L5.9997,10.3845 C5.9997,10.1775 5.8507,10.0105 5.6667,10.0105 L5.6667,10.0105 L5.6667,10.0105 Z M1.9997,14.0105 L3.9997,14.0105 L3.9997,12.0105 L1.9997,12.0105 L1.9997,14.0105 L1.9997,14.0105 Z" id="Fill-8"></path>
- <polygon id="Stroke-1" points="12.5 7.5834 3.5 7.5834 3.5 9.5834 12.5 9.5834"></polygon>
- <polygon id="Stroke-3" points="9 9.0834 9 5.0834 7 5.0834 7 9.0834"></polygon>
- <polygon id="Stroke-4" points="4 11.0834 4 7.5834 2 7.5834 2 11.0834"></polygon>
- <polygon id="Stroke-6" points="14 11.0834 14 7.5834 12 7.5834 12 11.0834"></polygon>
- <path d="M11.6667,6.21724894e-15 L4.3337,6.21724894e-15 C4.1497,6.21724894e-15 3.9997,0.167 3.9997,0.374 L3.9997,6.604 C3.9997,6.811 4.1497,6.978 4.3337,6.978 L11.6667,6.978 C11.8507,6.978 11.9997,6.811 11.9997,6.604 L11.9997,0.374 C11.9997,0.167 11.8507,6.21724894e-15 11.6667,6.21724894e-15 L11.6667,6.21724894e-15 L11.6667,6.21724894e-15 Z M5.9997,5 L9.9997,5 L9.9997,2 L5.9997,2 L5.9997,5 L5.9997,5 Z" id="Fill-14"></path>
- </g>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_1.svg b/app/views/shared/icons/_i2p_step_1.svg
deleted file mode 100644
index 9dedcd5291a..00000000000
--- a/app/views/shared/icons/_i2p_step_1.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m45.688 18.854c-4.869-1.989-10.488-1.975-15.29-.001-2.413.979-4.597 2.414-6.493 4.268-1.836 1.8-3.33 3.985-4.346 6.381-1.013 2.38-1.525 4.916-1.525 7.537 0 2.066.33 4.118.983 6.104.469 1.388 1.089 2.706 1.83 3.937-1.275 1.101-2.086 2.725-2.086 4.538 0 3.309 2.691 6 6 6s6-2.691 6-6-2.691-6-6-6c-.779 0-1.522.154-2.205.425-.665-1.105-1.221-2.289-1.642-3.533-.585-1.776-.881-3.618-.881-5.472 0-2.351.459-4.623 1.391-6.814.89-2.096 2.231-4.059 3.88-5.675 1.708-1.669 3.675-2.962 5.85-3.845 4.329-1.778 9.392-1.79 13.78.002 2.17.881 4.137 2.175 5.843 3.84 3.39 3.34 5.257 7.776 5.257 12.493.002 1.86-.294 3.705-.878 5.481-.579 1.75-1.443 3.406-2.569 4.923-2.134 2.866-3.818 4.698-5.174 6.173-2.424 2.643-3.98 4.599-4.383 8.384h-10.815c-.553 0-1 .447-1 1s.447 1 1 1h11.739c.532 0 .971-.416.999-.947.19-3.645 1.345-5.263 3.934-8.09 1.385-1.506 3.107-3.381 5.304-6.331 1.254-1.688 2.218-3.535 2.864-5.489.651-1.98.98-4.04.979-6.109 0-5.256-2.078-10.198-5.856-13.92-1.897-1.851-4.081-3.287-6.49-4.265m-16.927 32.763c0 2.206-1.794 4-4 4s-4-1.794-4-4 1.794-4 4-4 4 1.794 4 4"/>
- <path d="m40 74h-4c-.553 0-1 .447-1 1s.447 1 1 1h4c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m42 70h-8c-.553 0-1 .447-1 1s.447 1 1 1h8c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m38 10c.553 0 1-.447 1-1v-8c0-.553-.447-1-1-1s-1 .447-1 1v8c0 .553.447 1 1 1"/>
- <path d="m20.828 15.828c.256 0 .512-.098.707-.293.391-.391.391-1.023 0-1.414l-5.656-5.656c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l5.656 5.656c.195.195.451.293.707.293"/>
- <path d="m10 33h-8c-.553 0-1 .447-1 1s.447 1 1 1h8c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m60.12 8.465l-5.656 5.656c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l5.656-5.656c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0"/>
- <path d="m74 33h-8c-.553 0-1 .447-1 1s.447 1 1 1h8c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m43 66h-10c-.553 0-1 .447-1 1s.447 1 1 1h10c.553 0 1-.447 1-1s-.447-1-1-1"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_10.svg b/app/views/shared/icons/_i2p_step_10.svg
deleted file mode 100644
index dd6fd1457ff..00000000000
--- a/app/views/shared/icons/_i2p_step_10.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m5 43c0 .553.447 1 1 1s1-.447 1-1v-4h4c.553 0 1-.447 1-1s-.447-1-1-1h-4v-4c0-.553-.447-1-1-1s-1 .447-1 1v4h-4c-.553 0-1 .447-1 1s.447 1 1 1h4v4"/>
- <path d="m75 37h-4v-4c0-.553-.447-1-1-1s-1 .447-1 1v4h-4c-.553 0-1 .447-1 1s.447 1 1 1h4v4c0 .553.447 1 1 1s1-.447 1-1v-4h4c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m21 38c0 .345.178.665.47.848l8 5c.165.103.348.152.529.152.333 0 .659-.166.849-.47.293-.469.15-1.086-.317-1.378l-6.644-4.152 6.644-4.152c.468-.292.61-.909.317-1.378s-.908-.611-1.378-.317l-8 5c-.292.182-.47.502-.47.847"/>
- <path d="m55 38c0-.345-.178-.665-.47-.848l-8-5c-.469-.294-1.086-.151-1.378.317-.293.469-.15 1.086.317 1.378l6.644 4.153-6.644 4.152c-.468.292-.61.909-.317 1.378.189.304.516.47.849.47.181 0 .364-.049.529-.152l8-5c.292-.183.47-.503.47-.848"/>
- <path d="m41.803 26.05c-.525-.168-1.089.124-1.256.65l-7 22c-.167.525.124 1.088.65 1.256.101.032.202.047.303.047.424 0 .817-.271.953-.697l7-22c.167-.526-.124-1.088-.65-1.256"/>
- <path d="m62 7c3.859 0 7 3.141 7 7v11c0 .553.447 1 1 1s1-.447 1-1v-11c0-4.963-4.04-9-9-9h-16.09c-.479-2.833-2.943-5-5.91-5-3.309 0-6 2.691-6 6s2.691 6 6 6c2.967 0 5.431-2.167 5.91-5h16.09m-22 3c-2.206 0-4-1.794-4-4s1.794-4 4-4 4 1.794 4 4-1.794 4-4 4"/>
- <path d="m6 26c.553 0 1-.447 1-1v-11c0-3.859 3.141-7 7-7h11.09l-3.293 3.293c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l5-5c.391-.391.391-1.023 0-1.414l-5-5c-.391-.391-1.023-.391-1.414 0s-.391 1.023 0 1.414l3.293 3.293h-11.09c-4.963 0-9 4.04-9 9v11c0 .553.447 1 1 1"/>
- <path d="m36 64c-2.967 0-5.431 2.167-5.91 5h-16.09c-3.859 0-7-3.141-7-7v-11c0-.553-.447-1-1-1s-1 .447-1 1v11c0 4.963 4.04 9 9 9h16.09c.478 2.833 2.942 5 5.91 5 3.309 0 6-2.691 6-6s-2.691-6-6-6m0 10c-2.206 0-4-1.794-4-4s1.794-4 4-4 4 1.794 4 4-1.794 4-4 4"/>
- <path d="m70 50c-.553 0-1 .447-1 1v11c0 3.859-3.141 7-7 7h-11.09l3.293-3.293c.391-.391.391-1.023 0-1.414s-1.023-.391-1.414 0l-5 5c-.391.391-.391 1.023 0 1.414l5 5c.195.195.451.293.707.293s.512-.098.707-.293c.391-.391.391-1.023 0-1.414l-3.293-3.293h11.09c4.963 0 9-4.04 9-9v-11c0-.553-.447-1-1-1"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_2.svg b/app/views/shared/icons/_i2p_step_2.svg
deleted file mode 100644
index b8805b90275..00000000000
--- a/app/views/shared/icons/_i2p_step_2.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m42.26 40.44c.558.073 1.045-.329 1.109-.877l2.625-22.444c.033-.283-.057-.567-.246-.781-.189-.214-.462-.336-.747-.336h-14c-.284 0-.555.121-.744.332-.19.212-.281.494-.25.776l3.454 31.575c-1.503 1.285-2.46 3.19-2.46 5.317 0 3.859 3.141 7 7 7s7-3.141 7-7-3.141-7-7-7c-.94 0-1.835.189-2.655.527l-3.23-29.527h11.761l-2.494 21.328c-.065.549.328 1.045.877 1.11m.741 13.562c0 2.757-2.243 5-5 5s-5-2.243-5-5 2.243-5 5-5 5 2.243 5 5"/>
- <path d="M73.236,23.749c-0.207-0.513-0.796-0.76-1.302-0.552c-0.513,0.207-0.759,0.79-0.552,1.302 C73.119,28.787,74,33.329,74,38c0,19.851-16.149,36-36,36S2,57.851,2,38S18.149,2,38,2c7.6,0,14.83,2.332,20.965,6.74 C58.339,9.702,58,10.825,58,12c0,1.603,0.624,3.109,1.758,4.242C60.891,17.376,62.397,18,64,18c1.603,0,3.109-0.624,4.242-1.758 C69.376,15.109,70,13.603,70,12s-0.624-3.109-1.758-4.242C67.109,6.624,65.603,6,64,6c-1.346,0-2.622,0.445-3.668,1.259 C53.812,2.512,46.104,0,38,0C17.047,0,0,17.047,0,38s17.047,38,38,38s38-17.047,38-38C76,33.07,75.07,28.275,73.236,23.749z M64,8 c1.068,0,2.072,0.416,2.828,1.172S68,10.932,68,12s-0.416,2.072-1.172,2.828c-1.512,1.512-4.145,1.512-5.656,0 C60.416,14.072,60,13.068,60,12s0.416-2.072,1.172-2.828S62.932,8,64,8z"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_3.svg b/app/views/shared/icons/_i2p_step_3.svg
deleted file mode 100644
index 6c783ed8289..00000000000
--- a/app/views/shared/icons/_i2p_step_3.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m12 8c0-3.309-2.691-6-6-6s-6 2.691-6 6c0 2.967 2.167 5.431 5 5.91v8.181c-2.833.478-5 2.942-5 5.909s2.167 5.431 5 5.91v8.181c-2.833.478-5 2.942-5 5.909s2.167 5.431 5 5.91v8.181c-2.833.478-5 2.942-5 5.909 0 3.309 2.691 6 6 6s6-2.691 6-6c0-2.967-2.167-5.431-5-5.91v-8.18c2.833-.478 5-2.942 5-5.91s-2.167-5.431-5-5.91v-8.18c2.833-.478 5-2.942 5-5.91s-2.167-5.431-5-5.91v-8.18c2.833-.479 5-2.943 5-5.91m-10 0c0-2.206 1.794-4 4-4s4 1.794 4 4-1.794 4-4 4-4-1.794-4-4m8 60c0 2.206-1.794 4-4 4s-4-1.794-4-4 1.794-4 4-4 4 1.794 4 4m0-20c0 2.206-1.794 4-4 4s-4-1.794-4-4 1.794-4 4-4 4 1.794 4 4m0-20c0 2.206-1.794 4-4 4s-4-1.794-4-4 1.794-4 4-4 4 1.794 4 4"/>
- <path d="m21 6h54c.553 0 1-.447 1-1s-.447-1-1-1h-54c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m21 12h35c.553 0 1-.447 1-1s-.447-1-1-1h-35c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m75 24h-54c-.553 0-1 .447-1 1s.447 1 1 1h54c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m21 32h34c.553 0 1-.447 1-1s-.447-1-1-1h-34c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m75 44h-54c-.553 0-1 .447-1 1s.447 1 1 1h54c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m21 52h34c.553 0 1-.447 1-1s-.447-1-1-1h-34c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m75 64h-54c-.553 0-1 .447-1 1s.447 1 1 1h54c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m55 70h-34c-.553 0-1 .447-1 1s.447 1 1 1h34c.553 0 1-.447 1-1s-.447-1-1-1"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_4.svg b/app/views/shared/icons/_i2p_step_4.svg
deleted file mode 100644
index af804c838e0..00000000000
--- a/app/views/shared/icons/_i2p_step_4.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m67.7 10h-6.751c-.507-5.598-5.221-10-10.949-10-6.06 0-11 4.935-11 11s4.935 11 11 11c5.728 0 10.442-4.402 10.949-10h6.751c1.269 0 2.3.987 2.3 2.2v57.6c0 1.213-1.031 2.2-2.3 2.2h-59.4c-1.269 0-2.3-.987-2.3-2.2v-57.6c0-1.213 1.031-2.2 2.3-2.2h15.15c.553 0 1-.447 1-1s-.447-1-1-1h-15.15c-2.371 0-4.3 1.884-4.3 4.2v57.6c0 2.316 1.929 4.2 4.3 4.2h59.4c2.371 0 4.3-1.884 4.3-4.2v-57.6c0-2.316-1.929-4.2-4.3-4.2m-17.7 10c-4.963 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9"/>
- <path d="m21.293 29.29c-.391.391-.391 1.023 0 1.414l12.975 12.975-12.975 12.974c-.391.391-.391 1.023 0 1.414.195.195.451.293.707.293s.512-.098.707-.293l13.682-13.682c.391-.391.391-1.023 0-1.414l-13.682-13.681c-.391-.391-1.023-.391-1.414 0"/>
- <path d="m54 59c.553 0 1-.447 1-1s-.447-1-1-1h-12c-.553 0-1 .447-1 1s.447 1 1 1h12"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_5.svg b/app/views/shared/icons/_i2p_step_5.svg
deleted file mode 100644
index e54f707019e..00000000000
--- a/app/views/shared/icons/_i2p_step_5.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m48.949 37c-.507-5.598-5.221-10-10.949-10s-10.442 4.402-10.949 10h-13.05c-.553 0-1 .447-1 1s.447 1 1 1h13.05c.507 5.598 5.221 10 10.949 10s10.442-4.402 10.949-10h12.24c.553 0 1-.447 1-1s-.447-1-1-1h-12.24m-10.949 10c-4.963 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9"/>
- <path d="M73.236,23.749c-0.207-0.513-0.797-0.76-1.302-0.552c-0.513,0.207-0.759,0.79-0.552,1.302 C73.119,28.787,74,33.329,74,38c0,19.851-16.149,36-36,36S2,57.851,2,38S18.149,2,38,2c7.6,0,14.83,2.332,20.965,6.74 C58.339,9.702,58,10.825,58,12c0,1.603,0.624,3.109,1.758,4.242C60.891,17.376,62.397,18,64,18c1.603,0,3.109-0.624,4.242-1.758 C69.376,15.109,70,13.603,70,12s-0.624-3.109-1.758-4.242C67.109,6.624,65.603,6,64,6c-1.346,0-2.622,0.445-3.668,1.259 C53.812,2.512,46.104,0,38,0C17.047,0,0,17.047,0,38s17.047,38,38,38s38-17.047,38-38C76,33.07,75.07,28.275,73.236,23.749z M64,8 c1.068,0,2.072,0.416,2.828,1.172S68,10.932,68,12s-0.416,2.072-1.172,2.828c-1.512,1.512-4.145,1.512-5.656,0 C60.416,14.072,60,13.068,60,12s0.416-2.072,1.172-2.828S62.932,8,64,8z"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_6.svg b/app/views/shared/icons/_i2p_step_6.svg
deleted file mode 100644
index c57baccc06b..00000000000
--- a/app/views/shared/icons/_i2p_step_6.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m14.267 7.32l-4.896 5.277-1.702-1.533c-.409-.369-1.043-.338-1.412.074-.369.41-.337 1.042.074 1.412l2.434 2.192c.064.058.139.091.212.13.035.018.065.048.101.062.114.044.235.066.356.066.135 0 .27-.028.396-.082.044-.019.077-.058.118-.084.076-.047.155-.086.219-.154l5.566-6c.375-.404.352-1.037-.054-1.413-.405-.377-1.036-.353-1.412.053"/>
- <path d="m31 9h44c.553 0 1-.447 1-1s-.447-1-1-1h-44c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m31 15h24c.553 0 1-.447 1-1s-.447-1-1-1h-24c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m11 0c-6.07 0-11 4.935-11 11s4.935 11 11 11 11-4.935 11-11-4.935-11-11-11m0 20c-4.963 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9"/>
- <path d="m14.267 34.32l-4.896 5.277-1.702-1.533c-.409-.368-1.043-.338-1.412.074-.369.41-.337 1.042.074 1.412l2.434 2.192c.064.058.139.091.212.13.035.018.065.048.101.062.114.044.235.066.356.066.135 0 .27-.028.396-.082.044-.019.077-.058.118-.084.076-.047.155-.086.219-.154l5.566-6c.375-.404.352-1.037-.054-1.413-.405-.377-1.036-.353-1.412.053"/>
- <path d="m75 34h-44c-.553 0-1 .447-1 1s.447 1 1 1h44c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m31 42h24c.553 0 1-.447 1-1s-.447-1-1-1h-24c-.553 0-1 .447-1 1s.447 1 1 1"/>
- <path d="m11 27c-6.07 0-11 4.935-11 11s4.935 11 11 11 11-4.935 11-11-4.935-11-11-11m0 20c-4.963 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9"/>
- <path d="m14.267 61.32l-4.896 5.277-1.702-1.533c-.409-.368-1.043-.338-1.412.074-.369.41-.337 1.042.074 1.412l2.434 2.192c.064.058.139.091.212.13.035.018.065.048.101.062.114.044.235.066.356.066.135 0 .27-.028.396-.082.044-.019.077-.058.118-.084.076-.047.155-.086.219-.154l5.566-6c.375-.404.352-1.037-.054-1.413-.405-.377-1.036-.353-1.412.053"/>
- <path d="m11 54c-6.07 0-11 4.935-11 11s4.935 11 11 11 11-4.935 11-11-4.935-11-11-11m0 20c-4.963 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9"/>
- <path d="m75 61h-44c-.553 0-1 .447-1 1s.447 1 1 1h44c.553 0 1-.447 1-1s-.447-1-1-1"/>
- <path d="m55 67h-24c-.553 0-1 .447-1 1s.447 1 1 1h24c.553 0 1-.447 1-1s-.447-1-1-1"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_7.svg b/app/views/shared/icons/_i2p_step_7.svg
deleted file mode 100644
index e9083de3afa..00000000000
--- a/app/views/shared/icons/_i2p_step_7.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="M73.236,23.749c-0.208-0.513-0.798-0.76-1.302-0.552c-0.513,0.207-0.759,0.79-0.552,1.302 C73.119,28.787,74,33.329,74,38c0,19.851-16.149,36-36,36S2,57.851,2,38S18.149,2,38,2c7.6,0,14.83,2.332,20.965,6.74 C58.339,9.702,58,10.825,58,12c0,1.603,0.624,3.109,1.758,4.242C60.891,17.376,62.397,18,64,18c1.603,0,3.109-0.624,4.242-1.758 C69.376,15.109,70,13.603,70,12s-0.624-3.109-1.758-4.242C67.109,6.624,65.603,6,64,6c-1.346,0-2.622,0.445-3.668,1.259 C53.812,2.512,46.104,0,38,0C17.047,0,0,17.047,0,38s17.047,38,38,38s38-17.047,38-38C76,33.07,75.07,28.275,73.236,23.749z M64,8 c1.068,0,2.072,0.416,2.828,1.172S68,10.932,68,12s-0.416,2.072-1.172,2.828c-1.512,1.512-4.145,1.512-5.656,0 C60.416,14.072,60,13.068,60,12s0.416-2.072,1.172-2.828S62.932,8,64,8z"/>
- <path d="m27.19 32.17c-.277-.479-.89-.643-1.366-.364l-12.654 7.326c-.309.179-.499.509-.499.865s.19.687.499.865l12.654 7.326c.157.092.33.135.5.135.345 0 .681-.179.866-.499.277-.478.113-1.09-.364-1.366l-11.159-6.461 11.159-6.461c.478-.276.642-.889.364-1.366"/>
- <path d="m48.808 47.827c.186.32.521.499.866.499.17 0 .343-.043.5-.135l12.654-7.326c.309-.179.499-.509.499-.865s-.19-.687-.499-.865l-12.654-7.326c-.478-.278-1.09-.114-1.366.364-.277.478-.113 1.09.364 1.366l11.159 6.461-11.159 6.461c-.478.276-.642.889-.364 1.366"/>
- <path d="m42.71 23.06l-11.312 33.23c-.179.522.102 1.091.624 1.269.106.037.216.054.322.054.416 0 .805-.262.946-.678l11.312-33.23c.179-.522-.102-1.091-.624-1.269-.523-.181-1.089.101-1.268.624"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_8.svg b/app/views/shared/icons/_i2p_step_8.svg
deleted file mode 100644
index 62676b0e12e..00000000000
--- a/app/views/shared/icons/_i2p_step_8.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m62.44 54.765l-9.912-11.09c.315-3.881.481-7.241.508-10.271-.029-13.871-3.789-23.05-13.413-32.746-.855-.859-2.411-.828-3.294.059-7.594 7.65-11.139 13.934-12.575 22.3-1.776.062-3.437.776-4.699 2.039-1.321 1.321-2.05 3.079-2.05 4.949s.729 3.628 2.051 4.949c1.321 1.322 3.079 2.051 4.949 2.051s3.628-.729 4.949-2.051c1.322-1.321 2.051-3.079 2.051-4.949 0-1.869-.729-3.627-2.051-4.949-.9-.9-2-1.517-3.205-1.824 1.373-7.859 4.764-13.818 11.999-21.11.128-.13.356-.158.456-.059 9.207 9.274 12.805 18.06 12.832 31.33-.026 3.079-.202 6.527-.536 10.54-.023.273.067.545.25.749l10.166 11.379c.062.076.109.23.093.32l-4.547 17.407c-.004.015-.009.036-.079.106-.062.063-.155.1-.2.106l-3.577.002c-.144-.009-.265-.077-.309-.153l-5.425-10.328c-.173-.329-.515-.535-.886-.535h-15.962c-.371 0-.713.206-.886.535l-5.407 10.303-.069.072c-.07.07-.165.105-.199.105l-3.588.001c-.179-.009-.304-.123-.33-.227l-4.531-17.338c-.029-.146.019-.301.049-.34l10.197-11.415c.367-.412.332-1.044-.08-1.412-.411-.366-1.042-.333-1.412.08l-10.229 11.453c-.448.554-.63 1.312-.474 2.084l4.544 17.396c.253.963 1.146 1.669 2.218 1.719h3.636c.581 0 1.187-.261 1.615-.693.114-.114.286-.286.406-.528l5.144-9.793h14.754l5.16 9.822c.396.697 1.124 1.143 2.01 1.192l3.712-.003c.604-.046 1.137-.285 1.544-.694.313-.316.504-.646.598-1.022l4.557-17.451c.143-.718-.039-1.476-.518-2.066m-33.435-24.765c0 1.335-.521 2.591-1.465 3.535s-2.2 1.465-3.535 1.465-2.591-.521-3.535-1.465-1.465-2.2-1.465-3.535.521-2.591 1.465-3.535 2.2-1.465 3.535-1.465 2.591.521 3.535 1.465 1.465 2.2 1.465 3.535"/>
-</svg>
diff --git a/app/views/shared/icons/_i2p_step_9.svg b/app/views/shared/icons/_i2p_step_9.svg
deleted file mode 100644
index e4285a14425..00000000000
--- a/app/views/shared/icons/_i2p_step_9.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 76 76" enable-background="new 0 0 76 76">
- <path d="m68 67c-1.725 0-3.36.541-4.723 1.545-2.298-4.02-6.592-6.545-11.277-6.545-2.734 0-5.359.853-7.555 2.43l-2.286-15.43h1.228l3.829 7.645c.339.598.962.979 1.724 1.022l2.812-.003c.507-.039.974-.25 1.316-.595.264-.266.433-.559.514-.882l3.433-13.145c.12-.611-.037-1.258-.449-1.763l-7.385-8.268c.231-2.875.354-5.376.374-7.641-.023-10.507-2.871-17.462-10.162-24.806-.737-.742-2.072-.715-2.829.044-5.617 5.659-8.309 10.336-9.446 16.463-1.267.186-2.438.764-3.36 1.686-1.134 1.134-1.758 2.64-1.758 4.243s.624 3.109 1.758 4.242c1.133 1.134 2.639 1.758 4.242 1.758s3.109-.624 4.242-1.758c1.134-1.133 1.758-2.639 1.758-4.242s-.624-3.109-1.758-4.242c-.858-.859-1.932-1.424-3.098-1.648 1.095-5.538 3.637-9.855 8.83-15.14 6.874 6.924 9.561 13.485 9.581 23.392-.021 2.316-.151 4.903-.402 7.91-.023.273.067.544.25.749l7.663 8.572-3.391 13.07-2.695.036-4.081-8.15c-.17-.339-.516-.553-.895-.553h-12.01c-.379 0-.725.214-.895.553l-4.04 8.114-2.707.015-3.427-13.07 7.671-8.588c.367-.412.332-1.044-.08-1.412-.411-.366-1.043-.333-1.412.08l-7.7 8.623c-.383.47-.54 1.116-.406 1.787l3.419 13.08c.216.829.98 1.438 1.907 1.48h2.735c.508 0 1.016-.218 1.391-.595.091-.09.242-.241.358-.475l3.804-7.597h1.228l-2.286 15.43c-2.196-1.577-4.821-2.43-7.555-2.43-4.685 0-8.979 2.53-11.277 6.545-1.363-1-2.998-1.545-4.723-1.545-4.411 0-8 3.589-8 8 0 .553.447 1 1 1h74c.553 0 1-.447 1-1 0-4.411-3.589-8-8-8m-36-44c0 1.068-.416 2.072-1.172 2.828-1.512 1.512-4.145 1.512-5.656 0-.756-.756-1.172-1.76-1.172-2.828s.416-2.072 1.172-2.828 1.76-1.172 2.828-1.172 2.072.416 2.828 1.172 1.172 1.76 1.172 2.828m-29.917 51c.478-2.834 2.949-5 5.917-5 1.638 0 3.17.652 4.313 1.836.231.24.562.35.895.29.327-.058.604-.274.739-.579 1.765-3.977 5.711-6.547 10.05-6.547 2.836 0 5.532 1.085 7.593 3.055.271.258.665.345 1.016.224.354-.122.61-.43.665-.8l2.588-17.479h4.275l2.589 17.479c.055.37.312.678.665.8s.745.035 1.016-.224c2.061-1.97 4.757-3.055 7.593-3.055 4.343 0 8.288 2.57 10.05 6.547.135.305.412.521.739.579.329.059.663-.051.895-.29 1.143-1.184 2.675-1.836 4.313-1.836 2.968 0 5.439 2.166 5.917 5h-71.834"/>
-</svg>
diff --git a/app/views/shared/icons/_icon_action_cancel.svg b/app/views/shared/icons/_icon_action_cancel.svg
deleted file mode 100644
index a1f700eb0ff..00000000000
--- a/app/views/shared/icons/_icon_action_cancel.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="30px" height="30px" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"><path d="M19.25,14.9765625 C19.25,14.1380166 19.0234398,13.3697952 18.5703125,12.671875 L12.6796875,18.5546875 C13.3932327,19.0182315 14.1666625,19.25 15,19.25 C15.5781279,19.25 16.1289036,19.1367199 16.6523438,18.9101562 C17.1757839,18.6835926 17.6276023,18.3802102 18.0078125,18 C18.3880227,17.6197898 18.690103,17.1653672 18.9140625,16.6367188 C19.138022,16.1080703 19.25,15.5546904 19.25,14.9765625 Z M11.4453125,17.3125 L17.34375,11.421875 C16.6406215,10.9479143 15.8593793,10.7109375 15,10.7109375 C14.2291628,10.7109375 13.5182324,10.9010398 12.8671875,11.28125 C12.2161426,11.6614602 11.7005227,12.1796842 11.3203125,12.8359375 C10.9401023,13.4921908 10.75,14.2057253 10.75,14.9765625 C10.75,15.8203167 10.9817685,16.5989548 11.4453125,17.3125 Z M21,14.9765625 C21,15.7942749 20.8411474,16.5755171 20.5234375,17.3203125 C20.2057276,18.0651079 19.7799506,18.7057265 19.2460938,19.2421875 C18.7122369,19.7786485 18.0742225,20.2057276 17.3320312,20.5234375 C16.58984,20.8411474 15.8125041,21 15,21 C14.1874959,21 13.41016,20.8411474 12.6679688,20.5234375 C11.9257775,20.2057276 11.2877631,19.7786485 10.7539062,19.2421875 C10.2200494,18.7057265 9.79427242,18.0651079 9.4765625,17.3203125 C9.15885258,16.5755171 9,15.7942749 9,14.9765625 C9,14.1588501 9.15885258,13.37891 9.4765625,12.6367188 C9.79427242,11.8945275 10.2200494,11.255211 10.7539062,10.71875 C11.2877631,10.182289 11.9257775,9.75520992 12.6679688,9.4375 C13.41016,9.11979008 14.1874959,8.9609375 15,8.9609375 C15.8125041,8.9609375 16.58984,9.11979008 17.3320312,9.4375 C18.0742225,9.75520992 18.7122369,10.182289 19.2460938,10.71875 C19.7799506,11.255211 20.2057276,11.8945275 20.5234375,12.6367188 C20.8411474,13.37891 21,14.1588501 21,14.9765625 Z"></path></svg>
diff --git a/app/views/shared/icons/_icon_action_play.svg b/app/views/shared/icons/_icon_action_play.svg
deleted file mode 100644
index 6ac192cd7e9..00000000000
--- a/app/views/shared/icons/_icon_action_play.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="30px" height="30px" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"><path d="M21.5401786,15.2320328 L11.90625,20.5858274 C11.7950143,20.6486998 11.6994982,20.6559541 11.6196987,20.6075908 C11.5398992,20.5592275 11.5,20.4721748 11.5,20.3464301 L11.5,9.66785867 C11.5,9.54211399 11.5398992,9.45506129 11.6196987,9.40669795 C11.6994982,9.35833462 11.7950143,9.36558901 11.90625,9.42846135 L21.5401786,14.782256 C21.6514142,14.8451283 21.7070312,14.9200904 21.7070312,15.0071444 C21.7070312,15.0941984 21.6514142,15.1691604 21.5401786,15.2320328 Z"></path></svg>
diff --git a/app/views/shared/icons/_icon_action_retry.svg b/app/views/shared/icons/_icon_action_retry.svg
deleted file mode 100644
index 0fa0243f3c0..00000000000
--- a/app/views/shared/icons/_icon_action_retry.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="30px" height="30px" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"><path d="M20.6114971,16.0821413 C20.6114971,16.106323 20.6090789,16.1232499 20.6042426,16.1329226 C20.2947172,17.42906 19.6466582,18.4797378 18.6600462,19.2849873 C17.6734341,20.0902369 16.5175677,20.4928556 15.1924122,20.4928556 C14.4863075,20.4928556 13.8031856,20.3598584 13.1430261,20.0938601 C12.4828665,19.8278617 11.8940517,19.4482152 11.376564,18.9549092 L10.4407381,19.8907351 C10.3488478,19.9826254 10.2400319,20.0285699 10.1142872,20.0285699 C9.98854256,20.0285699 9.87972669,19.9826254 9.78783635,19.8907351 C9.69594601,19.7988447 9.65000153,19.6900289 9.65000153,19.5642842 L9.65000153,16.3142842 C9.65000153,16.1885395 9.69594601,16.0797236 9.78783635,15.9878333 C9.87972669,15.895943 9.98854256,15.8499985 10.1142872,15.8499985 L13.3642872,15.8499985 C13.4900319,15.8499985 13.5988478,15.895943 13.6907381,15.9878333 C13.7826285,16.0797236 13.828573,16.1885395 13.828573,16.3142842 C13.828573,16.4400289 13.7826285,16.5488447 13.6907381,16.6407351 L12.6968765,17.6345967 C13.0402562,17.9537947 13.4295752,18.200444 13.8648453,18.374552 C14.3001153,18.5486601 14.7523057,18.6357128 15.2214301,18.6357128 C15.8694988,18.6357128 16.4740315,18.4785343 17.0350462,18.1641726 C17.5960609,17.8498109 18.0458332,17.4169655 18.3843765,16.8656235 C18.4375762,16.7834058 18.5657371,16.5004845 18.7688631,16.0168512 C18.8075538,15.9056155 18.8800977,15.8499985 18.9864971,15.8499985 L20.3793542,15.8499985 C20.4422265,15.8499985 20.4966345,15.8729707 20.5425797,15.9189159 C20.5885248,15.9648611 20.6114971,16.019269 20.6114971,16.0821413 Z M20.7928587,10.2785699 L20.7928587,13.5285699 C20.7928587,13.6543146 20.7469142,13.7631305 20.6550238,13.8550208 C20.5631335,13.9469111 20.4543176,13.9928556 20.328573,13.9928556 L17.078573,13.9928556 C16.9528283,13.9928556 16.8440124,13.9469111 16.7521221,13.8550208 C16.6602317,13.7631305 16.6142872,13.6543146 16.6142872,13.5285699 C16.6142872,13.4028252 16.6602317,13.2940094 16.7521221,13.202119 L17.7532381,12.2010029 C17.0374607,11.5384252 16.1935332,11.2071413 15.2214301,11.2071413 C14.5733614,11.2071413 13.9688287,11.3643198 13.407814,11.6786815 C12.8467993,11.9930432 12.397027,12.4258886 12.0584837,12.9772306 C12.005284,13.0594483 11.8771231,13.3423696 11.6739971,13.8260029 C11.6353064,13.9372386 11.5627625,13.9928556 11.4563631,13.9928556 L10.0127247,13.9928556 C9.9498524,13.9928556 9.89544446,13.9698834 9.84949929,13.9239382 C9.80355412,13.877993 9.78058188,13.8235851 9.78058188,13.7607128 L9.78058188,13.7099315 C10.0949436,12.4137941 10.7478388,11.3631163 11.7392872,10.5578668 C12.7307356,9.75261722 13.8914383,9.34999847 15.2214301,9.34999847 C15.9275348,9.34999847 16.6142839,9.48420472 17.281698,9.75262124 C17.949112,10.0210378 18.541554,10.3994752 19.0590417,10.8879449 L20.0021221,9.95211901 C20.0940124,9.86022867 20.2028283,9.81428419 20.328573,9.81428419 C20.4543176,9.81428419 20.5631335,9.86022867 20.6550238,9.95211901 C20.7469142,10.0440094 20.7928587,10.1528252 20.7928587,10.2785699 Z"></path></svg>
diff --git a/app/views/shared/icons/_icon_action_stop.svg b/app/views/shared/icons/_icon_action_stop.svg
deleted file mode 100644
index 1c8e2fe4156..00000000000
--- a/app/views/shared/icons/_icon_action_stop.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="30px" height="30px" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M20.1357204,10.2985704 L20.1357204,19.7271418 C20.1357204,19.8432138 20.0933101,19.9436592 20.0084882,20.0284811 C19.9236664,20.1133029 19.823221,20.1557132 19.707149,20.1557132 L10.2785775,20.1557132 C10.1625055,20.1557132 10.0620601,20.1133029 9.97723825,20.0284811 C9.89241639,19.9436592 9.8500061,19.8432138 9.8500061,19.7271418 L9.8500061,10.2985704 C9.8500061,10.1824984 9.89241639,10.0820529 9.97723825,9.99723107 C10.0620601,9.91240922 10.1625055,9.86999893 10.2785775,9.86999893 L19.707149,9.86999893 C19.823221,9.86999893 19.9236664,9.91240922 20.0084882,9.99723107 C20.0933101,10.0820529 20.1357204,10.1824984 20.1357204,10.2985704 Z"></path></svg>
diff --git a/app/views/shared/icons/_icon_arrow_circle_o_right.svg b/app/views/shared/icons/_icon_arrow_circle_o_right.svg
deleted file mode 100644
index 29bdc8e5754..00000000000
--- a/app/views/shared/icons/_icon_arrow_circle_o_right.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 6h-7a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586a1 1 0 0 0 -1.707.707z" fill-rule="evenodd"/></svg>
-
diff --git a/app/views/shared/icons/_icon_arrow_right.svg.erb b/app/views/shared/icons/_icon_arrow_right.svg.erb
deleted file mode 100644
index 24d64eb73bd..00000000000
--- a/app/views/shared/icons/_icon_arrow_right.svg.erb
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M9 6H2a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586A1 1 0 0 0 9 3.414V6z"/></svg>
diff --git a/app/views/shared/icons/_icon_autodevops.svg b/app/views/shared/icons/_icon_autodevops.svg
deleted file mode 100644
index 7e47c084bde..00000000000
--- a/app/views/shared/icons/_icon_autodevops.svg
+++ /dev/null
@@ -1,54 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="189" height="110" viewBox="0 0 189 179">
- <g fill="none" fill-rule="evenodd">
- <path fill="#FFFFFF" fill-rule="nonzero" d="M110.160166,47.6956996 L160.160166,47.6956996 C165.683013,47.6956996 170.160166,52.1728521 170.160166,57.6956996 L170.160166,117.6957 C170.160166,123.218547 165.683013,127.6957 160.160166,127.6957 L110.160166,127.6957 C104.637318,127.6957 100.160166,123.218547 100.160166,117.6957 L100.160166,57.6956996 C100.160166,52.1728521 104.637318,47.6956996 110.160166,47.6956996 Z" transform="rotate(10 135.16 87.696)"/>
- <path fill="#EEEEEE" fill-rule="nonzero" d="M110.160166,51.6956996 C106.846457,51.6956996 104.160166,54.3819911 104.160166,57.6956996 L104.160166,117.6957 C104.160166,121.009408 106.846457,123.6957 110.160166,123.6957 L160.160166,123.6957 C163.473874,123.6957 166.160166,121.009408 166.160166,117.6957 L166.160166,57.6956996 C166.160166,54.3819911 163.473874,51.6956996 160.160166,51.6956996 L110.160166,51.6956996 Z M110.160166,47.6956996 L160.160166,47.6956996 C165.683013,47.6956996 170.160166,52.1728521 170.160166,57.6956996 L170.160166,117.6957 C170.160166,123.218547 165.683013,127.6957 160.160166,127.6957 L110.160166,127.6957 C104.637318,127.6957 100.160166,123.218547 100.160166,117.6957 L100.160166,57.6956996 C100.160166,52.1728521 104.637318,47.6956996 110.160166,47.6956996 Z" transform="rotate(10 135.16 87.696)"/>
- <rect width="70" height="80" x="80" y="34" fill="#000000" fill-opacity=".03" transform="rotate(5 115 74)" rx="10"/>
- <path fill="#000000" fill-opacity=".03" fill-rule="nonzero" d="M126.028,178 L150,178 C169.972,177.457 186,161.1 186,141 C186,120.565 169.435,104 149,104 C148.007,104 147.023,104.04 146.05,104.116 C141.1,89.51 127.277,79 111,79 C105.71511,78.9924557 100.490375,80.1212986 95.68,82.31 C89.03,72.47 77.77,66 65,66 C44.565,66 28,82.565 28,103 C28,103.7 28.02,104.397 28.058,105.088 C11.944,109.088 0,123.648 0,141 C0,161.435 16.565,178 37,178 C37.324,178 37.646,177.996 37.968,177.988 L126.028,178 Z"/>
- <g transform="rotate(5 -300.07 1010.998)">
- <rect width="70" height="80" fill="#FFFFFF" rx="10"/>
- <path fill="#EEEEEE" fill-rule="nonzero" d="M10,4 C6.6862915,4 4,6.6862915 4,10 L4,70 C4,73.3137085 6.6862915,76 10,76 L60,76 C63.3137085,76 66,73.3137085 66,70 L66,10 C66,6.6862915 63.3137085,4 60,4 L10,4 Z M10,-2.68673972e-14 L60,-2.68673972e-14 C65.5228475,-2.78819278e-14 70,4.4771525 70,10 L70,70 C70,75.5228475 65.5228475,80 60,80 L10,80 C4.4771525,80 9.15550472e-14,75.5228475 9.08786935e-14,70 L9.08786935e-14,10 C9.02023397e-14,4.4771525 4.4771525,-2.58528666e-14 10,-2.68673972e-14 Z"/>
- <rect width="8" height="4" x="14" y="18" fill="#FC6D26" rx="2"/>
- <rect width="8" height="4" x="32" y="38" fill="#E1DBF1" rx="2"/>
- <rect width="8" height="4" x="45" y="48" fill="#FEE1D3" rx="2"/>
- <rect width="8" height="4" x="44" y="38" fill="#FEF0E8" rx="2"/>
- <rect width="12" height="4" x="26" y="18" fill="#EFEDF8" rx="2"/>
- <rect width="6" height="4" x="15" y="48" fill="#FEF0E8" rx="2"/>
- <rect width="6" height="4" x="25" y="48" fill="#FC6D26" rx="2"/>
- <rect width="6" height="4" x="35" y="48" fill="#EEEEEE" rx="2"/>
- <rect width="12" height="4" x="14" y="28" fill="#EEEEEE" rx="2"/>
- <rect width="12" height="4" x="44" y="58" fill="#6B4FBB" rx="2"/>
- <rect width="26" height="4" x="30" y="28" fill="#C3B8E3" rx="2"/>
- <rect width="26" height="4" x="15" y="58" fill="#FEE1D3" rx="2"/>
- <rect width="14" height="4" x="42" y="18" fill="#E1DBF1" rx="2"/>
- <rect width="14" height="4" x="14" y="38" fill="#6B4FBB" rx="2"/>
- </g>
- <g transform="translate(3 67)">
- <path fill="#FFFFFF" fill-rule="nonzero" d="M126.028,112 L150,112 C169.972,111.457 186,95.1 186,75 C186,54.565 169.435,38 149,38 C148.007,38 147.023,38.04 146.05,38.116 C141.1,23.51 127.277,13 111,13 C105.71511,12.9924557 100.490375,14.1212986 95.68,16.31 C89.03,6.47 77.77,0 65,0 C44.565,0 28,16.565 28,37 C28,37.7 28.02,38.397 28.058,39.088 C11.944,43.088 0,57.648 0,75 C0,95.435 16.565,112 37,112 C37.324,112 37.646,111.996 37.968,111.988 L126.028,112 Z"/>
- <path fill="#FFFFFF" d="M126.028,110 L149.946,110 C168.876,109.486 184,93.976 184,75 C184,55.67 168.33,40 149,40 C148.064,40 147.133,40.037 146.207,40.11 L144.656,40.232 L144.156,38.758 C139.381,24.67 126.116,15 111,15 C106.001056,14.9926759 101.058995,16.0604828 96.509,18.131 L94.969,18.832 L94.022,17.431 C87.552,7.855 76.774,2 65,2 C45.67,2 30,17.67 30,37 C30,37.661 30.018,38.32 30.055,38.977 L30.147,40.63 L28.54,41.029 C13.06,44.87 2,58.827 2,75 C2,94.33 17.67,110 37,110 C37.306,110 37.612,109.996 37.968,109.988 L126.028,110 Z"/>
- <path fill="#EEEEEE" fill-rule="nonzero" d="M149,38 C169.434569,38 186,54.5654305 186,75 C186,95.0477955 170.024944,111.45554 149.946,112 L126.028,112 L38.0129325,111.987495 C37.6348039,111.995992 37.3157048,112 37,112 C16.5654305,112 0,95.4345695 0,75 C0,57.9772494 11.6188339,43.1669444 28.0580557,39.0879359 C28.0192558,38.39805 28,37.7022134 28,37 C28,16.5654305 44.5654305,0 65,0 C77.3556804,0 88.7905015,6.1156181 95.6789703,16.310978 C100.491636,14.1213221 105.717209,12.9922579 111,13 C126.893041,13 140.974134,23.139867 146.049999,38.1155308 C147.031471,38.0388091 148.014765,38 149,38 Z M149.891715,108.000737 C167.750695,107.515818 182,92.8805667 182,75 C182,56.7745695 167.225431,42 149,42 C148.1197,42 147.241142,42.0346799 146.363833,42.1038413 L144.812833,42.2258413 C143.900567,42.2975992 143.055957,41.7410534 142.762001,40.8744692 L142.261844,39.400007 C137.735045,26.0442906 125.175364,17 110.99707,16.9999979 C106.284902,16.9930939 101.626355,17.9996435 97.3375854,19.9512874 L95.7975854,20.6522874 C94.9091924,21.0566793 93.8586575,20.7607079 93.3120297,19.952022 L92.3648004,18.5506827 C86.2175802,9.45241684 76.0227954,4 65,4 C46.7745695,4 32,18.7745695 32,37 C32,37.6282966 32.0172077,38.249659 32.0519095,38.8658592 L32.1439095,40.5188592 C32.1972908,41.4779816 31.5612439,42.3395846 30.6289443,42.5710641 L29.0216479,42.9701376 C14.3638424,46.6071293 4,59.8177208 4,75 C4,93.2254305 18.7745695,108 37,108 C37.2837952,108 37.5733598,107.996363 37.9682725,107.988 L126.02825,108 L149.891715,108.000737 Z"/>
- </g>
- <g fill-rule="nonzero" transform="rotate(15 -315.035 277.714)">
- <path fill="#FFFFFF" d="M12.275,10.57 C13.986216,9.15630755 15.921048,8.03765363 18,7.26 L18,5.5 C18,2.463 20.47,0 23.493,0 L26.507,0 C27.9648848,0.000530018716 29.3628038,0.580386367 30.3930274,1.61192286 C31.4232511,2.64345935 32.0013267,4.04211574 32,5.5 L32,7.26 C34.098,8.043 36.03,9.17 37.725,10.57 L39.253,9.688 C41.8816141,8.17268496 45.2407537,9.07039379 46.763,11.695 L48.27,14.305 C48.9984289,15.5678669 49.1951495,17.0684426 48.8168566,18.4763972 C48.4385638,19.8843518 47.5162683,21.0842673 46.253,21.812 L44.728,22.693 C44.907,23.769 45,24.873 45,26 C45,27.127 44.907,28.231 44.728,29.307 L46.253,30.187 C48.8800379,31.705769 49.7822744,35.0642181 48.27,37.695 L46.763,40.305 C46.0335844,41.5673849 44.8323832,42.4881439 43.4238487,42.8645658 C42.0153143,43.2409877 40.5149245,43.0422119 39.253,42.312 L37.725,41.43 C36.013784,42.8436924 34.078952,43.9623464 32,44.74 L32,46.5 C32,49.537 29.53,52 26.507,52 L23.493,52 C22.0351152,51.99947 20.6371962,51.4196136 19.6069726,50.3880771 C18.5767489,49.3565406 17.9986733,47.9578843 18,46.5 L18,44.74 C15.921048,43.9623464 13.986216,42.8436924 12.275,41.43 L10.747,42.312 C8.11838594,43.827315 4.75924629,42.9296062 3.237,40.305 L1.73,37.695 C1.00157113,36.4321331 0.804850523,34.9315574 1.18314337,33.5236028 C1.56143621,32.1156482 2.48373172,30.9157327 3.747,30.188 L5.272,29.307 C5.09051204,28.2140265 4.9995366,27.107939 5,26 C5,24.873 5.093,23.769 5.272,22.693 L3.747,21.813 C1.11996213,20.294231 0.217725591,16.9357819 1.73,14.305 L3.237,11.695 C3.96641559,10.4326151 5.16761682,9.51185609 6.57615125,9.13543417 C7.98468568,8.75901226 9.48507553,8.95778814 10.747,9.688 L12.275,10.57 Z"/>
- <path fill="#E1DBF1" d="M17.9996486,7.25963195 L18.0000013,5.49772675 C18.0034459,2.46713881 20.4561478,0.00952173148 23.493,0 L26.507,0 C29.542757,0 32,2.46161709 32,5.5 L32,7.25850184 C34.0799663,8.03664754 36.0149544,9.15559094 37.7260175,10.5694605 L39.2547869,9.68691874 C41.8812087,8.17416302 45.2363972,9.06948854 46.7630175,11.6949424 L48.270687,14.3061027 C48.9989901,15.569417 49.1952874,17.0704122 48.816349,18.4785295 C48.4374106,19.8866468 47.5143145,21.0864021 46.2530682,21.8120114 L44.7278655,22.6926677 C44.9091017,23.7802451 45,24.8850821 45,26 C45,27.1144218 44.9091826,28.218078 44.7278653,29.3073326 L46.2547984,30.1889888 C48.8778516,31.7070439 49.7801588,35.0599752 48.2700175,37.6950576 L46.7625317,40.3058986 C46.0327098,41.5684739 44.8309328,42.4891542 43.4219037,42.8651509 C42.0128746,43.2411475 40.512172,43.0416186 39.2533538,42.312255 L37.7244858,41.4299789 C36.013753,42.8435912 34.0794396,43.9622923 32.0003514,44.7403681 L31.9999987,46.5022733 C31.9965541,49.5328612 29.5438522,51.9904783 26.507,52 L23.493,52 C20.457243,52 18,49.5383829 18,46.5 L18,44.7414988 C15.9200337,43.9633525 13.9850456,42.8444091 12.2739825,41.4305395 L10.7452131,42.3130813 C8.11879127,43.825837 4.76360277,42.9305115 3.23698247,40.3050576 L1.72931303,37.6938973 C1.0010099,36.430583 0.804712603,34.9295878 1.18365098,33.5214705 C1.56258936,32.1133532 2.48568546,30.9135979 3.74693178,30.1879886 L5.27213454,29.3073323 C5.09089825,28.2197549 5,27.114918 5.00000019,26.0008761 C4.99951488,24.8930059 5.0904571,23.7869854 5.27213502,22.6926675 L3.74520157,21.8110112 C1.12214836,20.2929561 0.219841192,16.9400248 1.72998247,14.3049424 L3.23746831,11.6941014 C3.96729024,10.4315261 5.16906725,9.51084579 6.5780963,9.13484913 C7.98712536,8.75885247 9.48782803,8.95838137 10.7466462,9.687745 L12.2748018,10.56961 C14.0209791,9.13635584 15.9392199,8.03072455 17.9996486,7.25963195 Z M13.7518374,14.537862 C13.108069,15.069723 12.2016163,15.1456339 11.4783538,14.728255 L8.74433999,13.1505123 C8.40103903,12.9516035 7.99274958,12.8973186 7.60940137,12.9996143 C7.22605315,13.10191 6.89909107,13.3523954 6.70101753,13.6950576 L5.19724591,16.2994454 C4.78547321,17.0179634 5.03203388,17.9341714 5.74706822,18.3479886 L8.47306822,19.9219886 C9.19530115,20.3390079 9.58295216,21.1604138 9.44574883,21.983032 L9.21798321,23.3486236 C9.07251948,24.2246212 8.99961081,25.111131 9,26 C9,26.8953847 9.0728258,27.7804297 9.21774883,28.649968 L9.44574883,30.016968 C9.58295216,30.8395862 9.19530115,31.6609921 8.47306822,32.0780114 L5.74435077,33.6535776 C5.40046982,33.851417 5.14932721,34.1778291 5.04623114,34.5609292 C4.94313508,34.9440294 4.9965408,35.3523984 5.19401753,35.6949424 L6.69795587,38.2996585 C7.11427713,39.0156351 8.03110189,39.260288 8.7470791,38.8479035 L11.4770791,37.2719035 C12.200376,36.8543519 13.1069795,36.9302031 13.7508374,37.462138 L14.8210499,38.3463136 C16.1898549,39.4774943 17.737648,40.3725891 19.3990866,40.9941596 L20.6990866,41.4791596 C21.4813437,41.7710017 22,42.5180761 22,43.353 L22,46.5 C22,47.3308348 22.6679761,48 23.493,48 L26.5007228,48.0000099 C27.328845,47.9974107 27.99906,47.3258525 28,46.5 L28,43.353 C28,42.5185702 28.5180515,41.771829 29.2996486,41.4796319 L30.599003,40.9938734 C32.261836,40.3715765 33.8093225,39.4764853 35.1790197,38.3444304 L36.2490197,37.4614304 C36.8927697,36.9301861 37.798736,36.8545694 38.5216462,37.271745 L41.25566,38.8494877 C41.598961,39.0483965 42.0072504,39.1026814 42.3905986,39.0003857 C42.7739468,38.89809 43.1009089,38.6476046 43.2989825,38.3049424 L44.8027541,35.7005546 C45.2145268,34.9820366 44.9679661,34.0658286 44.2529318,33.6520114 L41.5269318,32.0780114 C40.8046988,31.6609921 40.4170478,30.8395862 40.5542512,30.016968 L40.7821577,28.6505288 C40.9272286,27.7792134 41,26.8950523 41,26 C41,25.1046153 40.9271742,24.2195703 40.7822512,23.350032 L40.5542512,21.983032 C40.4170478,21.1604138 40.8046988,20.3390079 41.5269318,19.9219886 L44.2556492,18.3464224 C44.5995302,18.148583 44.8506728,17.8221709 44.9537689,17.4390708 C45.0568649,17.0559706 45.0034592,16.6476016 44.8059825,16.3050576 L43.3020441,13.7003415 C42.8857229,12.9843649 41.9688981,12.739712 41.2529209,13.1520965 L38.5229209,14.7280965 C37.799624,15.1456481 36.8930205,15.0697969 36.2491626,14.537862 L35.1789501,13.6536864 C33.8101451,12.5225057 32.262352,11.6274109 30.6021792,11.0063122 L29.3021792,10.5223122 C28.5192618,10.230826 28,9.48341836 28,8.648 L28,5.5 C28,4.66916515 27.3320239,4 26.507,4 L23.4992772,3.99999015 C22.671155,4.00258933 22.00094,4.67414748 22,5.5 L22,8.647 C22,9.48142977 21.4819485,10.228171 20.7003514,10.5203681 L19.400997,11.0061266 C17.738164,11.6284235 16.1906775,12.5235147 14.822142,13.6546103 C14.8121128,13.6628994 14.4553446,13.9573166 13.7518374,14.537862 Z"/>
- <g transform="rotate(15 -59.137 82.348)">
- <circle cx="8" cy="8" r="8" fill="#FFFFFF" transform="translate(.035 6.008)"/>
- <path fill="#6B4FBB" d="M7.40192379,14.7679492 C2.98364579,14.7679492 -0.598076211,11.1862272 -0.598076211,6.76794919 C-0.598076211,2.34967119 2.98364579,-1.23205081 7.40192379,-1.23205081 C11.8202018,-1.23205081 15.4019238,2.34967119 15.4019238,6.76794919 C15.4019238,11.1862272 11.8202018,14.7679492 7.40192379,14.7679492 Z M7.40192379,10.7679492 C9.61106279,10.7679492 11.4019238,8.97708819 11.4019238,6.76794919 C11.4019238,4.55881019 9.61106279,2.76794919 7.40192379,2.76794919 C5.19278479,2.76794919 3.40192379,4.55881019 3.40192379,6.76794919 C3.40192379,8.97708819 5.19278479,10.7679492 7.40192379,10.7679492 Z"/>
- </g>
- </g>
- <g fill-rule="nonzero" transform="rotate(15 -402.968 460.884)">
- <path fill="#FFFFFF" d="M9.82,8.53730769 C11.1889728,7.39547918 12.7368384,6.49195101 14.4,5.86384615 L14.4,4.44230769 C14.4,1.98934615 16.376,0 18.7944,0 L21.2056,0 C22.3719078,0.00042809204 23.4902431,0.468773604 24.314422,1.30193769 C25.1386009,2.13510179 25.6010613,3.26478579 25.6,4.44230769 L25.6,5.86384615 C27.2784,6.49626923 28.824,7.40653846 30.18,8.53730769 L31.4024,7.82492308 C33.5052912,6.60101478 36.192603,7.32608729 37.4104,9.44596154 L38.616,11.5540385 C39.1987431,12.5740464 39.3561196,13.7860498 39.0534853,14.9232439 C38.750851,16.060438 38.0130146,17.0296006 37.0024,17.6173846 L35.7824,18.3289615 C35.9256,19.1980385 36,20.0897308 36,21 C36,21.9102692 35.9256,22.8019615 35.7824,23.6710385 L37.0024,24.3818077 C39.1040303,25.6085057 39.8258195,28.3210992 38.616,30.4459615 L37.4104,32.5540385 C36.8268675,33.573657 35.8659065,34.317347 34.739079,34.6213801 C33.6122515,34.9254132 32.4119396,34.7648634 31.4024,34.1750769 L30.18,33.4626923 C28.8110272,34.6045208 27.2631616,35.508049 25.6,36.1361538 L25.6,37.5576923 C25.6,40.0106538 23.624,42 21.2056,42 L18.7944,42 C17.6280922,41.9995719 16.5097569,41.5312264 15.685578,40.6980623 C14.8613991,39.8648982 14.3989387,38.7352142 14.4,37.5576923 L14.4,36.1361538 C12.7368384,35.508049 11.1889728,34.6045208 9.82,33.4626923 L8.5976,34.1750769 C6.49470875,35.3989852 3.80739703,34.6739127 2.5896,32.5540385 L1.384,30.4459615 C0.8012569,29.4259536 0.643880418,28.2139502 0.946514692,27.0767561 C1.24914897,25.939562 1.98698538,24.9703994 2.9976,24.3826154 L4.2176,23.6710385 C4.07240963,22.7882521 3.99962928,21.8948738 4,21 C4,20.0897308 4.0744,19.1980385 4.2176,18.3289615 L2.9976,17.6181923 C0.895969702,16.3914943 0.174180473,13.6789008 1.384,11.5540385 L2.5896,9.44596154 C3.17313247,8.42634297 4.13409345,7.682653 5.260921,7.37861991 C6.38774855,7.07458682 7.58806043,7.23513658 8.5976,7.82492308 L9.82,8.53730769 Z"/>
- <path fill="#FEE1D3" d="M14.0000007,5.6038043 L14.0000013,4.44005609 C14.0029906,1.78475013 16.1390906,-0.376211234 18.7944,-0.384615385 L21.2056,-0.384615385 C23.8595941,-0.384615385 26,1.78021801 26,4.44230769 L26,5.60295806 C27.5208716,6.20655954 28.9434678,7.03621848 30.2204219,8.06411282 L31.1970056,7.49492104 C33.4941909,6.15907529 36.4301298,6.95005805 37.7609369,9.26076474 L38.9671983,11.3699991 C39.5988409,12.4761812 39.768854,13.7886936 39.4405746,15.0202941 C39.1116282,16.2543969 38.308799,17.3078735 37.2096539,17.946304 L36.2175721,18.5246428 C36.3390841,19.3401617 36.4,20.1667594 36.4,21 C36.4,21.8329668 36.339124,22.6588262 36.2175401,23.4753391 L37.2113882,24.0547082 C39.4944154,25.3886826 40.276605,28.3232105 38.9665369,30.6311583 L37.7604568,32.7400742 C37.1252608,33.8495148 36.0768547,34.6604208 34.8452776,34.9922248 C33.6111681,35.324711 32.2964469,35.1482289 31.195569,34.5042428 L30.2192355,33.9354047 C28.9426535,34.9630196 27.5206806,35.7924453 25.9999993,36.3961957 L25.9999987,37.5599439 C25.9970094,40.2152499 23.8609094,42.3762112 21.2056,42.3846154 L18.7944,42.3846154 C16.1404059,42.3846154 14,40.219782 14,37.5576923 L14,36.3970419 C12.4791284,35.7934405 11.0565322,34.9637815 9.77957815,33.9358872 L8.80299442,34.505079 C6.50580915,35.8409247 3.56987021,35.049942 2.23906313,32.7392353 L1.03280169,30.6300009 C0.401159146,29.5238188 0.231145999,28.2113064 0.559425405,26.9797059 C0.888371786,25.7456031 1.69120101,24.6921265 2.79034606,24.053696 L3.78242779,23.4753573 C3.66091587,22.6598457 3.60000002,21.8333228 3.60000019,21.0008678 C3.59964068,20.1722851 3.66061719,19.3449468 3.78254167,18.5247085 L2.78861183,17.9452918 C0.505584602,16.6113174 -0.276605002,13.6767895 1.03346313,11.3688417 L2.23954317,9.25992583 C2.87473915,8.15048519 3.92314533,7.33957919 5.15472238,7.00777521 C6.38883187,6.67528896 7.70355311,6.85177112 8.80443097,7.49575721 L9.78076186,8.06459377 C11.0573465,7.03698045 12.4793194,6.20755475 14.0000007,5.6038043 Z M11.2634746,12.0326234 C10.617233,12.5716613 9.7026973,12.6485026 8.97556903,12.2248582 L6.78774825,10.9501716 C6.60754053,10.8447551 6.39506809,10.8162338 6.19527576,10.8700606 C5.99295099,10.9245697 5.8183659,11.0596053 5.71133687,11.246543 L4.50892658,13.3490215 C4.28085652,13.7508163 4.41776119,14.2644394 4.80485394,14.4906191 L6.98565394,15.7619268 C7.70254629,16.1798426 8.08690703,16.9970357 7.95165511,17.8157512 L7.76948523,18.9184706 C7.65638664,19.6061109 7.59969735,20.3020342 7.6,21 C7.6,21.7031066 7.65662064,22.3978283 7.76925511,23.0801334 L7.95165511,24.1842488 C8.08690703,25.0029643 7.70254629,25.8201574 6.98565394,26.2380732 L4.80213007,27.5109659 C4.61772321,27.6180778 4.48116147,27.7972748 4.42448029,28.0099246 C4.36713215,28.2250767 4.39688141,28.454743 4.50573687,28.6453801 L5.70831165,30.7481858 C5.93243371,31.1373303 6.41410538,31.2670993 6.79049373,31.0482253 L8.97449373,29.7753023 C9.7016554,29.3514832 10.6163433,29.4282639 11.2626746,29.9673766 L12.1188867,30.6815536 C13.1796505,31.566598 14.3786867,32.2666727 15.6649769,32.7525215 L16.7049769,33.1442523 C17.4841581,33.4377419 18,34.1832625 18,35.0158846 L18,37.5576923 C18,38.02074 18.3597694,38.3846154 18.7944,38.3846154 L21.1992624,38.3846254 C21.6372484,38.3832375 21.9994819,38.0167881 22,37.5576923 L22,35.0158846 C22,34.18376 22.5152346,33.4385758 23.2937506,33.1447321 L24.3331012,32.7524389 C25.620867,32.2658727 26.8196661,31.5658006 27.8813806,30.679856 L28.7373806,29.9666637 C29.3836087,29.4282468 30.2976553,29.3517028 31.024431,29.7751418 L33.2122517,31.0498284 C33.3924595,31.1552449 33.6049319,31.1837662 33.8047242,31.1299394 C34.007049,31.0754303 34.1816341,30.9403947 34.2886631,30.753457 L35.4910734,28.6509785 C35.7191435,28.2491837 35.5822388,27.7355606 35.1951461,27.5093809 L33.0143461,26.2380732 C32.2974537,25.8201574 31.913093,25.0029643 32.0483449,24.1842488 L32.2306531,23.0806893 C32.3434217,22.3968737 32.4,21.7028459 32.4,21 C32.4,20.2968934 32.3433794,19.6021717 32.2307449,18.9198666 L32.0483449,17.8157512 C31.913093,16.9970357 32.2974537,16.1798426 33.0143461,15.7619268 L35.1978699,14.4890341 C35.3822768,14.3819222 35.5188385,14.2027252 35.5755197,13.9900754 C35.6328679,13.7749233 35.6031186,13.545257 35.4942631,13.3546199 L34.2916883,11.2518142 C34.0675663,10.8626697 33.5858946,10.7329007 33.2095063,10.9517747 L31.0255063,12.2246977 C30.2983446,12.6485168 29.3836567,12.5717361 28.7373254,12.0326234 L27.8811133,11.3184464 C26.8203495,10.433402 25.6213133,9.73332732 24.3362966,9.24795765 L23.2962966,8.85703457 C22.5164499,8.56389992 22,7.81804293 22,6.98492308 L22,4.44230769 C22,3.97925995 21.6402306,3.61538462 21.2056,3.61538462 L18.8007376,3.61537457 C18.3627516,3.61676247 18.0005181,3.98321188 18,4.44230769 L18,6.98411538 C18,7.81623999 17.4847654,8.56142419 16.7062494,8.85526793 L15.6668988,9.24756113 C14.379133,9.73412728 13.1803339,10.4341994 12.1197785,11.3191775 C12.1108094,11.3266617 11.8253748,11.564477 11.2634746,12.0326234 Z"/>
- <g transform="rotate(15 -47.892 66.043)">
- <ellipse cx="6.4" cy="6.462" fill="#FFFFFF" rx="6.4" ry="6.462" transform="translate(.028 4.853)"/>
- <path fill="#FC6D26" d="M5.92153903,11.9125743 C2.3834711,11.9125743 -0.478460969,9.0231237 -0.478460969,5.4664205 C-0.478460969,1.9097173 2.3834711,-0.979733345 5.92153903,-0.979733345 C9.45960696,-0.979733345 12.321539,1.9097173 12.321539,5.4664205 C12.321539,9.0231237 9.45960696,11.9125743 5.92153903,11.9125743 Z M5.92153903,8.71257435 C7.6854047,8.71257435 9.12153903,7.26263103 9.12153903,5.4664205 C9.12153903,3.67020997 7.6854047,2.22026666 5.92153903,2.22026666 C4.15767337,2.22026666 2.72153903,3.67020997 2.72153903,5.4664205 C2.72153903,7.26263103 4.15767337,8.71257435 5.92153903,8.71257435 Z"/>
- </g>
- </g>
- <path fill="#000000" fill-opacity=".03" d="M61.6792606,38.251778 C61.8904713,36.8653316 62,35.4454567 62,34 C62,18.536027 49.463973,6 34,6 C18.536027,6 6,18.536027 6,34 C6,49.463973 18.536027,62 34,62 C42.8132237,62 50.6754255,57.9281916 55.8080076,51.5631726 L64.2689981,50.6250607 C64.4699867,50.6027761 64.6664333,50.5501384 64.8516368,50.4689431 C65.8632575,50.0254374 66.3238058,48.8458244 65.8803001,47.8342037 L65.8803001,47.8342037 L61.6792599,38.2517794 Z"/>
- <path fill="#FFFFFF" d="M63.6792606,34.251778 C63.8904713,32.8653316 64,31.4454567 64,30 C64,14.536027 51.463973,2 36,2 C20.536027,2 8,14.536027 8,30 C8,45.463973 20.536027,58 36,58 C44.8132237,58 52.6754255,53.9281916 57.8080076,47.5631726 L66.2689981,46.6250607 C66.4699867,46.6027761 66.6664333,46.5501384 66.8516368,46.4689431 C67.8632575,46.0254374 68.3238058,44.8458244 67.8803001,43.8342037 L67.8803001,43.8342037 L63.6792599,34.2517794 Z"/>
- <path fill="#EEEEEE" fill-rule="nonzero" d="M69.7120015,43.0311656 C70.5990128,45.0544071 69.6779163,47.4136331 67.6546748,48.3006445 C67.2842678,48.463035 66.8913746,48.5683104 66.4893975,48.6128796 L58.8313193,49.4619687 C53.1777737,56.0908093 44.9077957,60 36,60 C19.4314575,60 6,46.5685425 6,30 C6,13.4314575 19.4314575,0 36,0 C52.5685425,0 66,13.4314575 66,30 C66,31.335699 65.9125851,32.6609639 65.739427,33.9698636 L69.7120015,43.0311656 Z M61.7020717,33.9505738 C61.8999153,32.6518726 62,31.332589 62,30 C62,15.6405965 50.3594035,4 36,4 C21.6405965,4 10,15.6405965 10,30 C10,44.3594035 21.6405965,56 36,56 C43.969518,56 51.3430155,52.3943837 56.251122,46.3077415 L56.7684631,45.6661764 L66.0485988,44.6372417 L61.8475593,35.054816 L61.6147491,34.5237842 L61.7020717,33.9505738 Z"/>
- <g fill="#31AF64" fill-rule="nonzero" transform="translate(24 18)">
- <path d="M12.5,26.5 C4.7680135,26.5 -1.5,20.2319865 -1.5,12.5 C-1.5,4.7680135 4.7680135,-1.5 12.5,-1.5 C20.2319865,-1.5 26.5,4.7680135 26.5,12.5 C26.5,20.2319865 20.2319865,26.5 12.5,26.5 Z M12.5,23.5 C18.5751322,23.5 23.5,18.5751322 23.5,12.5 C23.5,6.42486775 18.5751322,1.5 12.5,1.5 C6.42486775,1.5 1.5,6.42486775 1.5,12.5 C1.5,18.5751322 6.42486775,23.5 12.5,23.5 Z"/>
- <path d="M11.18,13.81 L9.248,11.878 C8.67483243,11.3054203 7.74616757,11.3054203 7.173,11.878 C6.89709997,12.1525667 6.74198837,12.5257601 6.74198837,12.915 C6.74198837,13.3042399 6.89709997,13.6774333 7.173,13.952 L10.048,16.826 C10.0636337,16.8423622 10.0796378,16.8583663 10.096,16.874 C10.646,17.424 11.526,17.423 12.071,16.879 L17.879,11.071 C18.1403709,10.8085057 18.2866977,10.4528922 18.2857599,10.0824639 C18.2848221,9.71203558 18.1366966,9.35716757 17.874,9.096 C17.6132271,8.83256594 17.2582132,8.68392968 16.8875393,8.68299126 C16.5168653,8.68205285 16.1611034,8.82888967 15.899,9.091 L11.18,13.81 Z"/>
- </g>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_icon_calendar.svg b/app/views/shared/icons/_icon_calendar.svg
deleted file mode 100644
index 4d0a703f9a0..00000000000
--- a/app/views/shared/icons/_icon_calendar.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M15 5v7a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V5a2 2 0 0 1 2-2h1V2a1 1 0 1 1 2 0v1h4V2a1 1 0 1 1 2 0v1h1a2 2 0 0 1 2 2zM3 6v6a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V6H3zm2 2h2a1 1 0 1 1 0 2H5a1 1 0 1 1 0-2z" fill="#000" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_icon_check_square_o.svg b/app/views/shared/icons/_icon_check_square_o.svg
deleted file mode 100644
index 05ed4d715d5..00000000000
--- a/app/views/shared/icons/_icon_check_square_o.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_clock_o.svg b/app/views/shared/icons/_icon_clock_o.svg
deleted file mode 100644
index 9787ff6cb9e..00000000000
--- a/app/views/shared/icons/_icon_clock_o.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1c.552 0 1 .448 1 1s-.448 1-1 1H8c-.276 0-.526-.112-.707-.293S7 8.277 7 8V5c0-.552.448-1 1-1s1 .448 1 1zm-1 9c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
diff --git a/app/views/shared/icons/_icon_clone.svg b/app/views/shared/icons/_icon_clone.svg
deleted file mode 100644
index faba51b5797..00000000000
--- a/app/views/shared/icons/_icon_clone.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_close.svg b/app/views/shared/icons/_icon_close.svg
deleted file mode 100644
index 59a6cb32d18..00000000000
--- a/app/views/shared/icons/_icon_close.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15"><path d="M9,7.5l5.83-5.91a.48.48,0,0,0,0-.69L14.11.15a.46.46,0,0,0-.68,0l-5.93,6L1.57.15a.46.46,0,0,0-.68,0L.15.9a.48.48,0,0,0,0,.69L6,7.5.15,13.41a.48.48,0,0,0,0,.69l.74.75a.46.46,0,0,0,.68,0l5.93-6,5.93,6a.46.46,0,0,0,.68,0l.74-.75a.48.48,0,0,0,0-.69Z"/></svg>
diff --git a/app/views/shared/icons/_icon_code_fork.svg b/app/views/shared/icons/_icon_code_fork.svg
deleted file mode 100644
index 968e0ad3b2b..00000000000
--- a/app/views/shared/icons/_icon_code_fork.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_comment_o.svg b/app/views/shared/icons/_icon_comment_o.svg
deleted file mode 100644
index 050d7356f54..00000000000
--- a/app/views/shared/icons/_icon_comment_o.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.707 15.707c-.63.63-1.707.184-1.707-.707v-12a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1 -3 3h-7.586zm.293-3.121 2.293-2.293a1 1 0 0 1 .707-.293h8a1 1 0 0 0 1-1v-6a1 1 0 0 0 -1-1h-10a1 1 0 0 0 -1 1z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_customization.svg b/app/views/shared/icons/_icon_customization.svg
deleted file mode 100644
index eb1f8ba129b..00000000000
--- a/app/views/shared/icons/_icon_customization.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 112 90" xmlns:xlink="http://www.w3.org/1999/xlink"><g fill="none" fill-rule="evenodd"><rect width="112" height="90" fill="#fff" rx="6"/><path fill="#eee" fill-rule="nonzero" d="m4 6.01v77.98c0 1.11.899 2.01 2 2.01h100c1.105 0 2-.898 2-2.01v-77.98c0-1.11-.899-2.01-2-2.01h-100c-1.105 0-2 .898-2 2.01m-4 0c0-3.319 2.686-6.01 6-6.01h100c3.315 0 6 2.694 6 6.01v77.98c0 3.319-2.686 6.01-6 6.01h-100c-3.315 0-6-2.694-6-6.01v-77.98"/><g transform="translate(26 35)"><rect width="4" height="39" x="5" fill="#eee" rx="2" id="0"/><rect width="4" height="21" x="5" y="18" fill="#fef0ea" rx="2"/><circle cx="7" cy="13" r="5" fill="#fff"/><path fill="#fb722e" fill-rule="nonzero" d="m7 20c-3.866 0-7-3.134-7-7 0-3.866 3.134-7 7-7 3.866 0 7 3.134 7 7 0 3.866-3.134 7-7 7m0-4c1.657 0 3-1.343 3-3 0-1.657-1.343-3-3-3-1.657 0-3 1.343-3 3 0 1.657 1.343 3 3 3"/></g><g transform="translate(49 35)"><use xlink:href="#0"/><rect width="4" height="21" x="5" y="18" fill="#b5a7dd" rx="2"/><circle cx="7" cy="25" r="5" fill="#fff"/><path fill="#6b4fbb" fill-rule="nonzero" d="m7 32c-3.866 0-7-3.134-7-7 0-3.866 3.134-7 7-7 3.866 0 7 3.134 7 7 0 3.866-3.134 7-7 7m0-4c1.657 0 3-1.343 3-3 0-1.657-1.343-3-3-3-1.657 0-3 1.343-3 3 0 1.657 1.343 3 3 3"/></g><g transform="translate(72 33)"><rect width="4" height="39" x="5" y="2" fill="#eee" rx="2"/><rect width="4" height="34" x="5" y="7" fill="#fef0ea" rx="2"/><circle cx="7" cy="7" r="5" fill="#fff"/><path fill="#fb722e" fill-rule="nonzero" d="m7 14c-3.866 0-7-3.134-7-7 0-3.866 3.134-7 7-7 3.866 0 7 3.134 7 7 0 3.866-3.134 7-7 7m0-4c1.657 0 3-1.343 3-3 0-1.657-1.343-3-3-3-1.657 0-3 1.343-3 3 0 1.657 1.343 3 3 3"/></g><g fill="#6b4fbb"><circle cx="13.5" cy="11.5" r="2.5"/><circle cx="23.5" cy="11.5" r="2.5" opacity=".5"/><circle cx="33.5" cy="11.5" r="2.5" opacity=".5"/></g><path fill="#eee" d="m0 19h111v4h-111z"/></g></svg>
diff --git a/app/views/shared/icons/_icon_cycle_analytics_overview.svg b/app/views/shared/icons/_icon_cycle_analytics_overview.svg
deleted file mode 100644
index eea9c975c35..00000000000
--- a/app/views/shared/icons/_icon_cycle_analytics_overview.svg
+++ /dev/null
@@ -1,81 +0,0 @@
-<svg width="366px" height="229px" viewBox="784 258 366 229" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
- <desc>Created with Sketch.</desc>
- <defs>
- <rect id="path-1" x="35" y="39" width="24" height="21" rx="10"></rect>
- <mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="24" height="21" fill="white">
- <use xlink:href="#path-1"></use>
- </mask>
- <rect id="path-3" x="64.8662386" y="58.3882666" width="10" height="71" rx="5"></rect>
- <mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="10" height="71" fill="white">
- <use xlink:href="#path-3"></use>
- </mask>
- <rect id="path-5" x="18.1550472" y="58.3882666" width="10" height="71" rx="5"></rect>
- <mask id="mask-6" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="10" height="71" fill="white">
- <use xlink:href="#path-5"></use>
- </mask>
- <rect id="path-7" x="24" y="56" width="46" height="10" rx="5"></rect>
- <mask id="mask-8" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="46" height="10" fill="white">
- <use xlink:href="#path-7"></use>
- </mask>
- <rect id="path-9" x="42" y="60" width="10" height="68" rx="5"></rect>
- <mask id="mask-10" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="10" height="68" fill="white">
- <use xlink:href="#path-9"></use>
- </mask>
- <rect id="path-11" x="69" y="12" width="12" height="12" rx="3"></rect>
- <mask id="mask-12" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="12" height="12" fill="white">
- <use xlink:href="#path-11"></use>
- </mask>
- <rect id="path-13" x="40" y="18" width="14" height="22" rx="6"></rect>
- <mask id="mask-14" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="14" height="22" fill="white">
- <use xlink:href="#path-13"></use>
- </mask>
- <rect id="path-15" x="41" y="8" width="34" height="20" rx="3"></rect>
- <mask id="mask-16" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="34" height="20" fill="white">
- <use xlink:href="#path-15"></use>
- </mask>
- <path d="M8,8.00793008 C8,6.34669617 9.34984627,5.0321392 11.0036812,5.07151622 L46.9963188,5.92848378 C48.6552061,5.9679811 50,7.34177063 50,8.99109042 L50,27.0089096 C50,28.6608432 48.6501537,30.0321392 46.9963188,30.0715162 L11.0036812,30.9284838 C9.34479389,30.9679811 8,29.6568766 8,27.9920699 L8,8.00793008 Z" id="path-17"></path>
- <mask id="mask-18" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="42" height="25.858699" fill="white">
- <use xlink:href="#path-17"></use>
- </mask>
- <rect id="path-19" x="-7.10542736e-15" y="1.77635684e-14" width="16" height="36" rx="3"></rect>
- <mask id="mask-20" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="16" height="36" fill="white">
- <use xlink:href="#path-19"></use>
- </mask>
- </defs>
- <g id="Group-7" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(786.000000, 259.000000)">
- <g id="Group-5" transform="translate(132.727922, 71.000000)">
- <use id="Rectangle-21" stroke="#EEEEEE" mask="url(#mask-2)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-1"></use>
- <use id="Rectangle-16-Copy" stroke="#EEEEEE" mask="url(#mask-4)" stroke-width="8" fill="#FFFFFF" transform="translate(69.866239, 93.888267) rotate(-20.000000) translate(-69.866239, -93.888267) " xlink:href="#path-3"></use>
- <use id="Rectangle-16-Copy-2" stroke="#EEEEEE" mask="url(#mask-6)" stroke-width="8" fill="#FFFFFF" transform="translate(23.155047, 93.888267) scale(-1, 1) rotate(-20.000000) translate(-23.155047, -93.888267) " xlink:href="#path-5"></use>
- <use id="Rectangle-15" stroke="#EEEEEE" mask="url(#mask-8)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-7"></use>
- <use id="Rectangle-16" stroke="#EEEEEE" mask="url(#mask-10)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-9"></use>
- <g id="Group" transform="translate(45.500000, 33.000000) rotate(20.000000) translate(-45.500000, -33.000000) translate(5.000000, 13.000000)">
- <use id="Rectangle-4" stroke="#EEEEEE" mask="url(#mask-12)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-11"></use>
- <use id="Rectangle-20" stroke="#EEEEEE" mask="url(#mask-14)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-13"></use>
- <use id="Rectangle-2" stroke="#EEEEEE" mask="url(#mask-16)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-15"></use>
- <use id="Rectangle" stroke="#EEEEEE" mask="url(#mask-18)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-17"></use>
- <rect id="Rectangle-17" fill="#EEEEEE" x="21" y="7" width="3" height="22"></rect>
- <rect id="Rectangle-17-Copy" fill="#EEEEEE" x="64" y="8" width="3" height="17"></rect>
- <circle id="Oval-9" fill="#B5A7DD" cx="40" cy="18" r="2"></circle>
- <circle id="Oval-9-Copy-4" fill="#EEEEEE" cx="47" cy="33" r="2"></circle>
- <use id="Rectangle-19" stroke="#EEEEEE" mask="url(#mask-20)" stroke-width="8" fill="#FFFFFF" xlink:href="#path-19"></use>
- </g>
- </g>
- <path d="M265.128496,225.286991 C247.289192,194.617726 214.068171,174 176.031622,174 C137.847583,174 104.51649,194.77793 86.7279221,225.644211" id="Oval-10" stroke="#EEEEEE" stroke-width="4" stroke-linecap="round" fill="#FFFFFF"></path>
- <circle id="Oval-11" stroke="#FDE5D8" stroke-width="4" fill="#FFFFFF" cx="24.5" cy="25.5" r="24.5"></circle>
- <path d="M24,1.00292933 C24,0.449026756 24.4438648,0 25,0 C25.5522847,0 26,0.437881351 26,1.00292933 L26,5.99707067 C26,6.55097324 25.5561352,7 25,7 C24.4477153,7 24,6.56211865 24,5.99707067 L24,1.00292933 Z M48.46461,17.3244238 C48.9914026,17.1532585 49.5556142,17.4366422 49.7274694,17.9655581 C49.8981348,18.4908122 49.6200365,19.0519274 49.0826439,19.2265369 L44.3329333,20.7698114 C43.8061406,20.9409767 43.241929,20.6575931 43.0700738,20.1286771 C42.8994084,19.6034231 43.1775067,19.0423078 43.7148993,18.8676984 L48.46461,17.3244238 Z M40.5019265,45.6352697 C40.8275022,46.0833863 40.7323394,46.7075538 40.2824166,47.0344419 C39.8356088,47.3590667 39.2160194,47.2679737 38.8838925,46.8108402 L35.9484099,42.770495 C35.6228341,42.3223784 35.717997,41.6982109 36.1679198,41.3713229 C36.6147275,41.0466981 37.234317,41.1377911 37.5664439,41.5949245 L40.5019265,45.6352697 Z M11.1161075,46.8108402 C10.7905317,47.2589568 10.1675063,47.3613299 9.71758344,47.0344419 C9.27077569,46.709817 9.16594665,46.0924031 9.49807352,45.6352697 L12.4335561,41.5949245 C12.7591319,41.1468079 13.3821574,41.0444348 13.8320802,41.3713229 C14.278888,41.6959477 14.383717,42.3133616 14.0515901,42.770495 L11.1161075,46.8108402 Z M0.917356057,19.2265369 C0.390563404,19.0553716 0.100675355,18.4944741 0.272530576,17.9655581 C0.44319595,17.4403041 0.997997482,17.1498144 1.53539005,17.3244238 L6.28510071,18.8676984 C6.81189336,19.0388637 7.10178141,19.5997611 6.92992619,20.1286771 C6.75926082,20.6539311 6.20445928,20.9444208 5.66706672,20.7698114 L0.917356057,19.2265369 Z" id="Rectangle-23" fill="#FDE5D8"></path>
- <rect id="Rectangle-18" fill="#FC6D26" x="24" y="14" width="3" height="12" rx="1.5"></rect>
- <rect id="Rectangle-22" fill="#FC6D26" x="24" y="24" width="12" height="3" rx="1.5"></rect>
- <circle id="Oval-11" fill="#6B4FBB" cx="25.5" cy="25.5" r="2.5"></circle>
- <path d="M358.949747,6.87474747 L357.453009,7.20729654 C356.9128,7.32732164 356.570654,6.9935311 356.692198,6.44648557 L357.024747,4.94974747 L356.692198,3.45300937 C356.572173,2.91279997 356.905964,2.57065443 357.453009,2.69219839 L358.949747,3.02474747 L360.446486,2.69219839 C360.986695,2.5721733 361.328841,2.90596384 361.207297,3.45300937 L360.874747,4.94974747 L361.207297,6.44648557 C361.327322,6.98669496 360.993531,7.32884051 360.446486,7.20729654 L358.949747,6.87474747 Z" id="Star-Copy-5" fill="#6B4FBB" transform="translate(358.949747, 4.949747) rotate(-315.000000) translate(-358.949747, -4.949747) "></path>
- <path d="M113.949747,32.8747475 L112.453009,33.2072965 C111.9128,33.3273216 111.570654,32.9935311 111.692198,32.4464856 L112.024747,30.9497475 L111.692198,29.4530094 C111.572173,28.9128 111.905964,28.5706544 112.453009,28.6921984 L113.949747,29.0247475 L115.446486,28.6921984 C115.986695,28.5721733 116.328841,28.9059638 116.207297,29.4530094 L115.874747,30.9497475 L116.207297,32.4464856 C116.327322,32.986695 115.993531,33.3288405 115.446486,33.2072965 L113.949747,32.8747475 Z" id="Star-Copy-7" fill="#B5A7DD" transform="translate(113.949747, 30.949747) rotate(-315.000000) translate(-113.949747, -30.949747) "></path>
- <path d="M329.949747,211.874747 L328.453009,212.207297 C327.9128,212.327322 327.570654,211.993531 327.692198,211.446486 L328.024747,209.949747 L327.692198,208.453009 C327.572173,207.9128 327.905964,207.570654 328.453009,207.692198 L329.949747,208.024747 L331.446486,207.692198 C331.986695,207.572173 332.328841,207.905964 332.207297,208.453009 L331.874747,209.949747 L332.207297,211.446486 C332.327322,211.986695 331.993531,212.328841 331.446486,212.207297 L329.949747,211.874747 Z" id="Star-Copy-6" fill="#B5A7DD" opacity="0.5" transform="translate(329.949747, 209.949747) rotate(-315.000000) translate(-329.949747, -209.949747) "></path>
- <path d="M265.363961,54.838961 L263.153969,55.3299826 C262.617155,55.4492534 262.280283,55.1035008 262.397939,54.5739526 L262.888961,52.363961 L262.397939,50.1539694 C262.278669,49.6171548 262.624421,49.2802831 263.153969,49.3979395 L265.363961,49.888961 L267.573953,49.3979395 C268.110767,49.2786686 268.447639,49.6244213 268.329983,50.1539694 L267.838961,52.363961 L268.329983,54.5739526 C268.449253,55.1107673 268.103501,55.4476389 267.573953,55.3299826 L265.363961,54.838961 Z" id="Star-Copy-9" fill="#FC6D26" transform="translate(265.363961, 52.363961) rotate(-315.000000) translate(-265.363961, -52.363961) "></path>
- <path d="M56.363961,142.838961 L54.1539694,143.329983 C53.6171548,143.449253 53.2802831,143.103501 53.3979395,142.573953 L53.888961,140.363961 L53.3979395,138.153969 C53.2786686,137.617155 53.6244213,137.280283 54.1539694,137.397939 L56.363961,137.888961 L58.5739526,137.397939 C59.1107673,137.278669 59.4476389,137.624421 59.3299826,138.153969 L58.838961,140.363961 L59.3299826,142.573953 C59.4492534,143.110767 59.1035008,143.447639 58.5739526,143.329983 L56.363961,142.838961 Z" id="Star-Copy-8" fill="#6B4FBB" transform="translate(56.363961, 140.363961) rotate(-315.000000) translate(-56.363961, -140.363961) "></path>
- <g id="Group-6" transform="translate(311.872633, 125.094458) rotate(-345.000000) translate(-311.872633, -125.094458) translate(290.872633, 115.094458)">
- <circle id="Oval-12" stroke="#FDE5D8" stroke-width="4" fill="#FFFFFF" cx="21" cy="10" r="10"></circle>
- <ellipse id="Oval-13" fill="#FDE5D8" cx="21" cy="10" rx="21" ry="2"></ellipse>
- </g>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_icon_cycle_analytics_splash.svg b/app/views/shared/icons/_icon_cycle_analytics_splash.svg
deleted file mode 100644
index eb5a962d651..00000000000
--- a/app/views/shared/icons/_icon_cycle_analytics_splash.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 99 102" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="0" d="m35.12 56.988c4.083-4.385 5.968-12.155 5.968-24.04 0-20.2-15.874-32.16-15.874-32.16-1.114-.954-2.929-.979-4.04 0 0 0-15.874 11.957-15.874 32.16 0 11.882 1.884 19.652 5.968 24.04h23.848"/><mask id="1" width="35.783" height="56.924" x="0" y="0" fill="#fff"><use xlink:href="#0"/></mask></defs><g fill="none" fill-rule="evenodd" transform="translate(0-4)"><g transform="translate(32.15 3.976)"><g fill="#6b4fbb"><path d="m11.928 56.988l1.325-1.325v3.313c0 .737.59 1.325 1.325 1.325h17.229c.736 0 1.325-.59 1.325-1.325v-3.313l1.325 1.325h-22.53m22.53-1.325v3.313c0 1.464-1.18 2.651-2.651 2.651h-17.229c-1.464 0-2.651-1.178-2.651-2.651v-3.313h22.53m-5.964 7.361h.663c0 3.294-2.67 5.964-5.964 5.964-3.294 0-5.964-2.67-5.964-5.964h.663.663c0 2.562 2.077 4.639 4.639 4.639 2.562 0 4.639-2.077 4.639-4.639h.663"/><path d="m5.816 42.535c-.346-2.839-.515-6.03-.515-9.584 0-20.2 15.874-32.16 15.874-32.16 1.106-.979 2.921-.954 4.04 0 0 0 15.874 11.957 15.874 32.16 0 11.882-1.884 19.652-5.968 24.04h-23.848c-2.861-3.073-4.643-7.807-5.453-14.453-.06-.493-.115-.997-.164-1.511l-4.04 2.884c-.891.637-1.614 2.041-1.614 3.137v14.581c0 1.465.971 1.958 2.165 1.106l8.691-6.208c-.282-.332-.553-.681-.813-1.048l-8.648 6.177c-.147.105-.069.152-.069-.027v-14.581c0-.668.516-1.671 1.059-2.059l3.432-2.451m38.4 20.2c1.193.852 2.165.359 2.165-1.106v-14.581c0-1.096-.723-2.5-1.614-3.137l-4.04-2.884c-.049.514-.104 1.018-.164 1.511l3.432 2.451c.543.388 1.059 1.391 1.059 2.059v14.581c0 .179.078.132-.069.027l-8.648-6.177c-.26.367-.531.716-.813 1.048l8.691 6.208"/></g><use fill="#fff" stroke="#6b4fbb" stroke-width="2.651" mask="url(#1)" xlink:href="#0"/><g fill="#b5a7dd"><path d="m30.482 28.494c0-4.03-3.263-7.289-7.289-7.289-4.03 0-7.289 3.263-7.289 7.289 0 4.03 3.263 7.289 7.289 7.289 4.03 0 7.289-3.263 7.289-7.289m-15.904 0c0-4.758 3.857-8.614 8.614-8.614 4.758 0 8.614 3.857 8.614 8.614 0 4.758-3.857 8.614-8.614 8.614-4.758 0-8.614-3.857-8.614-8.614"/><path d="m27.17 28.494c0-2.196-1.78-3.976-3.976-3.976-2.196 0-3.976 1.78-3.976 3.976 0 2.196 1.78 3.976 3.976 3.976 2.196 0 3.976-1.78 3.976-3.976m-9.277 0c0-2.928 2.373-5.301 5.301-5.301 2.928 0 5.301 2.373 5.301 5.301 0 2.928-2.373 5.301-5.301 5.301-2.928 0-5.301-2.373-5.301-5.301"/></g><path fill="#6b4fbb" d="m34.458 87.47c0 1.098.89 1.988 1.988 1.988 1.098 0 1.988-.89 1.988-1.988 0-.366.297-.663.663-.663.366 0 .663.297.663.663 0 1.83-1.483 3.313-3.313 3.313-1.826 0-3.307-1.478-3.313-3.302 0-.002 0-.003 0-.005v-2.663c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.657m-21.2-6.615c0-.002 0-.003 0-.005v-2.663c0-.358-.297-.657-.663-.657-.369 0-.663.294-.663.657v2.657c0 1.098-.89 1.988-1.988 1.988-1.098 0-1.988-.89-1.988-1.988 0-.366-.297-.663-.663-.663-.366 0-.663.297-.663.663 0 1.83 1.483 3.313 3.313 3.313 1.826 0 3.307-1.477 3.313-3.302m5.301 7.285c0-.001 0-.002 0-.003v-16.576c0-.362-.297-.658-.663-.658-.369 0-.663.295-.663.658v16.571c0 2.01-1.632 3.645-3.645 3.645-2.01 0-3.645-1.632-3.645-3.645 0-.366-.297-.663-.663-.663-.366 0-.663.297-.663.663 0 2.745 2.225 4.97 4.97 4.97 2.742 0 4.966-2.221 4.97-4.963m10.602 8.607v-18.555c0-.365-.297-.661-.663-.661-.369 0-.663.296-.663.661v18.557c0 0 0 0 0 .001.001 2.744 2.226 4.968 4.97 4.968 2.745 0 4.97-2.225 4.97-4.97 0-.366-.297-.663-.663-.663-.366 0-.663.297-.663.663 0 2.01-1.632 3.645-3.645 3.645-2.01 0-3.645-1.632-3.645-3.645m3.976-25.19c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663m0 6.627c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663m-10.602-6.627c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663m5.301 0c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663m-5.301 6.627c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663m0 6.627c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663m-10.602-13.253c0-.363.294-.657.663-.657.366 0 .663.299.663.657v2.663c0 .363-.294.657-.663.657-.366 0-.663-.299-.663-.657v-2.663"/></g><path fill="#e2ddf2" d="m97.75 76.54c0-2.745-2.225-4.97-4.97-4.97-2.745 0-4.97 2.225-4.97 4.97 0 2.745 2.225 4.97 4.97 4.97 2.745 0 4.97-2.225 4.97-4.97m-8.614 0c0-2.01 1.632-3.645 3.645-3.645 2.01 0 3.645 1.632 3.645 3.645 0 2.01-1.632 3.645-3.645 3.645-2.01 0-3.645-1.632-3.645-3.645m-60.964-57.651c0-2.745-2.225-4.97-4.97-4.97-2.745 0-4.97 2.225-4.97 4.97 0 2.745 2.225 4.97 4.97 4.97 2.745 0 4.97-2.225 4.97-4.97m-8.614 0c0-2.01 1.632-3.645 3.645-3.645 2.01 0 3.645 1.632 3.645 3.645 0 2.01-1.632 3.645-3.645 3.645-2.01 0-3.645-1.632-3.645-3.645"/><path fill="#b5a7dd" d="m98.41 34.458c0-1.83-1.483-3.313-3.313-3.313-1.83 0-3.313 1.483-3.313 3.313 0 1.83 1.483 3.313 3.313 3.313 1.83 0 3.313-1.483 3.313-3.313m-5.301 0c0-1.098.89-1.988 1.988-1.988 1.098 0 1.988.89 1.988 1.988 0 1.098-.89 1.988-1.988 1.988-1.098 0-1.988-.89-1.988-1.988m-86.14 20.542c0-1.83-1.483-3.313-3.313-3.313-1.83 0-3.313 1.483-3.313 3.313 0 1.83 1.483 3.313 3.313 3.313 1.83 0 3.313-1.483 3.313-3.313m-5.301 0c0-1.098.89-1.988 1.988-1.988 1.098 0 1.988.89 1.988 1.988 0 1.098-.89 1.988-1.988 1.988-1.098 0-1.988-.89-1.988-1.988"/></g></svg>
diff --git a/app/views/shared/icons/_icon_edit.svg b/app/views/shared/icons/_icon_edit.svg
deleted file mode 100644
index 1c10ef138b5..00000000000
--- a/app/views/shared/icons/_icon_edit.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.436 1.413 1.415 1.414a1 1 0 0 1 0 1.414l-10.316 10.315a1 1 0 0 1 -.703.293l-2.407.008-.008-2.421a1 1 0 0 1 .293-.71l10.312-10.314a1 1 0 0 1 1.414 0zm-9.608 12.436 10.315-10.315-1.413-1.414-10.313 10.312.005 1.422zm7.486-10.313 1.414 1.414-7.778 7.778-1.407.007-.007-1.421zm1.414-1.415 1.414 1.415-.707.707-1.414-1.415z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_empty_metrics.svg b/app/views/shared/icons/_icon_empty_metrics.svg
deleted file mode 100644
index 24fa353f3ba..00000000000
--- a/app/views/shared/icons/_icon_empty_metrics.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
- <g fill="#E5E5E5">
- <path d="M32 64C30.8954305 64 30 63.1045695 30 62 30 60.8954305 30.8954305 60 32 60 33.8894444 60 35.7536611 59.8131396 37.574335 59.4454933 38.6570511 59.2268618 39.7120017 59.9273408 39.9306331 61.0100569 40.1492646 62.0927729 39.4487856 63.1477235 38.3660695 63.366355 36.285133 63.7865558 34.1557023 64 32 64zM49.2301062 58.9696428C51.0302775 57.8173242 52.7114504 56.4871355 54.247711 55.0008916 55.0415758 54.232873 55.0625283 52.9667164 54.2945097 52.1728516 53.5264912 51.3789869 52.2603346 51.3580344 51.4664698 52.1260529 50.1212672 53.4274592 48.6493395 54.5920875 47.0736141 55.6007347 46.1433158 56.1962335 45.8719072 57.4331365 46.4674061 58.3634348 47.0629049 59.2937331 48.2998079 59.5651416 49.2301062 58.9696428zM61.0426034 45.4531856C61.9412068 43.5163476 62.6441937 41.4911051 63.1388045 39.4034279 63.393449 38.3286117 62.7285685 37.2508708 61.6537523 36.9962262 60.5789361 36.7415816 59.5011952 37.4064621 59.2465506 38.4812784 58.8141946 40.3061875 58.1997219 42.0764286 57.4141077 43.7697311 56.9492346 44.7717126 57.3846469 45.9608331 58.3866284 46.4257062 59.3886098 46.8905793 60.5777303 46.455167 61.0426034 45.4531856zM63.7270657 27.8034151C63.4476841 25.6718707 62.9558906 23.5863203 62.2616468 21.5714028 61.9018246 20.527084 60.7635435 19.9721898 59.7192246 20.3320119 58.6749058 20.6918341 58.1200116 21.8301152 58.4798337 22.874434 59.0867105 24.6357842 59.5166381 26.45898 59.760988 28.3232492 59.9045362 29.4184513 60.9087418 30.1899192 62.0039439 30.046371 63.099146 29.9028228 63.8706139 28.8986173 63.7270657 27.8034151zM56.4699838 11.3781121C55.0919588 9.74451505 53.5537382 8.25140603 51.8798083 6.92273835 51.0146495 6.23602588 49.7566092 6.38068523 49.0698968 7.24584403 48.3831843 8.11100284 48.5278436 9.36904308 49.3930024 10.0557555 50.8587525 11.2191822 52.2058153 12.5267396 53.4125204 13.9572433 54.1247279 14.8015385 55.3865225 14.9086168 56.2308177 14.1964094 57.0751129 13.484202 57.1821912 12.2224073 56.4699838 11.3781121zM41.481294 1.42849704C39.4470333.798260231 37.3474846.371987025 35.2067823.158824109 34.1076485.0493765922 33.1278998.851675811 33.0184523 1.95080957 32.9090048 3.04994333 33.711304 4.02969203 34.8104377 4.13913955 36.6833634 4.32563829 38.5191483 4.69835932 40.297557 5.24933028 41.3526509 5.57621023 42.4729622 4.98587613 42.7998421 3.93078217 43.1267221 2.8756882 42.536388 1.75537699 41.481294 1.42849704zM23.6558195 1.0993008C21.5852929 1.6571259 19.5822296 2.42161363 17.6728876 3.37914679 16.6855233 3.874309 16.2865147 5.07613416 16.7816769 6.06349841 17.2768392 7.05086266 18.4786643 7.44987125 19.4660286 6.95470905 21.1354949 6.11747332 22.8864813 5.44919307 24.6963667 4.96158787 25.7629079 4.67424869 26.3945759 3.57671185 26.1072367 2.51017072 25.8198975 1.44362959 24.7223606.811961615 23.6558195 1.0993008zM8.36290105 10.4291871C6.92120358 12.00815 5.63985273 13.7275139 4.53998784 15.5610549 3.97179016 16.5082746 4.27904822 17.7367631 5.22626792 18.3049608 6.17348763 18.8731585 7.40197615 18.5659004 7.97017383 17.6186807 8.9327668 16.0139803 10.054503 14.5087932 11.3168098 13.126301 12.0615972 12.3106016 12.0041117 11.0455771 11.1884123 10.3007897 10.372713 9.55600224 9.10768848 9.61348772 8.36290105 10.4291871zM.450120287 26.6230259C.151304663 28.3883054 0 30.1850053 0 32 0 32.2974081.00406268322 32.594367.0121750297 32.8908218.0423897377 33.994978.96197903 34.8655796 2.0661352 34.8353649 3.17029137 34.8051502 4.04089294 33.8855609 4.01067824 32.7814047 4.00356366 32.521412 4 32.2609289 4 32 4 30.4089462 4.13249902 28.8355581 4.39401589 27.2906242 4.57836807 26.2015475 3.84494393 25.1692294 2.75586724 24.9848772 1.66679054 24.800525.634472466 25.5339492.450120287 26.6230259zM2.45830096 44.3202494C3.28286321 46.2952494 4.30407075 48.1806071 5.50459135 49.9494734 6.124886 50.8634254 7.36863868 51.1014818 8.28259072 50.4811871 9.19654276 49.8608925 9.43459912 48.6171398 8.81430448 47.7031878 7.76386025 46.1554464 6.87058107 44.5062706 6.14951581 42.7791677 5.72395784 41.7598668 4.55266835 41.2785432 3.53336751 41.7041011 2.51406668 42.1296591 2.03274299 43.3009486 2.45830096 44.3202494zM13.73374 58.2776222C15.4883094 59.4994144 17.3614388 60.5433005 19.3262717 61.39161 20.3403619 61.8294398 21.5173756 61.3622885 21.9552054 60.3481983 22.3930351 59.3341082 21.9258838 58.1570945 20.9117937 57.7192647 19.1934726 56.9773858 17.5548741 56.0642026 16.0195384 54.9950736 15.1130877 54.3638678 13.8665707 54.5869979 13.2353649 55.4934487 12.6041591 56.3998995 12.8272892 57.6464164 13.73374 58.2776222zM30.6955071 63.9738646C29.5918263 63.9295649 28.7330282 62.9989428 28.7773279 61.895262 28.8216276 60.7915812 29.7522497 59.9327832 30.8559305 59.9770829 31.2344492 59.9922759 31.6140624 59.9999282 31.9946308 59.9999995 33.0992003 60.0002065 33.994463 60.8958047 33.994256 62.0003742 33.9940491 63.1049437 33.0984508 64.0002064 31.9938814 63.9999994 31.5600677 63.9999181 31.1272192 63.9911927 30.6955071 63.9738646zM30.1721098 44.2840559C30.7941711 46.023825 33.2407935 46.0619159 33.9167124 44.3423547L38.9452693 31.5495297 41.1315797 35.2685507C41.4908522 35.8796908 42.1468005 36.2549751 42.8557214 36.2549751L51.1106965 36.2549751C52.215266 36.2549751 53.1106965 35.3595446 53.1106965 34.2549751 53.1106965 33.1504056 52.215266 32.2549751 51.1106965 32.2549751L43.9999712 32.2549751 40.3112064 25.9802055C39.465988 24.5424477 37.3358287 24.7099356 36.7257006 26.2621229L32.1439734 37.9181973 26.2115967 21.3266406C25.5807315 19.562249 23.0875908 19.5563214 22.4483429 21.3176933L18.4775633 32.2587065 13 32.2587065C11.8954305 32.2587065 11 33.154137 11 34.2587065 11 35.363276 11.8954305 36.2587065 13 36.2587065L19.8793532 36.2587065C20.720826 36.2587065 21.4722973 35.732004 21.7593685 34.9410132L24.314328 27.9011249 30.1721098 44.2840559z"/>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_icon_eye.svg b/app/views/shared/icons/_icon_eye.svg
deleted file mode 100644
index 9fea9841eb3..00000000000
--- a/app/views/shared/icons/_icon_eye.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_eye_slash.svg b/app/views/shared/icons/_icon_eye_slash.svg
deleted file mode 100644
index 45c06b3495d..00000000000
--- a/app/views/shared/icons/_icon_eye_slash.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_fork.svg b/app/views/shared/icons/_icon_fork.svg
deleted file mode 100644
index ce22b6cdaea..00000000000
--- a/app/views/shared/icons/_icon_fork.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="30" height="40" viewBox="5 0 30 40"><path fill="#7E7E7E" fill-rule="evenodd" d="M22 29.535V22.72c4.19-1.21 7.4-5.917 7.4-5.917.34-.446.6-1.247.6-1.795v-4.543C31.196 9.773 32 8.48 32 7c0-2.21-1.79-4-4-4s-4 1.79-4 4c0 1.48.804 2.773 2 3.465v4.243c0 .17-.094.39-.21.502 0 0-1.253 1.203-1.84 1.742C22.5 18.277 21.12 19 20.09 19c-1.042 0-2.473-.74-3.977-2.086-.61-.546-1.746-1.574-1.746-1.574-.2-.182-.367-.555-.367-.83v-4.045C15.196 9.773 16 8.48 16 7c0-2.21-1.79-4-4-4S8 4.79 8 7c0 1.48.804 2.773 2 3.465v4.543c0 .537.274 1.345.61 1.78 0 0 3.25 4.59 7.39 5.88v6.867c-1.196.692-2 1.984-2 3.465 0 2.21 1.79 4 4 4s4-1.79 4-4c0-1.48-.804-2.773-2-3.465zM14 7c0-1.105-.895-2-2-2s-2 .895-2 2 .895 2 2 2 2-.895 2-2zm16 0c0-1.105-.895-2-2-2s-2 .895-2 2 .895 2 2 2 2-.895 2-2zm-8 26c0-1.105-.895-2-2-2s-2 .895-2 2 .895 2 2 2 2-.895 2-2z"/></svg>
diff --git a/app/views/shared/icons/_icon_history.svg b/app/views/shared/icons/_icon_history.svg
deleted file mode 100644
index 41096da19c5..00000000000
--- a/app/views/shared/icons/_icon_history.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1664 896q0 156-61 298t-164 245-245 164-298 61q-172 0-327-72.5T305 1387q-7-10-6.5-22.5t8.5-20.5l137-138q10-9 25-9 16 2 23 12 73 95 179 147t225 52q104 0 198.5-40.5T1258 1258t109.5-163.5T1408 896t-40.5-198.5T1258 534t-163.5-109.5T896 384q-98 0-188 35.5T548 521l137 138q31 30 14 69-17 40-59 40H192q-26 0-45-19t-19-45V256q0-42 40-59 39-17 69 14l130 129q107-101 244.5-156.5T896 128q156 0 298 61t245 164 164 245 61 298zm-640-288v448q0 14-9 23t-23 9H672q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h224V608q0-14 9-23t23-9h64q14 0 23 9t9 23z"/></svg>
diff --git a/app/views/shared/icons/_icon_hourglass.svg b/app/views/shared/icons/_icon_hourglass.svg
deleted file mode 100644
index fe7e497ce13..00000000000
--- a/app/views/shared/icons/_icon_hourglass.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.331 4.889A2.988 2.988 0 0 0 11 3V2H5v1c0 .362.064.709.182 1.03l5.15.859zM3 14v-1c0-1.78.93-3.342 2.33-4.228.447-.327.67-.582.67-.764 0-.19-.242-.46-.725-.815A4.996 4.996 0 0 1 3 3V2H2a1 1 0 1 1 0-2h12a1 1 0 0 1 0 2h-1v1a4.997 4.997 0 0 1-2.39 4.266c-.407.3-.61.545-.61.734 0 .19.203.434.61.734A4.997 4.997 0 0 1 13 13v1h1a1 1 0 0 1 0 2H2a1 1 0 0 1 0-2h1zm8 0v-1a3 3 0 0 0-6 0v1h6z"/></svg>
diff --git a/app/views/shared/icons/_icon_lock.svg b/app/views/shared/icons/_icon_lock.svg
deleted file mode 100644
index 6ec671a76ed..00000000000
--- a/app/views/shared/icons/_icon_lock.svg
+++ /dev/null
@@ -1,25 +0,0 @@
-<svg width="46px" height="54px" viewBox="227 0 46 54" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
- <desc>Created with Sketch.</desc>
- <defs>
- <rect id="path-1" x="0" y="20" width="46" height="34" rx="8"></rect>
- <mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="46" height="34" fill="white">
- <use xlink:href="#path-1"></use>
- </mask>
- <path d="M29,16 C29,8.2680135 22.7319865,2 15,2 C7.2680135,2 1,8.2680135 1,16" id="path-3"></path>
- <mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="28" height="14" fill="white">
- <use xlink:href="#path-3"></use>
- </mask>
- </defs>
- <g id="locker" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(227.000000, 0.000000)">
- <g id="Group-8">
- <use id="Rectangle-14" stroke="#B5A7DD" mask="url(#mask-2)" stroke-width="6" xlink:href="#path-1"></use>
- <g id="Group-7" transform="translate(8.000000, 0.000000)">
- <use id="Oval-3" stroke="#B5A7DD" mask="url(#mask-4)" stroke-width="6" xlink:href="#path-3"></use>
- <rect id="Rectangle-13" fill="#B5A7DD" x="1" y="16" width="3" height="6"></rect>
- <rect id="Rectangle-13-Copy" fill="#B5A7DD" x="26" y="16" width="3" height="6"></rect>
- </g>
- <path d="M25,37.4648712 C26.1956027,36.7732524 27,35.4805647 27,34 C27,31.790861 25.209139,30 23,30 C20.790861,30 19,31.790861 19,34 C19,35.4805647 19.8043973,36.7732524 21,37.4648712 L21,41.0026083 C21,42.1041422 21.8954305,43 23,43 C24.1122704,43 25,42.1057373 25,41.0026083 L25,37.4648712 Z" id="Combined-Shape" fill="#6B4FBB"></path>
- </g>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_icon_merge.svg b/app/views/shared/icons/_icon_merge.svg
deleted file mode 100644
index 451ae12afbc..00000000000
--- a/app/views/shared/icons/_icon_merge.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m5 5.563v4.875c1.024.4 1.75 1.397 1.75 2.563 0 1.519-1.231 2.75-2.75 2.75-1.519 0-2.75-1.231-2.75-2.75 0-1.166.726-2.162 1.75-2.563v-4.875c-1.024-.4-1.75-1.397-1.75-2.563 0-1.519 1.231-2.75 2.75-2.75 1.519 0 2.75 1.231 2.75 2.75 0 1.166-.726 2.162-1.75 2.563m-1 8.687c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25m0-10c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25"/><path d="m10.501 2c1.381.001 2.499 1.125 2.499 2.506v5.931c1.024.4 1.75 1.397 1.75 2.563 0 1.519-1.231 2.75-2.75 2.75-1.519 0-2.75-1.231-2.75-2.75 0-1.166.726-2.162 1.75-2.563v-5.931c0-.279-.225-.506-.499-.506v.926c0 .346-.244.474-.569.271l-2.952-1.844c-.314-.196-.325-.507 0-.71l2.952-1.844c.314-.196.569-.081.569.271v.93m1.499 12.25c.69 0 1.25-.56 1.25-1.25 0-.69-.56-1.25-1.25-1.25-.69 0-1.25.56-1.25 1.25 0 .69.56 1.25 1.25 1.25"/></svg>
diff --git a/app/views/shared/icons/_icon_merged.svg b/app/views/shared/icons/_icon_merged.svg
deleted file mode 100644
index 77d170b2491..00000000000
--- a/app/views/shared/icons/_icon_merged.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_mr_issue.svg b/app/views/shared/icons/_icon_mr_issue.svg
deleted file mode 100644
index a56af9c556c..00000000000
--- a/app/views/shared/icons/_icon_mr_issue.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g fill-rule="evenodd"><path d="m8.411 1.012c-.136-.008-.273-.012-.411-.012-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-.138-.004-.275-.012-.411-.464.201-.964.334-1.488.386 0 .008 0 .016 0 .025 0 3.038-2.462 5.5-5.5 5.5-3.038 0-5.5-2.462-5.5-5.5 0-3.038 2.462-5.5 5.5-5.5.008 0 .016 0 .025 0 .052-.524.185-1.024.386-1.488"/><path d="m12 2h-1.01c-.54 0-.991.448-.991 1 0 .556.444 1 .991 1h1.01v1.01c0 .54.448.991 1 .991.556 0 1-.444 1-.991v-1.01h1.01c.54 0 .991-.448.991-1 0-.556-.444-1-.991-1h-1.01v-1.01c0-.54-.448-.991-1-.991-.556 0-1 .444-1 .991v1.01m-5 4.01c0-.557.444-1.01 1-1.01.552 0 1 .443 1 1.01v1.981c0 .557-.444 1.01-1 1.01-.552 0-1-.443-1-1.01v-1.981m1 5.991c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1"/></g></svg>
diff --git a/app/views/shared/icons/_icon_no_data.svg b/app/views/shared/icons/_icon_no_data.svg
deleted file mode 100644
index ced8653b88c..00000000000
--- a/app/views/shared/icons/_icon_no_data.svg
+++ /dev/null
@@ -1,27 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="211 0 78 36" xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs>
- <circle id="a" cx="5" cy="31" r="5"/>
- <mask id="e" width="10" height="10" x="0" y="0" fill="#fff">
- <use xlink:href="#a"/>
- </mask>
- <circle id="b" cx="29" cy="14" r="5"/>
- <mask id="f" width="10" height="10" x="0" y="0" fill="#fff">
- <use xlink:href="#b"/>
- </mask>
- <circle id="c" cx="53" cy="24" r="5"/>
- <mask id="g" width="10" height="10" x="0" y="0" fill="#fff">
- <use xlink:href="#c"/>
- </mask>
- <circle id="d" cx="73" cy="5" r="5"/>
- <mask id="h" width="10" height="10" x="0" y="0" fill="#fff">
- <use xlink:href="#d"/>
- </mask>
- </defs>
- <g fill="none" fill-rule="evenodd" transform="translate(211)">
- <path stroke="#B5A7DD" stroke-width="2" d="M5 31l24-17 26 10L73 5" stroke-linecap="round" stroke-dasharray="3 6"/>
- <use fill="#FFF" stroke="#6B4FBB" stroke-width="6" mask="url(#e)" xlink:href="#a"/>
- <use fill="#FFF" stroke="#6B4FBB" stroke-width="6" mask="url(#f)" xlink:href="#b"/>
- <use fill="#FFF" stroke="#B5A7DD" stroke-width="6" mask="url(#g)" xlink:href="#c"/>
- <use fill="#FFF" stroke="#B5A7DD" stroke-width="6" mask="url(#h)" xlink:href="#d"/>
- </g>
-</svg>
diff --git a/app/views/shared/icons/_icon_no_wrap.svg b/app/views/shared/icons/_icon_no_wrap.svg
deleted file mode 100644
index fe34cada002..00000000000
--- a/app/views/shared/icons/_icon_no_wrap.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="m6 11h-4.509c-.263 0-.491.226-.491.505v.991c0 .291.22.505.491.505h4.509v.679c0 .301.194.413.454.236l2.355-1.607c.251-.171.259-.442 0-.619l-2.355-1.607c-.251-.171-.454-.07-.454.236v.681m-5-7.495c0-.279.22-.505.498-.505h13c.275 0 .498.214.498.505v.991c0 .279-.22.505-.498.505h-13c-.275 0-.498-.214-.498-.505v-.991m10 8c0-.279.215-.505.49-.505h3.02c.271 0 .49.214.49.505v.991c0 .279-.215.505-.49.505h-3.02c-.271 0-.49-.214-.49-.505v-.991m-10-4c0-.279.22-.505.498-.505h13c.275 0 .498.214.498.505v.991c0 .279-.22.505-.498.505h-13c-.275 0-.498-.214-.498-.505v-.991"/>
-</svg>
diff --git a/app/views/shared/icons/_icon_pencil.svg b/app/views/shared/icons/_icon_pencil.svg
deleted file mode 100644
index bcde54bd1e1..00000000000
--- a/app/views/shared/icons/_icon_pencil.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_play.svg b/app/views/shared/icons/_icon_play.svg
deleted file mode 100644
index 4c69fc99a9e..00000000000
--- a/app/views/shared/icons/_icon_play.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 11" class="icon-play"><path fill-rule="evenodd" d="m9.283 6.47l-7.564 4.254c-.949.534-1.719.266-1.719-.576v-9.292c0-.852.756-1.117 1.719-.576l7.564 4.254c.949.534.963 1.392 0 1.934"/></svg>
diff --git a/app/views/shared/icons/_icon_random.svg b/app/views/shared/icons/_icon_random.svg
deleted file mode 100644
index 74c1c903657..00000000000
--- a/app/views/shared/icons/_icon_random.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
-
diff --git a/app/views/shared/icons/_icon_service_desk.svg b/app/views/shared/icons/_icon_service_desk.svg
deleted file mode 100644
index 2886388279e..00000000000
--- a/app/views/shared/icons/_icon_service_desk.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="78" height="82" viewBox="0 0 78 82"><g fill="none" fill-rule="evenodd"><path fill="#F9F9F9" d="M2.12 42c-.08.99-.12 1.99-.12 3 0 20.435 16.565 37 37 37s37-16.565 37-37c0-1.01-.04-2.01-.12-3C74.353 61.032 58.425 76 39 76 19.575 76 3.647 61.032 2.12 42z"/><path fill="#EEE" fill-rule="nonzero" d="M39 78C17.46 78 0 60.54 0 39S17.46 0 39 0s39 17.46 39 39-17.46 39-39 39zm0-4c19.33 0 35-15.67 35-35S58.33 4 39 4 4 19.67 4 39s15.67 35 35 35z"/><rect width="7" height="1" x="59" y="38" fill="#E1DBF2" rx=".5"/><path fill="#6B4FBB" d="M60.5 42a3.5 3.5 0 0 0 0-7v7z"/><rect width="7" height="1" x="12" y="38" fill="#E1DBF2" transform="matrix(-1 0 0 1 31 0)" rx=".5"/><path fill="#6B4FBB" d="M17.5 42a3.5 3.5 0 0 1 0-7v7z"/><path fill="#E1DBF1" fill-rule="nonzero" d="M39 58c10.493 0 19-8.507 19-19s-8.507-19-19-19-19 8.507-19 19 8.507 19 19 19zm0 4c-12.703 0-23-10.297-23-23s10.297-23 23-23 23 10.297 23 23-10.297 23-23 23z"/><path fill="#6B4FBB" d="M35 56a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm4 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/><path fill="#E1DBF1" fill-rule="nonzero" d="M26.5 40c0 4.143 3.355 7.5 7.494 7.5h10.012A7.497 7.497 0 0 0 51.5 40c0-4.143-3.355-7.5-7.494-7.5H33.994A7.497 7.497 0 0 0 26.5 40zm-3 0c0-5.799 4.698-10.5 10.494-10.5h10.012C49.802 29.5 54.5 34.2 54.5 40c0 5.799-4.698 10.5-10.494 10.5H33.994C28.198 50.5 23.5 45.8 23.5 40z"/><path fill="#6B4FBB" fill-rule="nonzero" d="M35.255 42.406a1 1 0 1 1 1.872-.703 2.001 2.001 0 0 0 3.76-.038 1 1 0 1 1 1.886.665 4 4 0 0 1-7.518.076zM31.5 40a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm15 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/><path fill="#6B4FBB" d="M38 22h2a1 1 0 0 1 0 2h-2a1 1 0 0 1 0-2zm0 3h2a1 1 0 0 1 0 2h-2a1 1 0 0 1 0-2z" style="mix-blend-mode:multiply"/></g></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_icon_soft_wrap.svg b/app/views/shared/icons/_icon_soft_wrap.svg
deleted file mode 100644
index ea27a2024b1..00000000000
--- a/app/views/shared/icons/_icon_soft_wrap.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="m12 11h-2v-.681c0-.307-.203-.407-.454-.236l-2.355 1.607c-.259.177-.251.448 0 .619l2.355 1.607c.259.177.454.065.454-.236v-.679h2c0 0 0 0 0 0 1.657 0 3-1.343 3-3 0-.828-.336-1.578-.879-2.121-.543-.543-1.293-.879-2.121-.879-.001 0-.002 0-.002 0h-10.497c-.271 0-.5.226-.5.505v.991c0 .291.224.505.5.505h10.497c.001 0 .002 0 .002 0 .552 0 1 .448 1 1 0 .276-.112.526-.293.707-.181.181-.431.293-.707.293m-11-7.495c0-.279.22-.505.498-.505h13c.275 0 .498.214.498.505v.991c0 .279-.22.505-.498.505h-13c-.275 0-.498-.214-.498-.505v-.991m0 8c0-.279.215-.505.49-.505h3.02c.271 0 .49.214.49.505v.991c0 .279-.215.505-.49.505h-3.02c-.271 0-.49-.214-.49-.505v-.991"/>
-</svg>
diff --git a/app/views/shared/icons/_icon_status_canceled.svg b/app/views/shared/icons/_icon_status_canceled.svg
deleted file mode 100644
index bd5d04e1cd7..00000000000
--- a/app/views/shared/icons/_icon_status_canceled.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M5.2 3.8l4.9 4.9c.2.2.2.5 0 .7l-.7.7c-.2.2-.5.2-.7 0L3.8 5.2c-.2-.2-.2-.5 0-.7l.7-.7c.2-.2.5-.2.7 0"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_canceled_borderless.svg b/app/views/shared/icons/_icon_status_canceled_borderless.svg
deleted file mode 100644
index bf7fb29185f..00000000000
--- a/app/views/shared/icons/_icon_status_canceled_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg"><path d="M8.17142857,5.97142857 L15.8714286,13.6714286 C16.1857143,13.9857143 16.1857143,14.4571429 15.8714286,14.7714286 L14.7714286,15.8714286 C14.4571429,16.1857143 13.9857143,16.1857143 13.6714286,15.8714286 L5.97142857,8.17142857 C5.65714286,7.85714286 5.65714286,7.38571429 5.97142857,7.07142857 L7.07142857,5.97142857 C7.38571429,5.65714286 7.85714286,5.65714286 8.17142857,5.97142857" id="Shape"></path></svg>
diff --git a/app/views/shared/icons/_icon_status_closed.svg b/app/views/shared/icons/_icon_status_closed.svg
deleted file mode 100644
index dc39223e721..00000000000
--- a/app/views/shared/icons/_icon_status_closed.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.83c.39-.39 1.024-.39 1.414 0 .39.392.39 1.025 0 1.416l-3.535 3.535c-.196.195-.452.293-.707.293-.256 0-.512-.097-.708-.292l-2.12-2.12c-.39-.392-.39-1.025 0-1.415s1.023-.39 1.413 0zM8 16c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_created.svg b/app/views/shared/icons/_icon_status_created.svg
deleted file mode 100644
index 326ad04e017..00000000000
--- a/app/views/shared/icons/_icon_status_created.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><circle cx="7" cy="7" r="3.25"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_created_borderless.svg b/app/views/shared/icons/_icon_status_created_borderless.svg
deleted file mode 100644
index 1810d023be8..00000000000
--- a/app/views/shared/icons/_icon_status_created_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle id="Oval" cx="11" cy="11" r="5.10714286"></circle></svg>
diff --git a/app/views/shared/icons/_icon_status_failed.svg b/app/views/shared/icons/_icon_status_failed.svg
deleted file mode 100644
index 64da5aa31fc..00000000000
--- a/app/views/shared/icons/_icon_status_failed.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M7 5.969L5.599 4.568a.29.29 0 0 0-.413.004l-.614.614a.294.294 0 0 0-.004.413L5.968 7l-1.4 1.401a.29.29 0 0 0 .004.413l.614.614c.113.114.3.117.413.004L7 8.032l1.401 1.4a.29.29 0 0 0 .413-.004l.614-.614a.294.294 0 0 0 .004-.413L8.032 7l1.4-1.401a.29.29 0 0 0-.004-.413l-.614-.614a.294.294 0 0 0-.413-.004L7 5.968z"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_failed_borderless.svg b/app/views/shared/icons/_icon_status_failed_borderless.svg
deleted file mode 100644
index b7022350c74..00000000000
--- a/app/views/shared/icons/_icon_status_failed_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M12.1458333,9.85416667 L12.1458333,6.74047388 C12.1458333,6.4826434 11.9382041,6.28571429 11.6820804,6.28571429 L10.3179196,6.28571429 C10.0656535,6.28571429 9.85416667,6.48931709 9.85416667,6.74047388 L9.85416667,9.85416667 L6.74047388,9.85416667 C6.4826434,9.85416667 6.28571429,10.0617959 6.28571429,10.3179196 L6.28571429,11.6820804 C6.28571429,11.9343465 6.48931709,12.1458333 6.74047388,12.1458333 L9.85416667,12.1458333 L9.85416667,15.2595261 C9.85416667,15.5173566 10.0617959,15.7142857 10.3179196,15.7142857 L11.6820804,15.7142857 C11.9343465,15.7142857 12.1458333,15.5106829 12.1458333,15.2595261 L12.1458333,12.1458333 L15.2595261,12.1458333 C15.5173566,12.1458333 15.7142857,11.9382041 15.7142857,11.6820804 L15.7142857,10.3179196 C15.7142857,10.0656535 15.5106829,9.85416667 15.2595261,9.85416667 L12.1458333,9.85416667 Z" id="Combined-Shape" transform="translate(11.000000, 11.000000) rotate(-45.000000) translate(-11.000000, -11.000000) "></path></svg>
diff --git a/app/views/shared/icons/_icon_status_manual.svg b/app/views/shared/icons/_icon_status_manual.svg
deleted file mode 100644
index c98839f51a9..00000000000
--- a/app/views/shared/icons/_icon_status_manual.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M10.5 7.63V6.37l-.787-.13c-.044-.175-.132-.349-.263-.61l.481-.652-.918-.913-.657.478a2.346 2.346 0 0 0-.612-.26L7.656 3.5H6.388l-.132.783c-.219.043-.394.13-.612.26l-.657-.478-.918.913.437.652c-.131.218-.175.392-.262.61l-.744.086v1.261l.787.13c.044.218.132.392.263.61l-.438.651.92.913.655-.434c.175.086.394.173.613.26l.131.783h1.313l.131-.783c.219-.043.394-.13.613-.26l.656.478.918-.913-.48-.652c.13-.218.218-.435.262-.61l.656-.13zM7 8.283a1.285 1.285 0 0 1-1.313-1.305c0-.739.57-1.304 1.313-1.304.744 0 1.313.565 1.313 1.304 0 .74-.57 1.305-1.313 1.305z"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_manual_borderless.svg b/app/views/shared/icons/_icon_status_manual_borderless.svg
deleted file mode 100644
index 5eec665688b..00000000000
--- a/app/views/shared/icons/_icon_status_manual_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M16.5,11.9906832 L16.5,10.0093168 L15.2625,9.80434783 C15.19375,9.5310559 15.05625,9.25776398 14.85,8.84782609 L15.60625,7.82298137 L14.1625,6.38819876 L13.13125,7.13975155 C12.7875,6.93478261 12.44375,6.79813665 12.16875,6.72981366 L12.03125,5.5 L10.0375,5.5 L9.83125,6.72981366 C9.4875,6.79813665 9.2125,6.93478261 8.86875,7.13975155 L7.8375,6.38819876 L6.39375,7.82298137 L7.08125,8.84782609 C6.875,9.18944099 6.80625,9.46273292 6.66875,9.80434783 L5.5,9.94099379 L5.5,11.9223602 L6.7375,12.1273292 C6.80625,12.4689441 6.94375,12.742236 7.15,13.0838509 L6.4625,14.1086957 L7.90625,15.5434783 L8.9375,14.8602484 C9.2125,14.9968944 9.55625,15.1335404 9.9,15.2701863 L10.10625,16.5 L12.16875,16.5 L12.375,15.2701863 C12.71875,15.2018634 12.99375,15.0652174 13.3375,14.8602484 L14.36875,15.6118012 L15.8125,14.1770186 L15.05625,13.1521739 C15.2625,12.810559 15.4,12.4689441 15.46875,12.1956522 L16.5,11.9906832 L16.5,11.9906832 Z M11,13.015528 C9.83125,13.015528 8.9375,12.1273292 8.9375,10.9658385 C8.9375,9.80434783 9.83125,8.91614907 11,8.91614907 C12.16875,8.91614907 13.0625,9.80434783 13.0625,10.9658385 C13.0625,12.1273292 12.16875,13.015528 11,13.015528 L11,13.015528 Z" id="Shape" ></path></svg>
diff --git a/app/views/shared/icons/_icon_status_open.svg b/app/views/shared/icons/_icon_status_open.svg
deleted file mode 100644
index ed58d23c626..00000000000
--- a/app/views/shared/icons/_icon_status_open.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7z"/><path d="M1 7c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6z" fill="#FFF"/><path d="M7 9.219a2.218 2.218 0 1 0 0-4.436A2.218 2.218 0 0 0 7 9.22zm0 1.12a3.338 3.338 0 1 1 0-6.676 3.338 3.338 0 0 1 0 6.676z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_pending.svg b/app/views/shared/icons/_icon_status_pending.svg
deleted file mode 100644
index 02d5da407e3..00000000000
--- a/app/views/shared/icons/_icon_status_pending.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M4.7 5.3c0-.2.1-.3.3-.3h.9c.2 0 .3.1.3.3v3.4c0 .2-.1.3-.3.3H5c-.2 0-.3-.1-.3-.3V5.3m3 0c0-.2.1-.3.3-.3h.9c.2 0 .3.1.3.3v3.4c0 .2-.1.3-.3.3H8c-.2 0-.3-.1-.3-.3V5.3"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_pending_borderless.svg b/app/views/shared/icons/_icon_status_pending_borderless.svg
deleted file mode 100644
index 8d66e9e6c9c..00000000000
--- a/app/views/shared/icons/_icon_status_pending_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M7.38571429,8.32857143 C7.38571429,8.01428571 7.54285714,7.85714286 7.85714286,7.85714286 L9.27142857,7.85714286 C9.58571429,7.85714286 9.74285714,8.01428571 9.74285714,8.32857143 L9.74285714,13.6714286 C9.74285714,13.9857143 9.58571429,14.1428571 9.27142857,14.1428571 L7.85714286,14.1428571 C7.54285714,14.1428571 7.38571429,13.9857143 7.38571429,13.6714286 L7.38571429,8.32857143 M12.1,8.32857143 C12.1,8.01428571 12.2571429,7.85714286 12.5714286,7.85714286 L13.9857143,7.85714286 C14.3,7.85714286 14.4571429,8.01428571 14.4571429,8.32857143 L14.4571429,13.6714286 C14.4571429,13.9857143 14.3,14.1428571 13.9857143,14.1428571 L12.5714286,14.1428571 C12.2571429,14.1428571 12.1,13.9857143 12.1,13.6714286 L12.1,8.32857143" id="Shape"></path></svg>
diff --git a/app/views/shared/icons/_icon_status_running.svg b/app/views/shared/icons/_icon_status_running.svg
deleted file mode 100644
index 532f4fee33c..00000000000
--- a/app/views/shared/icons/_icon_status_running.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M7 3c2.2 0 4 1.8 4 4s-1.8 4-4 4c-1.3 0-2.5-.7-3.3-1.7L7 7V3"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_running_borderless.svg b/app/views/shared/icons/_icon_status_running_borderless.svg
deleted file mode 100644
index 2757a168ed5..00000000000
--- a/app/views/shared/icons/_icon_status_running_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M11,4.71428571 C14.4571429,4.71428571 17.2857143,7.54285714 17.2857143,11 C17.2857143,14.4571429 14.4571429,17.2857143 11,17.2857143 C8.95714286,17.2857143 7.07142857,16.1857143 5.81428571,14.6142857 L11,11 L11,4.71428571" id="Shape"></path></svg>
diff --git a/app/views/shared/icons/_icon_status_scheduled.svg b/app/views/shared/icons/_icon_status_scheduled.svg
deleted file mode 100644
index ca6e4efce50..00000000000
--- a/app/views/shared/icons/_icon_status_scheduled.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><circle cx="7" cy="7" r="7"/><circle fill="#FFF" cx="7" cy="7" r="6"/><g transform="translate(2.75 2.75)" fill-rule="nonzero"><path d="M4.165 7.81a3.644 3.644 0 1 1 0-7.29 3.644 3.644 0 0 1 0 7.29zm0-1.042a2.603 2.603 0 1 0 0-5.206 2.603 2.603 0 0 0 0 5.206z"/><rect x="3.644" y="2.083" width="1.041" height="2.603" rx=".488"/><rect x="3.644" y="3.644" width="2.083" height="1.041" rx=".488"/></g></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_icon_status_scheduled_borderless.svg b/app/views/shared/icons/_icon_status_scheduled_borderless.svg
deleted file mode 100644
index dc38c01d898..00000000000
--- a/app/views/shared/icons/_icon_status_scheduled_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M6.16 11.55a5.39 5.39 0 1 1 0-10.78 5.39 5.39 0 0 1 0 10.78zm0-1.54a3.85 3.85 0 1 0 0-7.7 3.85 3.85 0 0 0 0 7.7z"/><rect x="5.39" y="3.08" width="1.54" height="3.85" rx=".767"/><rect x="5.39" y="5.39" width="3.08" height="1.54" rx=".767"/></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_icon_status_skipped.svg b/app/views/shared/icons/_icon_status_skipped.svg
deleted file mode 100644
index a9ba29c922c..00000000000
--- a/app/views/shared/icons/_icon_status_skipped.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M7 14A7 7 0 1 1 7 0a7 7 0 0 1 0 14z"/><path d="M7 13A6 6 0 1 0 7 1a6 6 0 0 0 0 12z" fill="#FFF" fill-rule="nonzero"/><path d="M6.415 7.04L4.579 5.203a.295.295 0 0 1 .004-.416l.349-.349a.29.29 0 0 1 .416-.004l2.214 2.214a.289.289 0 0 1 .019.021l.132.133c.11.11.108.291 0 .398L5.341 9.573a.282.282 0 0 1-.398 0l-.331-.331a.285.285 0 0 1 0-.399L6.415 7.04zm2.54 0L7.119 5.203a.295.295 0 0 1 .004-.416l.349-.349a.29.29 0 0 1 .416-.004l2.214 2.214a.289.289 0 0 1 .019.021l.132.133c.11.11.108.291 0 .398L7.881 9.573a.282.282 0 0 1-.398 0l-.331-.331a.285.285 0 0 1 0-.399L8.955 7.04z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_skipped_borderless.svg b/app/views/shared/icons/_icon_status_skipped_borderless.svg
deleted file mode 100644
index 3c8a26d7f4d..00000000000
--- a/app/views/shared/icons/_icon_status_skipped_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22" height="22" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg"><path d="M14.072 11.063l-2.82 2.82a.46.46 0 0 0-.001.652l.495.495a.457.457 0 0 0 .653-.001l3.7-3.7a.46.46 0 0 0 .001-.653l-.196-.196a.453.453 0 0 0-.03-.033l-3.479-3.479a.464.464 0 0 0-.654.007l-.548.548a.463.463 0 0 0-.007.654l2.886 2.886z"/><path d="M10.08 11.063l-2.819 2.82a.46.46 0 0 0-.002.652l.496.495a.457.457 0 0 0 .652-.001l3.7-3.7a.46.46 0 0 0 .002-.653l-.196-.196a.453.453 0 0 0-.03-.033l-3.48-3.479a.464.464 0 0 0-.653.007l-.548.548a.463.463 0 0 0-.007.654l2.886 2.886z"/></svg>
diff --git a/app/views/shared/icons/_icon_status_success.svg b/app/views/shared/icons/_icon_status_success.svg
deleted file mode 100644
index eed5006bebe..00000000000
--- a/app/views/shared/icons/_icon_status_success.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M6.278 7.697L5.045 6.464a.296.296 0 0 0-.42-.002l-.613.614a.298.298 0 0 0 .002.42l1.91 1.909a.5.5 0 0 0 .703.005l.265-.265L9.997 6.04a.291.291 0 0 0-.009-.408l-.614-.614a.29.29 0 0 0-.408-.009L6.278 7.697z"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_warning.svg b/app/views/shared/icons/_icon_status_warning.svg
deleted file mode 100644
index cb785635b7e..00000000000
--- a/app/views/shared/icons/_icon_status_warning.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M6 3.5c0-.3.2-.5.5-.5h1c.3 0 .5.2.5.5v4c0 .3-.2.5-.5.5h-1c-.3 0-.5-.2-.5-.5v-4m0 6c0-.3.2-.5.5-.5h1c.3 0 .5.2.5.5v1c0 .3-.2.5-.5.5h-1c-.3 0-.5-.2-.5-.5v-1"/></g></svg>
diff --git a/app/views/shared/icons/_icon_status_warning_borderless.svg b/app/views/shared/icons/_icon_status_warning_borderless.svg
deleted file mode 100644
index 7b061624521..00000000000
--- a/app/views/shared/icons/_icon_status_warning_borderless.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M9.42857143,5.5 C9.42857143,5.02857143 9.74285714,4.71428571 10.2142857,4.71428571 L11.7857143,4.71428571 C12.2571429,4.71428571 12.5714286,5.02857143 12.5714286,5.5 L12.5714286,11.7857143 C12.5714286,12.2571429 12.2571429,12.5714286 11.7857143,12.5714286 L10.2142857,12.5714286 C9.74285714,12.5714286 9.42857143,12.2571429 9.42857143,11.7857143 L9.42857143,5.5 M9.42857143,14.9285714 C9.42857143,14.4571429 9.74285714,14.1428571 10.2142857,14.1428571 L11.7857143,14.1428571 C12.2571429,14.1428571 12.5714286,14.4571429 12.5714286,14.9285714 L12.5714286,16.5 C12.5714286,16.9714286 12.2571429,17.2857143 11.7857143,17.2857143 L10.2142857,17.2857143 C9.74285714,17.2857143 9.42857143,16.9714286 9.42857143,16.5 L9.42857143,14.9285714" id="Shape"></path></svg>
diff --git a/app/views/shared/icons/_icon_stopwatch.svg b/app/views/shared/icons/_icon_stopwatch.svg
deleted file mode 100644
index 6c2a8b2773f..00000000000
--- a/app/views/shared/icons/_icon_stopwatch.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 14" enable-background="new 0 0 12 14"><path d="m11.5 2.4l-1.3-1.1-1 1.1 1.4 1.1.9-1.1"/><path d="m6.8 2v-.5h.5v-1.5h-2.6v1.5h.5v.5c-2.9.4-5.2 2.9-5.2 6 0 3.3 2.7 6 6 6s6-2.7 6-6c0-3-2.3-5.6-5.2-6m-.8 10.5c-2.5 0-4.5-2-4.5-4.5s2-4.5 4.5-4.5 4.5 2 4.5 4.5-2 4.5-4.5 4.5"/><path d="m6.2 8.9h-.5c-.1 0-.2-.1-.2-.2v-3.5c0-.1.1-.2.2-.2h.5c.1 0 .2.1.2.2v3.5c0 .1-.1.2-.2.2"/></svg>
diff --git a/app/views/shared/icons/_icon_tags.svg b/app/views/shared/icons/_icon_tags.svg
deleted file mode 100644
index d36ea022f92..00000000000
--- a/app/views/shared/icons/_icon_tags.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m7.222.222c1.657 0 3 1.343 3 3v8.327c0 .631-.298 1.226-.805 1.603l-3 2.237c-.709.529-1.682.529-2.391 0l-3-2.237c-.506-.377-.805-.972-.805-1.603v-8.327c0-1.657 1.343-3 3-3h4m-5 3v8.08c0 .158.075.306.201.401l2.5 1.864c.177.132.42.132.598 0l2.5-1.864c.127-.094.201-.243.201-.401v-8.08c0-.552-.448-1-1-1h-4c-.552 0-1 .448-1 1m2.778 7.778c-.552 0-1-.448-1-1s .448-1 1-1 1 .448 1 1-.448 1-1 1" transform="matrix(-.70711 .70711 -.70711 -.70711 17.05 9.767)"/></svg>
-
diff --git a/app/views/shared/icons/_icon_terminal.svg b/app/views/shared/icons/_icon_terminal.svg
deleted file mode 100644
index c80f44c3edf..00000000000
--- a/app/views/shared/icons/_icon_terminal.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="19" height="14" viewBox="0 0 19 14" xmlns="http://www.w3.org/2000/svg"><rect fill="#848484" x="7.2" y="9.25" width="6.46" height="1.5" rx=".5"/><path d="M5.851 7.016L3.81 9.103a.503.503 0 0 0 .017.709l.35.334c.207.198.524.191.717-.006l2.687-2.748a.493.493 0 0 0 .137-.376.493.493 0 0 0-.137-.376L4.894 3.892a.507.507 0 0 0-.717-.006l-.35.334a.503.503 0 0 0-.017.709L5.85 7.016z"/><path d="M1.25 11.497c0 .691.562 1.253 1.253 1.253h13.994c.694 0 1.253-.56 1.253-1.253V2.503c0-.691-.562-1.253-1.253-1.253H2.503c-.694 0-1.253.56-1.253 1.253v8.994zM2.503 0h13.994A2.504 2.504 0 0 1 19 2.503v8.994A2.501 2.501 0 0 1 16.497 14H2.503A2.504 2.504 0 0 1 0 11.497V2.503A2.501 2.501 0 0 1 2.503 0z"/></svg>
diff --git a/app/views/shared/icons/_icon_trash_o.svg b/app/views/shared/icons/_icon_trash_o.svg
deleted file mode 100644
index 0d7a91ab536..00000000000
--- a/app/views/shared/icons/_icon_trash_o.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M704 736v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23v-576q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23v-576q0-14 9-23t23-9h64q14 0 23 9t9 23zm256 0v576q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23v-576q0-14 9-23t23-9h64q14 0 23 9t9 23zm128 724v-948h-896v948q0 22 7 40.5t14.5 27 10.5 8.5h832q3 0 10.5-8.5t14.5-27 7-40.5zm-672-1076h448l-48-117q-7-9-17-11h-317q-10 2-17 11zm928 32v64q0 14-9 23t-23 9h-96v948q0 83-47 143.5t-113 60.5h-832q-66 0-113-58.5t-47-141.5v-952h-96q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h309l70-167q15-37 54-63t79-26h320q40 0 79 26t54 63l70 167h309q14 0 23 9t9 23z"/></svg>
diff --git a/app/views/shared/icons/_icon_user.svg b/app/views/shared/icons/_icon_user.svg
deleted file mode 100644
index 6e7406f7eac..00000000000
--- a/app/views/shared/icons/_icon_user.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 7C6.343 7 5 5.657 5 4s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48S14.888 15 8 15z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/icons/_key.svg b/app/views/shared/icons/_key.svg
deleted file mode 100644
index 5ad03ed4480..00000000000
--- a/app/views/shared/icons/_key.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7.574 6.689a4.002 4.002 0 0 1 6.275-4.861 4 4 0 0 1-4.86 6.275l-2.21 2.21.706.707a1 1 0 0 1-1.414 1.415l-.707-.708-.707.708.707.707a1 1 0 0 1-1.414 1.414l-.707-.707a1 1 0 0 1-1.415-1.414l5.746-5.746zm2.033-.618a2 2 0 1 0 2.828-2.829 2 2 0 0 0-2.828 2.829z"/></svg>
diff --git a/app/views/shared/icons/_labels.svg b/app/views/shared/icons/_labels.svg
deleted file mode 100644
index 1ebad4bb4fa..00000000000
--- a/app/views/shared/icons/_labels.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M9.424 2.254l2.08-.905a1 1 0 0 1 1.206.326l3.013 4.12a1 1 0 0 1 .16.849l-1.947 7.264a3 3 0 0 1-3.675 2.122l-.5-.135a3.999 3.999 0 0 0 1.082-1.782 1 1 0 0 0 1.16-.722l1.823-6.802-2.258-3.087-.687.299a2 2 0 0 0-.628-.88l-.829-.667z"/><path d="M.377 3.7L4.4.498a1 1 0 0 1 1.25.003L9.627 3.7a1 1 0 0 1 .373.78V13a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V4.482A1 1 0 0 1 .377 3.7zM2 13a1 1 0 0 0 1 1h4a1 1 0 0 0 1-1V4.958L5.02 2.561 2 4.964V13zm3-6a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
diff --git a/app/views/shared/icons/_lock.svg b/app/views/shared/icons/_lock.svg
deleted file mode 100644
index 703c09611a3..00000000000
--- a/app/views/shared/icons/_lock.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="m8 9c-.6 0-1 .4-1 1v1c0 .6.4 1 1 1s1-.4 1-1v-1c0-.6-.4-1-1-1"/><path d="m12 5v-1c0-2.2-1.8-4-4-4s-4 1.8-4 4v1c-1.7 0-3 1.3-3 3v5c0 1.7 1.3 3 3 3h8c1.7 0 3-1.3 3-3v-5c0-1.7-1.3-3-3-3m-6-1c0-1.1.9-2 2-2s2 .9 2 2v1h-4v-1m7 9c0 .6-.4 1-1 1h-8c-.6 0-1-.4-1-1v-5c0-.6.4-1 1-1h8c.6 0 1 .4 1 1v5"/></svg>
diff --git a/app/views/shared/icons/_members.svg b/app/views/shared/icons/_members.svg
deleted file mode 100644
index 68d957d6d11..00000000000
--- a/app/views/shared/icons/_members.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M10.521 8.01C15.103 8.19 16 10.755 16 12.48c0 1.533-.056 2.29-3.808 2.475.609-.54.808-1.331.808-2.475 0-1.911-.804-3.503-2.479-4.47zm-1.67-1.228A3.987 3.987 0 0 0 9.976 4a3.987 3.987 0 0 0-1.125-2.782 3 3 0 1 1 0 5.563zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6zM6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8s6 2.692 6 4.48c0 1.788-.076 2.52-6 2.52z"/></svg>
diff --git a/app/views/shared/icons/_messages.svg b/app/views/shared/icons/_messages.svg
deleted file mode 100644
index 9a2ea15c35d..00000000000
--- a/app/views/shared/icons/_messages.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.588 8.942l1.173 5.862A1 1 0 0 1 8.78 16H7.22a1 1 0 0 1-.98-1.196l1.172-5.862a3.014 3.014 0 0 0 1.176 0zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zM4.464 2.464L5.88 3.88a3 3 0 0 0 0 4.242L4.464 9.536a5 5 0 0 1 0-7.072zm7.072 7.072L10.12 8.12a3 3 0 0 0 0-4.242l1.415-1.415a5 5 0 0 1 0 7.072zM2.343.343l1.414 1.414a6 6 0 0 0 0 8.486l-1.414 1.414a8 8 0 0 1 0-11.314zm11.314 11.314l-1.414-1.414a6 6 0 0 0 0-8.486L13.657.343a8 8 0 0 1 0 11.314z"/></svg>
diff --git a/app/views/shared/icons/_monitoring.svg b/app/views/shared/icons/_monitoring.svg
deleted file mode 100644
index 21689b0877c..00000000000
--- a/app/views/shared/icons/_monitoring.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M10 13v1h3a1 1 0 0 1 0 2H3a1 1 0 0 1 0-2h3v-1H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3h-3zM3 2a1 1 0 0 0-1 1v7a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm5.723 6.416l-2.66-1.773-1.71 1.71a.5.5 0 1 1-.707-.707l2-2a.5.5 0 0 1 .631-.062l2.66 1.773 2.71-2.71a.5.5 0 0 1 .707.707l-3 3a.5.5 0 0 1-.631.062z"/></svg>
diff --git a/app/views/shared/icons/_notifications.svg b/app/views/shared/icons/_notifications.svg
deleted file mode 100644
index da55de041da..00000000000
--- a/app/views/shared/icons/_notifications.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M6 14H2.435a2 2 0 0 1-1.761-2.947c.962-1.788 1.521-3.065 1.68-3.832.322-1.566.947-5.501 4.65-6.134a1 1 0 1 1 1.994-.024c3.755.528 4.375 4.27 4.761 6.043.188.86.742 2.188 1.661 3.982A2 2 0 0 1 13.64 14H10a2 2 0 1 1-4 0zm5.805-6.468c-.325-1.492-.37-1.674-.61-2.288C10.6 3.716 9.742 3 8.07 3c-1.608 0-2.49.718-3.103 2.197-.28.676-.356.982-.654 2.428-.208 1.012-.827 2.424-1.877 4.375H13.64c-.993-1.937-1.6-3.396-1.835-4.468z"/></svg>
diff --git a/app/views/shared/icons/_overview.svg b/app/views/shared/icons/_overview.svg
deleted file mode 100644
index 4791282df7f..00000000000
--- a/app/views/shared/icons/_overview.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M2 2v3h3V2H2zm0-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm9 2v3h3V2h-3zm0-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zM2 11v3h3v-3H2zm0-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2zm9 2v3h3v-3h-3zm0-2h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2z"/></svg>
diff --git a/app/views/shared/icons/_pipeline.svg b/app/views/shared/icons/_pipeline.svg
deleted file mode 100644
index 5bedc96a1bd..00000000000
--- a/app/views/shared/icons/_pipeline.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><path d="m8 0c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8m0 14c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6"/><circle cx="12.5" cy="9.5" r=".5"/><circle cx="12.5" cy="6.5" r=".5"/><circle cx="10.5" cy="12.5" r=".5"/><circle cx="10.5" cy="3.5" r=".5"/><circle cx="5.5" cy="12.5" r=".5"/><circle cx="5.5" cy="3.5" r=".5"/><circle cx="3.5" cy="9.5" r=".5"/><circle cx="3.5" cy="6.5" r=".5"/><path d="m9 7.2c0 0 0-.1 0-.2v-1.9c0-.1 0-.1-.1-.2l-.8-.8c0 0-.1 0-.1 0l-.9.8c-.1.1-.1.1-.1.2v1.9c0 .1 0 .2 0 .2-.6.4-1 1-1 1.8 0 1.1.9 2 2 2s2-.9 2-2c0-.8-.4-1.4-1-1.8m-1 2.8c-.6 0-1-.4-1-1s.4-1 1-1 1 .4 1 1-.4 1-1 1"/></svg>
diff --git a/app/views/shared/icons/_plus_square.svg b/app/views/shared/icons/_plus_square.svg
deleted file mode 100644
index 7263d924f1f..00000000000
--- a/app/views/shared/icons/_plus_square.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M9 7V4c0-.552-.448-1-1-1s-1 .448-1 1v3H4c-.552 0-1 .448-1 1s.448 1 1 1h3v3c0 .552.448 1 1 1s1-.448 1-1V9h3c.552 0 1-.448 1-1s-.448-1-1-1H9zM3 0h10c1.657 0 3 1.343 3 3v10c0 1.657-1.343 3-3 3H3c-1.657 0-3-1.343-3-3V3c0-1.657 1.343-3 3-3z"/></svg>
diff --git a/app/views/shared/icons/_preferences.svg b/app/views/shared/icons/_preferences.svg
deleted file mode 100644
index cbd7a4fe9f0..00000000000
--- a/app/views/shared/icons/_preferences.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6 2h9a1 1 0 0 1 0 2H6a1 1 0 1 1-2 0V2a1 1 0 1 1 2 0zM3 2H1a1 1 0 1 0 0 2h2V2zm10 5h2a1 1 0 0 1 0 2h-2a1 1 0 0 1-2 0V7a1 1 0 0 1 2 0zm-3 0H1a1 1 0 1 0 0 2h9V7zm-5 5h10a1 1 0 0 1 0 2H5a1 1 0 0 1-2 0v-2a1 1 0 0 1 2 0zm-3 0H1a1 1 0 0 0 0 2h1v-2z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/icons/_profile.svg b/app/views/shared/icons/_profile.svg
deleted file mode 100644
index 29e360a9051..00000000000
--- a/app/views/shared/icons/_profile.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 16A8 8 0 1 1 8 0a8 8 0 0 1 0 16zm0-2A6 6 0 1 0 8 2a6 6 0 0 0 0 12zm-4.274-3.404C4.412 9.709 5.694 9 8 9c2.313 0 3.595.7 4.28 1.586A4.997 4.997 0 0 1 8 13a4.997 4.997 0 0 1-4.274-2.404zM8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"/></svg>
diff --git a/app/views/shared/icons/_project.svg b/app/views/shared/icons/_project.svg
deleted file mode 100644
index bbfdd939e7b..00000000000
--- a/app/views/shared/icons/_project.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8.462 2.177l-.038.044a.505.505 0 0 0 .038-.044zm-.787 0a.5.5 0 0 0 .038.043l-.038-.043zM3.706 7h8.725L8.069 2.585 3.706 7zM7 13.369V12a1 1 0 0 1 2 0v1.369h3V9H4v4.369h3zM14 9v4.836c0 .833-.657 1.533-1.5 1.533h-9c-.843 0-1.5-.7-1.5-1.533V9h-.448a1.1 1.1 0 0 1-.783-1.873L6.934.887a1.5 1.5 0 0 1 2.269 0l6.165 6.24A1.1 1.1 0 0 1 14.585 9H14z"/></svg>
diff --git a/app/views/shared/icons/_scroll_down.svg b/app/views/shared/icons/_scroll_down.svg
deleted file mode 100644
index 1d22870ec09..00000000000
--- a/app/views/shared/icons/_scroll_down.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="12" height="16" viewBox="0 0 12 16" xmlns="http://www.w3.org/2000/svg">
- <path class="first-triangle" d="M1.048 14.155a.508.508 0 0 0-.32.105c-.091.07-.136.154-.136.25v.71c0 .095.045.178.135.249.09.07.197.105.321.105h10.043c.124 0 .23-.035.321-.105.09-.07.136-.154.136-.25v-.71c0-.095-.045-.178-.136-.249a.508.508 0 0 0-.32-.105"/>
- <path class="second-triangle" d="M.687 8.027c-.09-.087-.122-.16-.093-.22.028-.06.104-.09.228-.09h10.5c.123 0 .2.03.228.09.029.06-.002.133-.093.22L6.393 12.91a.458.458 0 0 1-.136.089h-.37a.626.626 0 0 1-.136-.09"/>
- <path class="third-triangle" d="M.687 1.027C.597.94.565.867.594.807c.028-.06.104-.09.228-.09h10.5c.123 0 .2.03.228.09.029.06-.002.133-.093.22L6.393 5.91A.458.458 0 0 1 6.257 6h-.37a.626.626 0 0 1-.136-.09"/>
-</svg>
diff --git a/app/views/shared/icons/_scroll_up.svg b/app/views/shared/icons/_scroll_up.svg
deleted file mode 100644
index 70b1e4d9c91..00000000000
--- a/app/views/shared/icons/_scroll_up.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg width="12" height="16" viewBox="0 0 12 16" xmlns="http://www.w3.org/2000/svg"><path d="M1.048 1.845a.508.508 0 0 1-.32-.105c-.091-.07-.136-.154-.136-.25V.78c0-.095.045-.178.135-.249a.508.508 0 0 1 .321-.105h10.043c.124 0 .23.035.321.105.09.07.136.154.136.25v.71c0 .095-.045.178-.136.249a.508.508 0 0 1-.32.105"/><path d="M.687 7.973c-.09.087-.122.16-.093.22.028.06.104.09.228.09h10.5c.123 0 .2-.03.228-.09.029-.06-.002-.133-.093-.22L6.393 3.09A.458.458 0 0 0 6.257 3h-.37a.626.626 0 0 0-.136.09"/><path d="M.687 14.973c-.09.087-.122.16-.093.22.028.06.104.09.228.09h10.5c.123 0 .2-.03.228-.09.029-.06-.002-.133-.093-.22L6.393 10.09A.458.458 0 0 0 6.257 10h-.37a.626.626 0 0 0-.136.09"/></svg>
diff --git a/app/views/shared/icons/_service_templates.svg b/app/views/shared/icons/_service_templates.svg
deleted file mode 100644
index b65cd8300b2..00000000000
--- a/app/views/shared/icons/_service_templates.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3zm.8 2h2.4a.8.8 0 0 1 .8.8v1.4a.8.8 0 0 1-.8.8H3.8a.8.8 0 0 1-.8-.8V4.8a.8.8 0 0 1 .8-.8zm4.7 0h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm0 2h4a.5.5 0 1 1 0 1h-4a.5.5 0 0 1 0-1zm-5 3h9a.5.5 0 1 1 0 1h-9a.5.5 0 0 1 0-1zm0 2h9a.5.5 0 1 1 0 1h-9a.5.5 0 1 1 0-1z"/></svg>
diff --git a/app/views/shared/icons/_settings.svg b/app/views/shared/icons/_settings.svg
deleted file mode 100644
index 96c5ef8c04d..00000000000
--- a/app/views/shared/icons/_settings.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M2.415 5.803L1.317 4.084A.5.5 0 0 1 1.35 3.5l.805-.994a.5.5 0 0 1 .564-.153l1.878.704a5.975 5.975 0 0 1 1.65-.797L6.885.342A.5.5 0 0 1 7.36 0h1.28a.5.5 0 0 1 .474.342l.639 1.918c.594.181 1.15.452 1.65.797l1.877-.704a.5.5 0 0 1 .565.153l.805.994a.5.5 0 0 1 .032.584l-1.097 1.719c.217.551.354 1.143.399 1.76l1.731 1.058a.5.5 0 0 1 .227.54l-.288 1.246a.5.5 0 0 1-.44.385l-2.008.19a6.026 6.026 0 0 1-1.142 1.431l.265 1.995a.5.5 0 0 1-.277.516l-1.15.56a.5.5 0 0 1-.576-.1l-1.424-1.452a6.047 6.047 0 0 1-1.804 0l-1.425 1.453a.5.5 0 0 1-.576.1l-1.15-.561a.5.5 0 0 1-.276-.516l.265-1.995a6.026 6.026 0 0 1-1.143-1.43l-2.008-.191a.5.5 0 0 1-.44-.385L.058 9.16a.5.5 0 0 1 .226-.539l1.732-1.058a5.968 5.968 0 0 1 .399-1.76zM8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/></svg>
diff --git a/app/views/shared/icons/_snippets.svg b/app/views/shared/icons/_snippets.svg
deleted file mode 100644
index 1e1340187b4..00000000000
--- a/app/views/shared/icons/_snippets.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.67 9.31a3.001 3.001 0 0 1 2.062 5.546 3 3 0 0 1-3.771-4.559 1.007 1.007 0 0 1-.095-.137l-4.5-7.794a1 1 0 1 1 1.732-1l4.5 7.794c.028.05.052.1.071.15zm-3.283.35l-.289.5c-.028.05-.06.095-.095.137a3.001 3.001 0 0 1-3.77 4.56A3 3 0 0 1 5.294 9.31c.02-.051.043-.102.071-.15l.866-1.5 1.155 2zm2.31-4l-1.156-2 1.325-2.294a1 1 0 1 1 1.732 1L9.696 5.66zm-5.465 7.464a1 1 0 1 0 1-1.732 1 1 0 0 0-1 1.732zm7.5 0a1 1 0 1 0-1-1.732 1 1 0 0 0 1 1.732z"/></svg>
diff --git a/app/views/shared/icons/_spam_logs.svg b/app/views/shared/icons/_spam_logs.svg
deleted file mode 100644
index 80ee0eb3856..00000000000
--- a/app/views/shared/icons/_spam_logs.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8.75.433l5.428 3.134a1.5 1.5 0 0 1 .75 1.299v6.268a1.5 1.5 0 0 1-.75 1.299L8.75 15.567a1.5 1.5 0 0 1-1.5 0l-5.428-3.134a1.5 1.5 0 0 1-.75-1.299V4.866a1.5 1.5 0 0 1 .75-1.299L7.25.433a1.5 1.5 0 0 1 1.5 0zM3.072 5.155v5.69L8 13.691l4.928-2.846v-5.69L8 2.309 3.072 5.155zM8 4a1 1 0 0 1 1 1v3a1 1 0 1 1-2 0V5a1 1 0 0 1 1-1zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
diff --git a/app/views/shared/icons/_system_hooks.svg b/app/views/shared/icons/_system_hooks.svg
deleted file mode 100644
index 7b95a6f29f3..00000000000
--- a/app/views/shared/icons/_system_hooks.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M10 3a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1h4zm0 1H6v1a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V4zM7 8a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3h2a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3v4a2 2 0 1 0 4 0h-.44a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H15a4 4 0 0 1-7 2.646A4 4 0 0 1 1 12H.56a.3.3 0 0 1-.25-.466l1.44-2.16a.3.3 0 0 1 .5 0l1.44 2.16a.3.3 0 0 1-.25.466H3a2 2 0 1 0 4 0V8z"/></svg>
diff --git a/app/views/shared/icons/_todo_done.svg b/app/views/shared/icons/_todo_done.svg
deleted file mode 100644
index 156dfa11df1..00000000000
--- a/app/views/shared/icons/_todo_done.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8.243 7.485l4.95-4.95a1 1 0 1 1 1.414 1.415L8.95 9.607a.997.997 0 0 1-1.414 0l-2.83-2.83a1 1 0 0 1 1.415-1.413l2.123 2.12zM12 11a1 1 0 0 1 2 0v2a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V5a3 3 0 0 1 3-3h2a1 1 0 1 1 0 2H3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-2z"/></svg>
diff --git a/app/views/shared/icons/_wiki.svg b/app/views/shared/icons/_wiki.svg
deleted file mode 100644
index b5ad38d9863..00000000000
--- a/app/views/shared/icons/_wiki.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 2H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1v4.191a.5.5 0 0 1-.724.447l-1.052-.526a.5.5 0 0 0-.448 0l-1.052.526A.5.5 0 0 1 8 6.191V2zM4 0h8a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3z"/></svg>
diff --git a/app/workers/click_house/event_paths_consistency_cron_worker.rb b/app/workers/click_house/event_paths_consistency_cron_worker.rb
index 9dbf55186de..71a1fb0995f 100644
--- a/app/workers/click_house/event_paths_consistency_cron_worker.rb
+++ b/app/workers/click_house/event_paths_consistency_cron_worker.rb
@@ -44,7 +44,7 @@ module ClickHouse
metadata[:modifications] = modifications
if modifications >= MAX_RECORD_MODIFICATIONS
- metadata[:status] = :modification_limit_reached
+ metadata[:status] = :limit_reached
return
end
diff --git a/app/workers/projects/git_garbage_collect_worker.rb b/app/workers/projects/git_garbage_collect_worker.rb
index 32bffc3ab6a..d99737f0567 100644
--- a/app/workers/projects/git_garbage_collect_worker.rb
+++ b/app/workers/projects/git_garbage_collect_worker.rb
@@ -24,15 +24,13 @@ module Projects
rescue Gitlab::Git::CommandTimedOut, GRPC::Internal => e
Gitlab::ErrorTracking.track_exception(e)
end
-
- cleanup_orphan_lfs_file_references(resource) unless reorder_feature_flag?(resource)
end
override :after_gitaly_call
def after_gitaly_call(task, resource)
return unless gc?(task)
- cleanup_orphan_lfs_file_references(resource) if reorder_feature_flag?(resource)
+ cleanup_orphan_lfs_file_references(resource)
end
def cleanup_orphan_lfs_file_references(resource)
@@ -52,9 +50,5 @@ module Projects
def stats
[:repository_size, :lfs_objects_size]
end
-
- def reorder_feature_flag?(resource)
- Feature.enabled?(:reorder_garbage_collection_calls, resource, type: :gitlab_com_derisk)
- end
end
end
diff --git a/config/feature_flags/gitlab_com_derisk/reorder_garbage_collection_calls.yml b/config/feature_flags/gitlab_com_derisk/determine_blank_ref_based_on_gitaly_object_format.yml
index 2fd1370118f..35443130efc 100644
--- a/config/feature_flags/gitlab_com_derisk/reorder_garbage_collection_calls.yml
+++ b/config/feature_flags/gitlab_com_derisk/determine_blank_ref_based_on_gitaly_object_format.yml
@@ -1,8 +1,8 @@
---
-name: reorder_garbage_collection_calls
-feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/429514
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141109
-rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17363
+name: determine_blank_ref_based_on_gitaly_object_format
+feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/434693
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140395
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17317
milestone: '16.8'
group: group::source code
type: gitlab_com_derisk
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 619263bb8db..314b61a5d74 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -795,6 +795,9 @@ Gitlab.ee do
Settings.cron_jobs['elastic_migration_worker'] ||= {}
Settings.cron_jobs['elastic_migration_worker']['cron'] ||= '*/5 * * * *'
Settings.cron_jobs['elastic_migration_worker']['job_class'] ||= 'Elastic::MigrationWorker'
+ Settings.cron_jobs['search_zoekt_scheduling_worker'] ||= {}
+ Settings.cron_jobs['search_zoekt_scheduling_worker']['cron'] ||= '*/10 * * * *'
+ Settings.cron_jobs['search_zoekt_scheduling_worker']['job_class'] ||= 'Search::Zoekt::SchedulingWorker'
Settings.cron_jobs['search_index_curation_worker'] ||= {}
Settings.cron_jobs['search_index_curation_worker']['cron'] ||= '*/1 * * * *'
Settings.cron_jobs['search_index_curation_worker']['job_class'] ||= 'Search::IndexCurationWorker'
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 92c45c59f7b..772f12d46ed 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -103,6 +103,11 @@ Gitlab::Cluster::LifecycleEvents.on_worker_start do
end
Gitlab::Ci::Parsers.instrument!
+
+ # We intentionally defer this instrumentation to occur after `reinitialize_on_pid_change`.
+ # Otherwise `ConnectionPool.after_fork` will result in the instrumentation being called early,
+ # before we had a chance to re-initialize prometheus mmapped metrics.
+ ConnectionPool.prepend(Gitlab::Instrumentation::ConnectionPool)
rescue IOError => e
Gitlab::ErrorTracking.track_exception(e)
Gitlab::Metrics.error_detected!
diff --git a/config/initializers/7_redis.rb b/config/initializers/7_redis.rb
index 5d5bb209774..0b908ce4b65 100644
--- a/config/initializers/7_redis.rb
+++ b/config/initializers/7_redis.rb
@@ -27,8 +27,6 @@ Redis::Cluster::SlotLoader.prepend(Gitlab::Patch::SlotLoader)
Redis::Cluster::CommandLoader.prepend(Gitlab::Patch::CommandLoader)
Redis::Cluster.prepend(Gitlab::Patch::RedisCluster)
-ConnectionPool.prepend(Gitlab::Instrumentation::ConnectionPool)
-
# this only instruments `RedisClient` used in `Sidekiq.redis`
RedisClient.register(Gitlab::Instrumentation::RedisClientMiddleware)
diff --git a/config/metrics/counts_all/20240117153239_instances_beyond_identity_active.yml b/config/metrics/counts_all/20240117153239_instances_beyond_identity_active.yml
new file mode 100644
index 00000000000..e1040d2a0cb
--- /dev/null
+++ b/config/metrics/counts_all/20240117153239_instances_beyond_identity_active.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.instances_beyond_identity_active
+description: Count of projects with active integrations for BeyondIdentity
+product_section: dev
+product_stage: create
+product_group: source_code
+value_type: number
+status: active
+milestone: "16.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136754
+time_frame: all
+data_source: database
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20240117153516_groups_inheriting_beyond_identity_active.yml b/config/metrics/counts_all/20240117153516_groups_inheriting_beyond_identity_active.yml
new file mode 100644
index 00000000000..5d68a2ed466
--- /dev/null
+++ b/config/metrics/counts_all/20240117153516_groups_inheriting_beyond_identity_active.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.groups_inheriting_beyond_identity_active
+description: Count of projects with active integrations for BeyondIdentity
+product_section: dev
+product_stage: create
+product_group: source_code
+value_type: number
+status: active
+milestone: "16.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136754
+time_frame: all
+data_source: database
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20240117153519_groups_beyond_identity_active.yml b/config/metrics/counts_all/20240117153519_groups_beyond_identity_active.yml
new file mode 100644
index 00000000000..ca4db507697
--- /dev/null
+++ b/config/metrics/counts_all/20240117153519_groups_beyond_identity_active.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.groups_beyond_identity_active
+description: Count of projects with active integrations for BeyondIdentity
+product_section: dev
+product_stage: create
+product_group: source_code
+value_type: number
+status: active
+milestone: "16.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136754
+time_frame: all
+data_source: database
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20240117153523_projects_inheriting_beyond_identity_active.yml b/config/metrics/counts_all/20240117153523_projects_inheriting_beyond_identity_active.yml
new file mode 100644
index 00000000000..0dffad590e4
--- /dev/null
+++ b/config/metrics/counts_all/20240117153523_projects_inheriting_beyond_identity_active.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.projects_inheriting_beyond_identity_active
+description: Count of projects with active integrations for BeyondIdentity
+product_section: dev
+product_stage: create
+product_group: source_code
+value_type: number
+status: active
+milestone: "16.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136754
+time_frame: all
+data_source: database
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/counts_all/20240117153527_projects_beyond_identity_active.yml b/config/metrics/counts_all/20240117153527_projects_beyond_identity_active.yml
new file mode 100644
index 00000000000..260213e3070
--- /dev/null
+++ b/config/metrics/counts_all/20240117153527_projects_beyond_identity_active.yml
@@ -0,0 +1,21 @@
+---
+key_path: counts.projects_beyond_identity_active
+description: Count of projects with active integrations for BeyondIdentity
+product_section: dev
+product_stage: create
+product_group: source_code
+value_type: number
+status: active
+milestone: "16.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136754
+time_frame: all
+data_source: database
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/db/docs/integrations.yml b/db/docs/integrations.yml
index 037dea949d0..415f0593cb1 100644
--- a/db/docs/integrations.yml
+++ b/db/docs/integrations.yml
@@ -13,6 +13,7 @@ classes:
- Integrations::BaseSlackNotification
- Integrations::BaseSlashCommands
- Integrations::BaseThirdPartyWiki
+- Integrations::BeyondIdentity
- Integrations::Bugzilla
- Integrations::Buildkite
- Integrations::Campfire
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 584bdb3526a..e48cec20e9e 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -8904,6 +8904,29 @@ The edge type for [`AgentConfiguration`](#agentconfiguration).
| <a id="agentconfigurationedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="agentconfigurationedgenode"></a>`node` | [`AgentConfiguration`](#agentconfiguration) | The item at the end of the edge. |
+#### `AiAgentConnection`
+
+The connection type for [`AiAgent`](#aiagent).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="aiagentconnectionedges"></a>`edges` | [`[AiAgentEdge]`](#aiagentedge) | A list of edges. |
+| <a id="aiagentconnectionnodes"></a>`nodes` | [`[AiAgent]`](#aiagent) | A list of nodes. |
+| <a id="aiagentconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `AiAgentEdge`
+
+The edge type for [`AiAgent`](#aiagent).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="aiagentedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="aiagentedgenode"></a>`node` | [`AiAgent`](#aiagent) | The item at the end of the edge. |
+
#### `AiMessageConnection`
The connection type for [`AiMessage`](#aimessage).
@@ -24332,6 +24355,7 @@ Represents vulnerability finding of a security report on the pipeline.
| ---- | ---- | ----------- |
| <a id="projectactualrepositorysizelimit"></a>`actualRepositorySizeLimit` | [`Float`](#float) | Size limit for the repository in bytes. |
| <a id="projectagentconfigurations"></a>`agentConfigurations` | [`AgentConfigurationConnection`](#agentconfigurationconnection) | Agent configurations defined by the project. (see [Connections](#connections)) |
+| <a id="projectaiagents"></a>`aiAgents` **{warning-solid}** | [`AiAgentConnection`](#aiagentconnection) | **Introduced** in 16.9. This feature is an Experiment. It can be changed or removed at any time. Ai Agents for the project. |
| <a id="projectallowmergeonskippedpipeline"></a>`allowMergeOnSkippedPipeline` | [`Boolean`](#boolean) | If `only_allow_merge_if_pipeline_succeeds` is true, indicates if merge requests of the project can also be merged with skipped jobs. |
| <a id="projectallowsmultiplemergerequestassignees"></a>`allowsMultipleMergeRequestAssignees` | [`Boolean!`](#boolean) | Project allows assigning multiple users to a merge request. |
| <a id="projectallowsmultiplemergerequestreviewers"></a>`allowsMultipleMergeRequestReviewers` | [`Boolean!`](#boolean) | Project allows assigning multiple reviewers to a merge request. |
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 6442059ebbe..a41390558ad 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -1692,6 +1692,10 @@ Offerings:
- `SAAS`
- `ALL` - Applies to both self-managed and SaaS.
+NOTE:
+GitLab Dedicated is not currently covered by product tier badges in the documentation.
+For more information, see [issue 417171](https://gitlab.com/gitlab-org/gitlab/-/issues/417171#note_1568753875).
+
You can also add a third component for the feature's status:
- `EXPERIMENT`
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index 2185d77e056..aaaf57eaa28 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -602,7 +602,7 @@ Instead of:
## email
-Do not use **e-mail** with a hyphen. When plural, use **emails** or **email messages**. ([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+Do not use **e-mail** with a hyphen. When plural, use **emails** or **email messages**. ([Vale](../testing.md#vale) rule: [`Substitutions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Substitutions.yml))
## email address
@@ -819,7 +819,7 @@ After the first use, use the feature name without **GitLab Duo**.
## GitLab Flavored Markdown
When possible, spell out [**GitLab Flavored Markdown**](../../../user/markdown.md).
-([Vale](../testing.md#vale) rule: [`GLFM.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+([Vale](../testing.md#vale) rule: [`GLFM.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Substitutions.yml))
If you must abbreviate, do not use **GFM**. Use **GLFM** instead.
@@ -1213,7 +1213,7 @@ Do not use **navigate**. Use **go** instead. For example:
- Go to this webpage.
- Open a terminal and go to the `runner` directory.
-([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+([Vale](../testing.md#vale) rule: [`Substitutions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Substitutions.yml))
## need to
@@ -1742,7 +1742,9 @@ Gitaly storages have physical paths and virtual storages have virtual paths.
## subgroup
-Use **subgroup** (no hyphen) instead of **sub-group**. ([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+Use **subgroup** (no hyphen) instead of **sub-group**.
+Also, avoid using alternative terms for subgroups, such as **child group** or **low-level group**.
+([Vale](../testing.md#vale) rule: [`Substitutions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Substitutions.yml))
## subscription tier
@@ -1958,7 +1960,7 @@ For example:
## utilize
Do not use **utilize**. Use **use** instead. It's more succinct and easier for non-native English speakers to understand.
-([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+([Vale](../testing.md#vale) rule: [`Substitutions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Substitutions.yml))
## Value stream forecasting
@@ -1996,7 +1998,7 @@ Instead of:
- We created a feature for you to add widgets.
-([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
+([Vale](../testing.md#vale) rule: [`Substitutions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Substitutions.yml))
## workaround
diff --git a/doc/install/index.md b/doc/install/index.md
index 782cd3bddd8..4f7adb99f87 100644
--- a/doc/install/index.md
+++ b/doc/install/index.md
@@ -13,9 +13,11 @@ To get the best experience, you should balance performance, reliability,
ease of administration (backups, upgrades, and troubleshooting) with the cost of hosting.
<!-- markdownlint-disable MD044 -->
+
| | | |
|--|--|--|
| [**Installation system requirements**](requirements.md) **{chevron-right}**<br><br> Prerequisites for installation. | [**Installation methods**](install_methods.md) **{chevron-right}**<br><br> Linux, Helm, Docker, Operator, source, or scripts. | [**Install GitLab on a cloud provider**](cloud_providers.md) **{chevron-right}**<br><br> AWS, Google Cloud Platform, Azure. |
| [**Offline GitLab**](../topics/offline/index.md) **{chevron-right}**<br><br> Isolated installation. | [**Reference architectures**](../administration/reference_architectures/index.md) **{chevron-right}**<br><br> Recommended deployments at scale. | [**Upgrade GitLab**](../update/index.md) **{chevron-right}**<br><br> Latest version instructions. |
| [**Install GitLab Runner**](https://docs.gitlab.com/runner/install/) **{chevron-right}**<br><br> Software for CI/CD jobs. | [**Configure GitLab Runner**](https://docs.gitlab.com/runner/configuration/) **{chevron-right}**<br><br> Config.toml, certificates, autoscaling, proxy setup. | |
+
<!-- markdownlint-enable MD044 -->
diff --git a/doc/user/project/integrations/beyond_identity.md b/doc/user/project/integrations/beyond_identity.md
new file mode 100644
index 00000000000..9f955ea3811
--- /dev/null
+++ b/doc/user/project/integrations/beyond_identity.md
@@ -0,0 +1,35 @@
+---
+stage: Create
+group: Source Code
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Beyond Identity **(FREE ALL)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/431433) in GitLab 16.9.
+
+Configure GitLab to verify GPG keys issued by [Beyond Identity](https://www.beyondidentity.com/)
+added to a user profile.
+
+## Set up the Beyond Identity integration for your instance
+
+Prerequisites:
+
+- You must have administrator access to the GitLab instance.
+- The email address used in the GitLab profile must be the same as the email assigned to the key in the Beyond Identity Authenticator.
+- You must have a Beyond Identity API token. You can request it from their Sales Engineer.
+
+To enable the Beyond Identity integration for your instance:
+
+1. Sign in to GitLab as an administrator.
+1. On the left sidebar, at the bottom, select **Admin Area**.
+1. Select **Settings > Integrations**.
+1. Select **Beyond Identity**.
+1. Under **Enable integration**, select the **Active** checkbox.
+1. In **API token**, paste the API token you received from Beyond Identity.
+1. Select **Save changes**.
+
+The Beyond Identity integration for your instance is now enabled.
+When a user adds a GPG key to their profile, the key is verified.
+If the key wasn't issued by the Beyond Identity Authenticator or the email used in their GitLab
+profile is different from the email assigned to the key in the Beyond Identity Authenticator, it's rejected.
diff --git a/lib/gitlab/beyond_identity/client.rb b/lib/gitlab/beyond_identity/client.rb
new file mode 100644
index 00000000000..c9e47eb8305
--- /dev/null
+++ b/lib/gitlab/beyond_identity/client.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BeyondIdentity
+ class Client
+ API_URL = "https://api.byndid.com/key-mgmt/v0/gpg/key/authorization/git-commit-signing"
+
+ Error = Class.new(StandardError)
+
+ attr_reader :integration
+
+ def initialize(integration)
+ raise Error, 'integration is not activated' unless integration.activated?
+
+ @integration = integration
+ end
+
+ def execute(params)
+ options = { headers: headers, query: params }
+ response = Gitlab::HTTP.get(API_URL, options)
+ body = Gitlab::Json.parse(response.body) || {}
+
+ raise Error, body.dig('error', 'message') unless response.success?
+ raise Error, "authorization denied: #{body['message']}" unless body['authorized']
+
+ body
+ rescue JSON::ParserError
+ raise Error, 'invalid response format'
+ end
+
+ private
+
+ def headers
+ {
+ 'Content-Type': 'application/json',
+ Authorization: "Bearer #{integration.token}"
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 894811ecd3c..3936ac57ecc 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -80,7 +80,7 @@ module Gitlab
end
def blank_ref?(ref)
- ref == SHA1_BLANK_SHA
+ ref == SHA1_BLANK_SHA || ref == SHA256_BLANK_SHA
end
def commit_id?(ref)
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index a8e680e539b..8790e20cd19 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -299,9 +299,9 @@ module Gitlab
@old_path = encode!(gitaly_diff.from_path.dup)
@a_mode = gitaly_diff.old_mode.to_s(8)
@b_mode = gitaly_diff.new_mode.to_s(8)
- @new_file = gitaly_diff.from_id == SHA1_BLANK_SHA
+ @new_file = Gitlab::Git.blank_ref?(gitaly_diff.from_id)
@renamed_file = gitaly_diff.from_path != gitaly_diff.to_path
- @deleted_file = gitaly_diff.to_id == SHA1_BLANK_SHA
+ @deleted_file = Gitlab::Git.blank_ref?(gitaly_diff.to_id)
@too_large = gitaly_diff.too_large if gitaly_diff.respond_to?(:too_large)
gitaly_overflow = gitaly_diff.try(:overflow_marker)
@overflow = Diff.collect_patch_overage? && gitaly_overflow
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 1bf796e167d..dcb384e31d4 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -398,7 +398,7 @@ module Gitlab
end
def new_blobs(newrevs, dynamic_timeout: nil)
- newrevs = Array.wrap(newrevs).reject { |rev| rev.blank? || rev == ::Gitlab::Git::SHA1_BLANK_SHA }
+ newrevs = Array.wrap(newrevs).reject { |rev| rev.blank? || Gitlab::Git.blank_ref?(rev) }
return [] if newrevs.empty?
newrevs = newrevs.uniq.sort
@@ -416,7 +416,7 @@ module Gitlab
# GitalyClient.medium_timeout and dynamic timeout if the dynamic
# timeout is set, otherwise it'll always use the medium timeout.
def blobs(revisions, with_paths: false, dynamic_timeout: nil)
- revisions = revisions.reject { |rev| rev.blank? || rev == ::Gitlab::Git::SHA1_BLANK_SHA }
+ revisions = revisions.reject { |rev| rev.blank? || Gitlab::Git.blank_ref?(rev) }
return [] if revisions.blank?
@@ -458,7 +458,7 @@ module Gitlab
@raw_changes_between[[old_rev, new_rev]] ||=
begin
- return [] if new_rev.blank? || new_rev == Gitlab::Git::SHA1_BLANK_SHA
+ return [] if new_rev.blank? || Gitlab::Git.blank_ref?(new_rev)
wrapped_gitaly_errors do
gitaly_repository_client.raw_changes_between(old_rev, new_rev)
diff --git a/lib/gitlab/patch/database_config.rb b/lib/gitlab/patch/database_config.rb
index 33be63a31c0..6a10dd6f6a2 100644
--- a/lib/gitlab/patch/database_config.rb
+++ b/lib/gitlab/patch/database_config.rb
@@ -55,7 +55,14 @@ module Gitlab
"database.yml: Execution of `#{command}` failed with exit code #{exit_status}. Output: #{output}"
end
- YAML.safe_load(output).deep_stringify_keys
+ parsed_output = YAML.safe_load(output)
+
+ unless parsed_output.is_a?(Hash)
+ raise CommandExecutionError,
+ "database.yml: The output of `#{command}` must be a Hash, #{parsed_output.class} given. Output: #{parsed_output}"
+ end
+
+ parsed_output.deep_stringify_keys
rescue Psych::SyntaxError => e
error_message = <<~MSG
database.yml: Execution of `#{command}` generated invalid yaml.
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index 80f3e8418ba..a106ed3884e 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -210,7 +210,14 @@ module Gitlab
"Redis: Execution of `#{command}` failed with exit code #{exit_status}. Output: #{output}"
end
- YAML.safe_load(output).deep_symbolize_keys
+ parsed_output = YAML.safe_load(output)
+
+ unless parsed_output.is_a?(Hash)
+ raise CommandExecutionError,
+ "Redis: The output of `#{command}` must be a Hash, #{parsed_output.class} given. Output: #{parsed_output}"
+ end
+
+ parsed_output.deep_symbolize_keys
rescue Psych::SyntaxError => e
error_message = <<~MSG
Redis: Execution of `#{command}` generated invalid yaml.
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 92bb70a880b..e04e50bc347 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4489,6 +4489,18 @@ msgstr ""
msgid "AiAgents|AI agent"
msgstr ""
+msgid "AiAgents|Agent Name"
+msgstr ""
+
+msgid "AiAgents|Create and manage your AI Agents"
+msgstr ""
+
+msgid "AiAgents|Create your own AI Agents"
+msgstr ""
+
+msgid "AiAgents|Get started"
+msgstr ""
+
msgid "Akismet"
msgstr ""
@@ -7745,6 +7757,12 @@ msgstr ""
msgid "BetaBadge|What's Beta?"
msgstr ""
+msgid "BeyondIdentityService|API Token. User must have access to `git-commit-signing` endpoint."
+msgstr ""
+
+msgid "BeyondIdentity|Verify that GPG keys are authorized by Beyond Identity Authenticator."
+msgstr ""
+
msgid "Bi-weekly code coverage"
msgstr ""
@@ -10555,7 +10573,7 @@ msgstr ""
msgid "CiCatalog|We want to help you create and manage pipeline component repositories, while also making it easier to reuse pipeline configurations. Let us know how we're doing!"
msgstr ""
-msgid "CiCatalog|Your resources"
+msgid "CiCatalog|Your groups"
msgstr ""
msgid "CiCdAnalytics|Date range: %{range}"
@@ -31334,6 +31352,9 @@ msgstr ""
msgid "MlModelRegistry|Failed to load model versions with error: %{message}"
msgstr ""
+msgid "MlModelRegistry|Failed to load model with error: %{message}"
+msgstr ""
+
msgid "MlModelRegistry|ID"
msgstr ""
@@ -38294,6 +38315,9 @@ msgstr ""
msgid "ProjectService|Enter new API key"
msgstr ""
+msgid "ProjectService|Enter new API token"
+msgstr ""
+
msgid "ProjectService|Enter new password"
msgstr ""
@@ -38312,6 +38336,9 @@ msgstr ""
msgid "ProjectService|Leave blank to use your current API key."
msgstr ""
+msgid "ProjectService|Leave blank to use your current API token."
+msgstr ""
+
msgid "ProjectService|Leave blank to use your current password"
msgstr ""
@@ -54009,6 +54036,9 @@ msgstr ""
msgid "Verify code"
msgstr ""
+msgid "Verify that GPG keys are authorized by Beyond Identity Authenticator. %{docs_link}"
+msgstr ""
+
msgid "Version"
msgstr ""
diff --git a/package.json b/package.json
index 098de717fec..e13ce6b37c9 100644
--- a/package.json
+++ b/package.json
@@ -285,7 +285,7 @@
"stylelint": "^16.1.0",
"swagger-cli": "^4.0.4",
"timezone-mock": "^1.0.8",
- "vite": "^5.0.11",
+ "vite": "^5.0.12",
"vite-plugin-ruby": "^5.0.0",
"vue-loader-vue3": "npm:vue-loader@17",
"vue-test-utils-compat": "0.0.14",
diff --git a/qa/Gemfile b/qa/Gemfile
index 4ca65d78aac..72ce6cfe43c 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -39,7 +39,7 @@ gem 'chemlab-library-www-gitlab-com', '~> 0.1', '>= 0.1.1'
# dependencies for jenkins client
gem 'nokogiri', '~> 1.16'
-gem 'deprecation_toolkit', '~> 2.0.4', require: false
+gem 'deprecation_toolkit', '~> 2.1.0', require: false
gem 'factory_bot', '~> 6.3.0'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 0040424d7f4..126061e83cb 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -71,8 +71,8 @@ GEM
crass (1.0.6)
debug_inspector (1.1.0)
declarative (0.0.20)
- deprecation_toolkit (2.0.4)
- activesupport (>= 5.2)
+ deprecation_toolkit (2.1.0)
+ activesupport (>= 7.0)
diff-lcs (1.3)
domain_name (0.6.20240107)
erubi (1.12.0)
@@ -348,7 +348,7 @@ DEPENDENCIES
capybara-screenshot (~> 1.0.26)
chemlab (~> 0.11, >= 0.11.1)
chemlab-library-www-gitlab-com (~> 0.1, >= 0.1.1)
- deprecation_toolkit (~> 2.0.4)
+ deprecation_toolkit (~> 2.1.0)
factory_bot (~> 6.3.0)
faker (~> 3.2, >= 3.2.3)
faraday-retry (~> 2.2)
diff --git a/qa/qa/page/organization/new.rb b/qa/qa/page/organization/new.rb
new file mode 100644
index 00000000000..c72a3e6d1b4
--- /dev/null
+++ b/qa/qa/page/organization/new.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Organization
+ class New < QA::Page::Base
+ include QA::Page::Component::Dropdown
+ view 'app/assets/javascripts/organizations/shared/components/new_edit_form.vue' do
+ element 'organization-name'
+ element 'submit-button'
+ end
+
+ # Sets the organization name
+ # @param name [string] name of organization
+ def organization_name=(name)
+ fill_element('organization-name', name)
+ end
+
+ def create_organization
+ click_element('submit-button')
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/organization/show.rb b/qa/qa/page/organization/show.rb
new file mode 100644
index 00000000000..402d481bd0a
--- /dev/null
+++ b/qa/qa/page/organization/show.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Organization
+ class Show < QA::Page::Base
+ include QA::Page::Component::Dropdown
+ view 'app/assets/javascripts/organizations/show/components/organization_avatar.vue' do
+ element 'organization-name'
+ end
+
+ def has_organization?(name)
+ has_element?('organization-name', text: name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/sub_menus/create_new_menu.rb b/qa/qa/page/sub_menus/create_new_menu.rb
index aaf763ac33e..9adb4e5ac8e 100644
--- a/qa/qa/page/sub_menus/create_new_menu.rb
+++ b/qa/qa/page/sub_menus/create_new_menu.rb
@@ -35,6 +35,12 @@ module QA
click_element(:create_menu_item, create_menu_item: 'general_new_group')
end
end
+
+ def go_to_create_organization
+ within_new_item_menu do
+ click_element(:create_menu_item, create_menu_item: 'general_new_organization')
+ end
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/9_data_stores/organization/create_organization_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/organization/create_organization_spec.rb
new file mode 100644
index 00000000000..d61403f40dd
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/9_data_stores/organization/create_organization_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Data Stores',
+ :skip_live_env,
+ :requires_admin,
+ product_group: :tenant_scale,
+ feature_flag: {
+ name: 'ui_for_organizations',
+ scope: :global
+ } do
+ describe 'Organization' do
+ let(:organization_name) { "organization-#{SecureRandom.hex(8)}" }
+
+ around do |example|
+ Runtime::Feature.enable(:ui_for_organizations)
+ example.run
+ Runtime::Feature.disable(:ui_for_organizations)
+ end
+
+ it 'is created', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/436587' do
+ Flow::Login.sign_in
+
+ Page::Main::Menu.perform(&:go_to_create_organization)
+
+ Page::Organization::New.perform do |organization_new|
+ organization_new.organization_name = organization_name
+ organization_new.create_organization
+ end
+
+ Page::Organization::Show.perform do |organization_show|
+ expect(organization_show).to have_organization(organization_name)
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/async_post_migrate_only.rb b/rubocop/cop/migration/async_post_migrate_only.rb
new file mode 100644
index 00000000000..e5b78617691
--- /dev/null
+++ b/rubocop/cop/migration/async_post_migrate_only.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require_relative '../../migration_helpers'
+
+module RuboCop
+ module Cop
+ module Migration
+ # Ensures that asynchronous index helper methods are only called from post migrations.
+ class AsyncPostMigrateOnly < RuboCop::Cop::Base
+ include MigrationHelpers
+
+ MSG = 'Async index operations must be performed in a post-deployment migration.'
+
+ FORBIDDEN_METHODS = %i[
+ prepare_async_index
+ unprepare_async_index
+ prepare_async_index_removal
+ unprepare_async_index
+ ].freeze
+
+ def on_send(node)
+ return unless in_migration?(node)
+ return unless time_enforced?(node)
+ return unless FORBIDDEN_METHODS.include?(node.method_name)
+ return if in_post_deployment_migration?(node)
+
+ add_offense(node, message: MSG)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/groups/settings/integrations_controller_spec.rb b/spec/controllers/groups/settings/integrations_controller_spec.rb
index e21010b76f7..73a9820bdaf 100644
--- a/spec/controllers/groups/settings/integrations_controller_spec.rb
+++ b/spec/controllers/groups/settings/integrations_controller_spec.rb
@@ -55,7 +55,9 @@ RSpec.describe Groups::Settings::IntegrationsController, feature_category: :inte
get :edit,
params: {
group_id: group,
- id: Integration.available_integration_names(include_project_specific: false).sample
+ id: Integration.available_integration_names(
+ include_project_specific: false, include_instance_specific: false
+ ).sample
}
expect(response).to have_gitlab_http_status(:not_found)
@@ -67,7 +69,9 @@ RSpec.describe Groups::Settings::IntegrationsController, feature_category: :inte
group.add_owner(user)
end
- Integration.available_integration_names(include_project_specific: false).each do |integration_name|
+ Integration.available_integration_names(
+ include_project_specific: false, include_instance_specific: false
+ ).each do |integration_name|
context integration_name do
it 'successfully displays the template' do
get :edit, params: { group_id: group, id: integration_name }
diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb
index 1d698e1b4d8..7c52907cefd 100644
--- a/spec/factories/integrations.rb
+++ b/spec/factories/integrations.rb
@@ -292,6 +292,13 @@ FactoryBot.define do
active { true }
end
+ factory :beyond_identity_integration, class: 'Integrations::BeyondIdentity' do
+ type { 'Integrations::BeyondIdentity' }
+ active { true }
+ instance { true }
+ token { 'api-token' }
+ end
+
factory :assembla_integration, class: 'Integrations::Assembla' do
project
token { 'secrettoken' }
diff --git a/spec/features/admin/integrations/instance_integrations_spec.rb b/spec/features/admin/integrations/instance_integrations_spec.rb
index d963aa700eb..5f2ce1d0411 100644
--- a/spec/features/admin/integrations/instance_integrations_spec.rb
+++ b/spec/features/admin/integrations/instance_integrations_spec.rb
@@ -10,7 +10,11 @@ RSpec.describe 'Instance integrations', :js, feature_category: :integrations do
end
it_behaves_like 'integration settings form' do
- let(:integrations) { Integration.find_or_initialize_all_non_project_specific(Integration.for_instance) }
+ let(:integrations) do
+ Integration.find_or_initialize_all_non_project_specific(
+ Integration.for_instance, include_instance_specific: true
+ )
+ end
def navigate_to_integration(integration)
visit_instance_integration(integration.title)
diff --git a/spec/frontend/ci/catalog/components/list/catalog_tabs_spec.js b/spec/frontend/ci/catalog/components/list/catalog_tabs_spec.js
index ea216300017..fe59baf0750 100644
--- a/spec/frontend/ci/catalog/components/list/catalog_tabs_spec.js
+++ b/spec/frontend/ci/catalog/components/list/catalog_tabs_spec.js
@@ -17,7 +17,7 @@ describe('Catalog Tabs', () => {
};
const findAllTab = () => wrapper.findByTestId('resources-all-tab');
- const findYourResourcesTab = () => wrapper.findByTestId('resources-your-tab');
+ const findGroupResourcesTab = () => wrapper.findByTestId('resources-group-tab');
const findLoadingIcons = () => wrapper.findAllComponents(GlLoadingIcon);
const triggerTabChange = (index) => wrapper.findAllComponents(GlTab).at(index).vm.$emit('click');
@@ -52,9 +52,9 @@ describe('Catalog Tabs', () => {
expect(trimText(findAllTab().text())).toBe(`All ${defaultProps.resourceCounts.all}`);
});
- it('renders your resources tab with count', () => {
- expect(trimText(findYourResourcesTab().text())).toBe(
- `Your resources ${defaultProps.resourceCounts.namespaces}`,
+ it('renders group resources tab with count', () => {
+ expect(trimText(findGroupResourcesTab().text())).toBe(
+ `Your groups ${defaultProps.resourceCounts.namespaces}`,
);
});
diff --git a/spec/frontend/design_management/components/design_notes/design_note_spec.js b/spec/frontend/design_management/components/design_notes/design_note_spec.js
index 28b264cede9..7ff488f7fcb 100644
--- a/spec/frontend/design_management/components/design_notes/design_note_spec.js
+++ b/spec/frontend/design_management/components/design_notes/design_note_spec.js
@@ -147,6 +147,31 @@ describe('Design note component', () => {
it('should not display a dropdown if user does not have a permission to delete note', () => {
expect(findDropdown().exists()).toBe(false);
});
+
+ it('should not have a `Deleted user` header', () => {
+ expect(wrapper.text()).not.toContain('A deleted user');
+ });
+ });
+
+ describe('when note has no author', () => {
+ beforeEach(() => {
+ createComponent({
+ props: {
+ note: {
+ ...note,
+ author: null,
+ },
+ },
+ });
+ });
+
+ it('should not render author details', () => {
+ expect(findUserLink().exists()).toBe(false);
+ });
+
+ it('should render a `Deleted user` header', () => {
+ expect(wrapper.text()).toContain('A deleted user');
+ });
});
describe('when user has a permission to edit note', () => {
@@ -280,6 +305,7 @@ describe('Design note component', () => {
...note,
userPermissions: {
adminNote: true,
+ awardEmoji: false,
},
},
},
@@ -297,6 +323,7 @@ describe('Design note component', () => {
...note,
userPermissions: {
adminNote: true,
+ awardEmoji: false,
},
},
},
diff --git a/spec/frontend/ml/model_registry/apps/index_ml_models_spec.js b/spec/frontend/ml/model_registry/apps/index_ml_models_spec.js
index 07d8b4b8b3d..12677470127 100644
--- a/spec/frontend/ml/model_registry/apps/index_ml_models_spec.js
+++ b/spec/frontend/ml/model_registry/apps/index_ml_models_spec.js
@@ -1,55 +1,80 @@
-import { GlBadge, GlButton } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { GlExperimentBadge } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import { IndexMlModels } from '~/ml/model_registry/apps';
import ModelRow from '~/ml/model_registry/components/model_row.vue';
-import Pagination from '~/vue_shared/components/incubation/pagination.vue';
-import SearchBar from '~/ml/model_registry/components/search_bar.vue';
-import { BASE_SORT_FIELDS, MODEL_ENTITIES } from '~/ml/model_registry/constants';
+import { MODEL_ENTITIES } from '~/ml/model_registry/constants';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
import EmptyState from '~/ml/model_registry/components/empty_state.vue';
import ActionsDropdown from '~/ml/model_registry/components/actions_dropdown.vue';
-import { mockModels, startCursor, defaultPageInfo } from '../mock_data';
-
-let wrapper;
-
-const createWrapper = (propsData = {}) => {
- wrapper = shallowMountExtended(IndexMlModels, {
- propsData: {
- models: mockModels,
- pageInfo: defaultPageInfo,
- modelCount: 2,
- createModelPath: 'path/to/create',
- canWriteModelRegistry: false,
- ...propsData,
- },
- });
+import SearchableList from '~/ml/model_registry/components/searchable_list.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import getModelsQuery from '~/ml/model_registry/graphql/queries/get_models.query.graphql';
+import * as Sentry from '~/sentry/sentry_browser_wrapper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { modelsQuery, modelWithOneVersion, modelWithoutVersion } from '../graphql_mock_data';
+
+Vue.use(VueApollo);
+
+const defaultProps = {
+ projectPath: 'path/to/project',
+ createModelPath: 'path/to/create',
+ canWriteModelRegistry: false,
};
-const findModelRow = (index) => wrapper.findAllComponents(ModelRow).at(index);
-const findPagination = () => wrapper.findComponent(Pagination);
-const findEmptyState = () => wrapper.findComponent(EmptyState);
-const findSearchBar = () => wrapper.findComponent(SearchBar);
-const findTitleArea = () => wrapper.findComponent(TitleArea);
-const findModelCountMetadataItem = () => findTitleArea().findComponent(MetadataItem);
-const findBadge = () => wrapper.findComponent(GlBadge);
-const findCreateButton = () => findTitleArea().findComponent(GlButton);
-const findActionsDropdown = () => wrapper.findComponent(ActionsDropdown);
-
describe('ml/model_registry/apps/index_ml_models', () => {
- describe('empty state', () => {
- beforeEach(() => createWrapper({ models: [], pageInfo: defaultPageInfo }));
+ let wrapper;
+ let apolloProvider;
+
+ const createWrapper = ({
+ props = {},
+ resolver = jest.fn().mockResolvedValue(modelsQuery()),
+ } = {}) => {
+ const requestHandlers = [[getModelsQuery, resolver]];
+ apolloProvider = createMockApollo(requestHandlers);
+
+ const propsData = {
+ ...defaultProps,
+ ...props,
+ };
+
+ wrapper = mountExtended(IndexMlModels, {
+ apolloProvider,
+ propsData,
+ });
+ };
- it('shows empty state', () => {
- expect(findEmptyState().props('entityType')).toBe(MODEL_ENTITIES.model);
+ beforeEach(() => {
+ jest.spyOn(Sentry, 'captureException').mockImplementation();
+ });
+
+ const emptyQueryResolver = () => jest.fn().mockResolvedValue(modelsQuery([]));
+
+ const findAllRows = () => wrapper.findAllComponents(ModelRow);
+ const findRow = (index) => findAllRows().at(index);
+ const findEmptyState = () => wrapper.findComponent(EmptyState);
+ const findTitleArea = () => wrapper.findComponent(TitleArea);
+ const findModelCountMetadataItem = () => findTitleArea().findComponent(MetadataItem);
+ const findBadge = () => wrapper.findComponent(GlExperimentBadge);
+ const findCreateButton = () => wrapper.findByTestId('create-model-button');
+ const findActionsDropdown = () => wrapper.findComponent(ActionsDropdown);
+ const findSearchableList = () => wrapper.findComponent(SearchableList);
+
+ describe('header', () => {
+ beforeEach(() => {
+ createWrapper();
});
- it('does not show pagination', () => {
- expect(findPagination().exists()).toBe(false);
+ it('displays the title', () => {
+ expect(findTitleArea().text()).toContain('Model registry');
});
- it('does not show search bar', () => {
- expect(findSearchBar().exists()).toBe(false);
+ it('displays the experiment badge', () => {
+ expect(findBadge().props('helpPageUrl')).toBe(
+ '/help/user/project/ml/model_registry/index.md',
+ );
});
it('renders the extra actions button', () => {
@@ -57,65 +82,155 @@ describe('ml/model_registry/apps/index_ml_models', () => {
});
});
+ describe('empty state', () => {
+ it('shows empty state', async () => {
+ createWrapper({ resolver: emptyQueryResolver() });
+
+ await waitForPromises();
+
+ expect(findEmptyState().props('entityType')).toBe(MODEL_ENTITIES.model);
+ });
+ });
+
describe('create button', () => {
describe('when user has no permission to write model registry', () => {
- it('does not display create button', () => {
- createWrapper();
+ it('does not display create button', async () => {
+ createWrapper({ resolver: emptyQueryResolver() });
+
+ await waitForPromises();
expect(findCreateButton().exists()).toBe(false);
});
});
describe('when user has permission to write model registry', () => {
- it('displays create button', () => {
- createWrapper({ canWriteModelRegistry: true });
+ it('displays create button', async () => {
+ createWrapper({
+ props: { canWriteModelRegistry: true },
+ resolver: emptyQueryResolver(),
+ });
+
+ await waitForPromises();
expect(findCreateButton().attributes().href).toBe('path/to/create');
});
});
});
+ describe('when loading data fails', () => {
+ beforeEach(async () => {
+ const error = new Error('Failure!');
+
+ createWrapper({ resolver: jest.fn().mockRejectedValue(error) });
+
+ await waitForPromises();
+ });
+
+ it('error message is displayed', () => {
+ expect(findSearchableList().props('errorMessage')).toBe(
+ 'Failed to load model with error: Failure!',
+ );
+ });
+
+ it('error is logged in sentry', () => {
+ expect(Sentry.captureException).toHaveBeenCalled();
+ });
+ });
+
describe('with data', () => {
- beforeEach(() => {
+ it('does not show empty state', async () => {
createWrapper();
- });
+ await waitForPromises();
- it('does not show empty state', () => {
expect(findEmptyState().exists()).toBe(false);
});
describe('header', () => {
- it('displays the title', () => {
- expect(findTitleArea().text()).toContain('Model registry');
+ it('sets model metadata item to model count', async () => {
+ createWrapper();
+ await waitForPromises();
+
+ expect(findModelCountMetadataItem().props('text')).toBe('2 models');
});
+ });
- it('displays the experiment badge', () => {
- expect(findBadge().attributes().href).toBe('/help/user/project/ml/model_registry/index.md');
+ describe('shows models', () => {
+ beforeEach(async () => {
+ createWrapper();
+ await waitForPromises();
});
- it('sets model metadata item to model count', () => {
- expect(findModelCountMetadataItem().props('text')).toBe(`2 models`);
+ it('passes items to list', () => {
+ expect(findSearchableList().props('items')).toEqual([
+ modelWithOneVersion,
+ modelWithoutVersion,
+ ]);
});
- });
- it('adds a search bar', () => {
- expect(findSearchBar().props()).toMatchObject({ sortableFields: BASE_SORT_FIELDS });
- });
+ it('displays package version rows', () => {
+ expect(findAllRows()).toHaveLength(2);
+ });
+
+ it('binds the correct props', () => {
+ expect(findRow(0).props()).toMatchObject({
+ model: expect.objectContaining(modelWithOneVersion),
+ });
- describe('model list', () => {
- it('displays the models', () => {
- expect(findModelRow(0).props('model')).toMatchObject(mockModels[0]);
- expect(findModelRow(1).props('model')).toMatchObject(mockModels[1]);
+ expect(findRow(1).props()).toMatchObject({
+ model: expect.objectContaining(modelWithoutVersion),
+ });
});
});
- describe('pagination', () => {
- it('should show', () => {
- expect(findPagination().exists()).toBe(true);
+ describe('when query is updated', () => {
+ let resolver;
+
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(modelsQuery());
+ createWrapper({ resolver });
+ });
+
+ it('when orderBy or sort are not present, use default value', async () => {
+ findSearchableList().vm.$emit('fetch-page', {
+ after: 'eyJpZCI6IjIifQ',
+ first: 30,
+ });
+
+ await waitForPromises();
+
+ expect(resolver).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ fullPath: 'path/to/project',
+ first: 30,
+ name: undefined,
+ orderBy: 'CREATED_AT',
+ sort: 'DESC',
+ after: 'eyJpZCI6IjIifQ',
+ }),
+ );
});
- it('passes pagination to pagination component', () => {
- expect(findPagination().props('startCursor')).toBe(startCursor);
+ it('when orderBy or sort present, updates filters', async () => {
+ findSearchableList().vm.$emit('fetch-page', {
+ after: 'eyJpZCI6IjIifQ',
+ first: 30,
+ orderBy: 'name',
+ sort: 'asc',
+ name: 'something',
+ });
+
+ await waitForPromises();
+
+ expect(resolver).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ fullPath: 'path/to/project',
+ first: 30,
+ name: 'something',
+ orderBy: 'NAME',
+ sort: 'ASC',
+ after: 'eyJpZCI6IjIifQ',
+ }),
+ );
});
});
});
diff --git a/spec/frontend/ml/model_registry/components/model_row_spec.js b/spec/frontend/ml/model_registry/components/model_row_spec.js
index 09729292355..02359949f5a 100644
--- a/spec/frontend/ml/model_registry/components/model_row_spec.js
+++ b/spec/frontend/ml/model_registry/components/model_row_spec.js
@@ -1,38 +1,45 @@
-import { GlLink } from '@gitlab/ui';
+import { GlLink, GlTruncate } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
import ModelRow from '~/ml/model_registry/components/model_row.vue';
-import { mockModels, modelWithoutVersion } from '../mock_data';
+import { modelWithOneVersion, modelWithVersions, modelWithoutVersion } from '../graphql_mock_data';
let wrapper;
-const createWrapper = (model = mockModels[0]) => {
+const createWrapper = (model = modelWithVersions) => {
wrapper = shallowMountExtended(ModelRow, { propsData: { model } });
};
-const findTitleLink = () => wrapper.findAllComponents(GlLink).at(0);
-const findVersionLink = () => wrapper.findAllComponents(GlLink).at(1);
+const findListItem = () => wrapper.findComponent(ListItem);
+const findTitleLink = () => findListItem().findAllComponents(GlLink).at(0);
+const findTruncated = () => findTitleLink().findComponent(GlTruncate);
+const findVersionLink = () => findListItem().findAllComponents(GlLink).at(1);
const findMessage = (message) => wrapper.findByText(message);
describe('ModelRow', () => {
it('Has a link to the model', () => {
createWrapper();
- expect(findTitleLink().text()).toBe(mockModels[0].name);
- expect(findTitleLink().attributes('href')).toBe(mockModels[0].path);
+ expect(findTruncated().props('text')).toBe(modelWithVersions.name);
+ expect(findTitleLink().attributes('href')).toBe(modelWithVersions._links.showPath);
});
it('Shows the latest version and the version count', () => {
createWrapper();
- expect(findVersionLink().text()).toBe(mockModels[0].version);
- expect(findVersionLink().attributes('href')).toBe(mockModels[0].versionPath);
- expect(findMessage('· 3 versions').exists()).toBe(true);
+ expect(findVersionLink().text()).toBe(modelWithVersions.latestVersion.version);
+ expect(findVersionLink().attributes('href')).toBe(
+ modelWithVersions.latestVersion._links.showPath,
+ );
+ expect(findMessage('· 2 versions').exists()).toBe(true);
});
it('Shows the latest version and no version count if it has only 1 version', () => {
- createWrapper(mockModels[1]);
+ createWrapper(modelWithOneVersion);
- expect(findVersionLink().text()).toBe(mockModels[1].version);
- expect(findVersionLink().attributes('href')).toBe(mockModels[1].versionPath);
+ expect(findVersionLink().text()).toBe(modelWithOneVersion.latestVersion.version);
+ expect(findVersionLink().attributes('href')).toBe(
+ modelWithOneVersion.latestVersion._links.showPath,
+ );
expect(findMessage('· 1 version').exists()).toBe(true);
});
diff --git a/spec/frontend/ml/model_registry/components/searchable_list_spec.js b/spec/frontend/ml/model_registry/components/searchable_list_spec.js
index ea58a9a830a..67c61a0d583 100644
--- a/spec/frontend/ml/model_registry/components/searchable_list_spec.js
+++ b/spec/frontend/ml/model_registry/components/searchable_list_spec.js
@@ -3,6 +3,9 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SearchableList from '~/ml/model_registry/components/searchable_list.vue';
import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import { BASE_SORT_FIELDS } from '~/ml/model_registry/constants';
+import * as urlHelpers from '~/lib/utils/url_utility';
import { defaultPageInfo } from '../mock_data';
describe('ml/model_registry/components/searchable_list.vue', () => {
@@ -14,12 +17,23 @@ describe('ml/model_registry/components/searchable_list.vue', () => {
const findEmptyState = () => wrapper.findByTestId('empty-state-slot');
const findFirstRow = () => wrapper.findByTestId('element');
const findRows = () => wrapper.findAllByTestId('element');
+ const findSearch = () => wrapper.findComponent(RegistrySearch);
+
+ const expectedFirstPage = {
+ after: 'eyJpZCI6IjIifQ',
+ first: 30,
+ last: null,
+ orderBy: 'created_at',
+ sort: 'desc',
+ };
const defaultProps = {
items: ['a', 'b', 'c'],
pageInfo: defaultPageInfo,
isLoading: false,
errorMessage: '',
+ showSearch: false,
+ sortableFields: [],
};
const mountComponent = (props = {}) => {
@@ -143,6 +157,12 @@ describe('ml/model_registry/components/searchable_list.vue', () => {
describe('when user interacts with pagination', () => {
beforeEach(() => mountComponent());
+ it('when it is created emits fetch-page to get first page', () => {
+ mountComponent({ showSearch: true, sortableFields: BASE_SORT_FIELDS });
+
+ expect(wrapper.emitted('fetch-page')).toEqual([[expectedFirstPage]]);
+ });
+
it('when list emits next-page emits fetchPage with correct pageInfo', () => {
findRegistryList().vm.$emit('next-page');
@@ -150,9 +170,11 @@ describe('ml/model_registry/components/searchable_list.vue', () => {
after: 'eyJpZCI6IjIifQ',
first: 30,
last: null,
+ orderBy: 'created_at',
+ sort: 'desc',
};
- expect(wrapper.emitted('fetch-page')).toEqual([[expectedNewPageInfo]]);
+ expect(wrapper.emitted('fetch-page')).toEqual([[expectedFirstPage], [expectedNewPageInfo]]);
});
it('when list emits prev-page emits fetchPage with correct pageInfo', () => {
@@ -162,9 +184,77 @@ describe('ml/model_registry/components/searchable_list.vue', () => {
before: 'eyJpZCI6IjE2In0',
first: null,
last: 30,
+ orderBy: 'created_at',
+ sort: 'desc',
+ };
+
+ expect(wrapper.emitted('fetch-page')).toEqual([[expectedFirstPage], [expectedNewPageInfo]]);
+ });
+ });
+
+ describe('search', () => {
+ beforeEach(() => {
+ jest.spyOn(urlHelpers, 'updateHistory').mockImplementation(() => {});
+ });
+
+ it('does not show search bar when showSearch is false', () => {
+ mountComponent({ showSearch: false });
+
+ expect(findSearch().exists()).toBe(false);
+ });
+
+ it('mounts search correctly', () => {
+ mountComponent({ showSearch: true, sortableFields: BASE_SORT_FIELDS });
+
+ expect(findSearch().props()).toMatchObject({
+ filters: [],
+ sorting: {
+ orderBy: 'created_at',
+ sort: 'desc',
+ },
+ sortableFields: BASE_SORT_FIELDS,
+ });
+ });
+
+ it('on search submit, emits fetch-page with correct variables', () => {
+ mountComponent({ showSearch: true, sortableFields: BASE_SORT_FIELDS });
+
+ findSearch().vm.$emit('filter:submit');
+
+ const expectedVariables = {
+ orderBy: 'created_at',
+ sort: 'desc',
+ };
+
+ expect(wrapper.emitted('fetch-page')).toEqual([[expectedFirstPage], [expectedVariables]]);
+ });
+
+ it('on sorting changed, emits fetch-page with correct variables', () => {
+ mountComponent({ showSearch: true, sortableFields: BASE_SORT_FIELDS });
+
+ const orderBy = 'name';
+ findSearch().vm.$emit('sorting:changed', { orderBy });
+
+ const expectedVariables = {
+ orderBy: 'name',
+ sort: 'desc',
+ };
+
+ expect(wrapper.emitted('fetch-page')).toEqual([[expectedFirstPage], [expectedVariables]]);
+ });
+
+ it('on direction changed, emits fetch-page with correct variables', () => {
+ mountComponent({ showSearch: true, sortableFields: BASE_SORT_FIELDS });
+
+ const sort = 'asc';
+ findSearch().vm.$emit('sorting:changed', { sort });
+
+ const expectedVariables = {
+ orderBy: 'created_at',
+ sort: 'asc',
};
- expect(wrapper.emitted('fetch-page')).toEqual([[expectedNewPageInfo]]);
+ expect(wrapper.emitted('fetch-page')).toEqual([[expectedFirstPage], [expectedVariables]]);
});
});
});
diff --git a/spec/frontend/ml/model_registry/graphql_mock_data.js b/spec/frontend/ml/model_registry/graphql_mock_data.js
index 27424fbf0df..b44963577bf 100644
--- a/spec/frontend/ml/model_registry/graphql_mock_data.js
+++ b/spec/frontend/ml/model_registry/graphql_mock_data.js
@@ -138,3 +138,64 @@ export const createModelResponses = {
},
},
};
+
+export const modelWithVersions = {
+ id: 'gid://gitlab/Ml::Model/1',
+ name: 'model_1',
+ versionCount: 2,
+ createdAt: '2023-12-06T12:41:48Z',
+ latestVersion: {
+ id: 'gid://gitlab/Ml::ModelVersion/1',
+ version: '1.0.0',
+ _links: {
+ showPath: '/my_project/-/ml/models/1/versions/1',
+ },
+ },
+ _links: {
+ showPath: '/my_project/-/ml/models/1',
+ },
+};
+
+export const modelWithOneVersion = {
+ id: 'gid://gitlab/Ml::Model/2',
+ name: 'model_2',
+ versionCount: 1,
+ createdAt: '2023-12-06T12:41:48Z',
+ latestVersion: {
+ id: 'gid://gitlab/Ml::ModelVersion/1',
+ version: '1.0.0',
+ _links: {
+ showPath: '/my_project/-/ml/models/2/versions/1',
+ },
+ },
+ _links: {
+ showPath: '/my_project/-/ml/models/2',
+ },
+};
+
+export const modelWithoutVersion = {
+ id: 'gid://gitlab/Ml::Model/3',
+ name: 'model_3',
+ versionCount: 0,
+ latestVersion: null,
+ createdAt: '2023-12-06T12:41:48Z',
+ _links: {
+ showPath: '/my_project/-/ml/models/3',
+ },
+};
+
+export const modelsQuery = (
+ models = [modelWithOneVersion, modelWithoutVersion],
+ pageInfo = graphqlPageInfo,
+) => ({
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/1',
+ mlModels: {
+ count: models.length,
+ nodes: models,
+ pageInfo,
+ },
+ },
+ },
+});
diff --git a/spec/frontend/work_items/components/notes/work_item_note_spec.js b/spec/frontend/work_items/components/notes/work_item_note_spec.js
index 2b4c9604382..330eb0430f3 100644
--- a/spec/frontend/work_items/components/notes/work_item_note_spec.js
+++ b/spec/frontend/work_items/components/notes/work_item_note_spec.js
@@ -478,4 +478,23 @@ describe('Work Item Note', () => {
expect(groupWorkItemResponseHandler).toHaveBeenCalled();
});
});
+
+ describe('when note has no author', () => {
+ beforeEach(() => {
+ createComponent({
+ note: {
+ ...mockWorkItemCommentNote,
+ author: null,
+ },
+ });
+ });
+
+ it('should pass correct author prop to note header', () => {
+ expect(findNoteHeader().props('author')).toEqual({});
+ });
+
+ it('should not allow assigning to comment author', () => {
+ expect(findNoteActions().props('showAssignUnassign')).toBe(false);
+ });
+ });
});
diff --git a/spec/graphql/resolvers/ml/find_models_resolver_spec.rb b/spec/graphql/resolvers/ml/find_models_resolver_spec.rb
index ce85dd62515..b19d066c369 100644
--- a/spec/graphql/resolvers/ml/find_models_resolver_spec.rb
+++ b/spec/graphql/resolvers/ml/find_models_resolver_spec.rb
@@ -9,20 +9,21 @@ RSpec.describe Resolvers::Ml::FindModelsResolver, feature_category: :mlops do
let_it_be(:project) { create(:project) }
let_it_be(:models) { create_list(:ml_models, 2, project: project) }
let_it_be(:model_in_another_project) { create(:ml_models) }
- let_it_be(:user) { project.owner }
+ let_it_be(:owner) { project.owner }
+ let(:current_user) { owner }
let(:args) { { name: 'model', orderBy: 'CREATED_AT', sort: 'desc', invalid: 'blah' } }
let(:read_model_registry) { true }
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?)
- .with(user, :read_model_registry, project)
+ .with(current_user, :read_model_registry, project)
.and_return(read_model_registry)
end
subject(:resolve_models) do
- force(resolve(described_class, obj: project, ctx: { current_user: user }, args: args))&.to_a
+ force(resolve(described_class, obj: project, ctx: { current_user: current_user }, args: args))&.to_a
end
context 'when user is allowed and model exists' do
@@ -36,6 +37,19 @@ sort: 'desc' })
resolve_models
end
+
+ context 'when user is nil' do
+ let(:current_user) { nil }
+
+ it 'processes the request' do
+ expect(::Projects::Ml::ModelFinder).to receive(:new)
+ .with(project, { name: 'model', order_by: 'created_at',
+ sort: 'desc' })
+ .and_call_original
+
+ resolve_models
+ end
+ end
end
context 'when user does not have permission' do
diff --git a/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb b/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb
index 1da208eb4d8..a992f2dedd5 100644
--- a/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb
+++ b/spec/graphql/resolvers/ml/model_detail_resolver_spec.rb
@@ -8,22 +8,29 @@ RSpec.describe Resolvers::Ml::ModelDetailResolver, feature_category: :mlops do
describe '#resolve' do
let_it_be(:project) { create(:project) }
let_it_be(:model) { create(:ml_models, project: project) }
- let_it_be(:user) { project.owner }
+ let_it_be(:owner) { project.owner }
+ let(:current_user) { owner }
let(:args) { { id: global_id_of(model) } }
let(:read_model_registry) { true }
+ subject { force(resolve(described_class, ctx: { current_user: current_user }, args: args)) }
+
before do
allow(Ability).to receive(:allowed?).and_call_original
allow(Ability).to receive(:allowed?)
- .with(user, :read_model_registry, project)
+ .with(current_user, :read_model_registry, project)
.and_return(read_model_registry)
end
- subject { force(resolve(described_class, ctx: { current_user: user }, args: args)) }
-
context 'when user is allowed and model exists' do
it { is_expected.to eq(model) }
+
+ context 'when user is nil' do
+ let(:current_user) { nil }
+
+ it { is_expected.to eq(model) }
+ end
end
context 'when user does not have permission' do
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index bf6b5ec5173..aab63ea0f70 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -485,6 +485,7 @@ RSpec.describe AvatarsHelper, feature_category: :source_code_management do
gl-avatar-s32\s+
gl-avatar-circle\s+
gl-mr-3\s+
+ gl-rounded-base!\s+
gl-avatar-identicon\s+
gl-avatar-identicon-bg\d+"\s*>
\s*F\s*
diff --git a/spec/helpers/projects/ml/model_registry_helper_spec.rb b/spec/helpers/projects/ml/model_registry_helper_spec.rb
new file mode 100644
index 00000000000..2180d4388ca
--- /dev/null
+++ b/spec/helpers/projects/ml/model_registry_helper_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'rspec'
+
+require 'spec_helper'
+require 'mime/types'
+
+RSpec.describe Projects::Ml::ModelRegistryHelper, feature_category: :mlops do
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:user) { project.owner }
+
+ describe '#index_ml_model_data' do
+ subject(:parsed) { Gitlab::Json.parse(helper.index_ml_model_data(project, user)) }
+
+ it 'generates the correct data' do
+ is_expected.to eq({
+ 'projectPath' => project.full_path,
+ 'createModelPath' => "/#{project.full_path}/-/ml/models/new",
+ 'canWriteModelRegistry' => true,
+ 'mlflowTrackingUrl' => "http://localhost/api/v4/projects/#{project.id}/ml/mlflow/api/2.0/mlflow/"
+ })
+ end
+
+ context 'when user does not have write access to model registry' do
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?)
+ .with(user, :write_model_registry, project)
+ .and_return(false)
+ end
+
+ it 'canWriteModelRegistry is false' do
+ expect(parsed['canWriteModelRegistry']).to eq(false)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/beyond_identity/client_spec.rb b/spec/lib/gitlab/beyond_identity/client_spec.rb
new file mode 100644
index 00000000000..250db1bbb23
--- /dev/null
+++ b/spec/lib/gitlab/beyond_identity/client_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::BeyondIdentity::Client, feature_category: :source_code_management do
+ let_it_be_with_reload(:integration) { create(:beyond_identity_integration) }
+
+ let(:stubbed_response) do
+ { 'authorized' => true }.to_json
+ end
+
+ let(:params) { { key_id: 'key-id', committer_email: 'email@example.com' } }
+ let(:status) { 200 }
+
+ let!(:request) do
+ stub_request(:get, ::Gitlab::BeyondIdentity::Client::API_URL).with(
+ query: params,
+ headers: { 'Content-Type' => 'application/json', Authorization: "Bearer #{integration.token}" }
+ ).to_return(
+ status: status,
+ body: stubbed_response
+ )
+ end
+
+ subject(:client) { described_class.new(integration) }
+
+ context 'when integration is not activated' do
+ it 'raises a config error' do
+ integration.active = false
+
+ expect do
+ client.execute(params)
+ end.to raise_error(::Gitlab::BeyondIdentity::Client::Error).with_message(
+ 'integration is not activated'
+ )
+
+ expect(request).not_to have_been_requested
+ end
+ end
+
+ it 'executes successfully' do
+ expect(client.execute(params)).to eq({ 'authorized' => true })
+ expect(request).to have_been_requested
+ end
+
+ context 'with invalid response' do
+ let(:stubbed_response) { 'invalid' }
+
+ it 'executes successfully' do
+ expect { client.execute(params) }.to raise_error(
+ ::Gitlab::BeyondIdentity::Client::Error
+ ).with_message('invalid response format')
+ end
+ end
+
+ context 'with an error response' do
+ let(:stubbed_response) do
+ { 'error' => { 'message' => 'gpg_key is invalid' } }.to_json
+ end
+
+ let(:status) { 400 }
+
+ it 'returns an error' do
+ expect { client.execute(params) }.to raise_error(
+ ::Gitlab::BeyondIdentity::Client::Error
+ ).with_message('gpg_key is invalid')
+ end
+ end
+
+ context 'when key is unauthorized' do
+ let(:stubbed_response) do
+ { 'unauthorized' => false, 'message' => 'key is unauthorized' }.to_json
+ end
+
+ it 'returns an error' do
+ expect { client.execute(params) }.to raise_error(
+ ::Gitlab::BeyondIdentity::Client::Error
+ ).with_message('authorization denied: key is unauthorized')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git_spec.rb b/spec/lib/gitlab/git_spec.rb
index 61f66c9cd0c..354ef377c94 100644
--- a/spec/lib/gitlab/git_spec.rb
+++ b/spec/lib/gitlab/git_spec.rb
@@ -68,4 +68,20 @@ RSpec.describe Gitlab::Git do
end
end
end
+
+ describe '.blank_ref?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:sha, :result) do
+ '4b825dc642cb6eb9a060e54bf8d69288fbee4904' | false
+ '0000000000000000000000000000000000000000' | true
+ '0000000000000000000000000000000000000000000000000000000000000000' | true
+ end
+
+ with_them do
+ it 'returns the expected result' do
+ expect(described_class.blank_ref?(sha)).to eq(result)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 9e83b7d85e9..acf39a02b28 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -585,6 +585,7 @@ project:
- prometheus_integration
- assembla_integration
- asana_integration
+- beyond_identity_integration
- slack_integration
- microsoft_teams_integration
- mattermost_integration
diff --git a/spec/lib/gitlab/instrumentation/connection_pool_spec.rb b/spec/lib/gitlab/instrumentation/connection_pool_spec.rb
index b7cab2e9900..ce869659c67 100644
--- a/spec/lib/gitlab/instrumentation/connection_pool_spec.rb
+++ b/spec/lib/gitlab/instrumentation/connection_pool_spec.rb
@@ -4,6 +4,10 @@ require 'spec_helper'
require 'support/helpers/rails_helpers'
RSpec.describe Gitlab::Instrumentation::ConnectionPool, feature_category: :redis do
+ before do
+ ::ConnectionPool.prepend(::Gitlab::Instrumentation::ConnectionPool)
+ end
+
let(:option) { { name: 'test', size: 5 } }
let(:pool) { ConnectionPool.new(option) { 'nothing' } }
diff --git a/spec/lib/gitlab/patch/database_config_spec.rb b/spec/lib/gitlab/patch/database_config_spec.rb
index 73452853050..eb987319160 100644
--- a/spec/lib/gitlab/patch/database_config_spec.rb
+++ b/spec/lib/gitlab/patch/database_config_spec.rb
@@ -143,6 +143,22 @@ RSpec.describe Gitlab::Patch::DatabaseConfig do
end
end
+ context 'when the parsed external command output returns invalid hash' do
+ before do
+ allow(Gitlab::Popen)
+ .to receive(:popen)
+ .and_return(["hello", 0])
+ end
+
+ it 'raises an error' do
+ expect { configuration.database_configuration }
+ .to raise_error(
+ Gitlab::Patch::DatabaseConfig::CommandExecutionError,
+ %r{database.yml: The output of `/opt/database-config.sh` must be a Hash, String given}
+ )
+ end
+ end
+
context 'when the external command fails' do
before do
allow(Gitlab::Popen).to receive(:popen).and_return(["", 125])
diff --git a/spec/models/integration_spec.rb b/spec/models/integration_spec.rb
index 3a96de4efe2..8e7729b1468 100644
--- a/spec/models/integration_spec.rb
+++ b/spec/models/integration_spec.rb
@@ -284,14 +284,29 @@ RSpec.describe Integration, feature_category: :integrations do
describe '.find_or_initialize_all_non_project_specific' do
shared_examples 'integration instances' do
- it 'returns the available integration instances' do
- expect(described_class.find_or_initialize_all_non_project_specific(described_class.for_instance).map(&:to_param))
- .to match_array(described_class.available_integration_names(include_project_specific: false))
- end
+ [false, true].each do |include_instance_specific|
+ context "with include_instance_specific value equal to #{include_instance_specific}" do
+ it 'returns the available integration instances' do
+ integrations = described_class.find_or_initialize_all_non_project_specific(
+ described_class.for_instance, include_instance_specific: include_instance_specific
+ ).map(&:to_param)
+
+ expect(integrations).to match_array(
+ described_class.available_integration_names(
+ include_project_specific: false,
+ include_instance_specific: include_instance_specific)
+ )
+ end
- it 'does not create integration instances' do
- expect { described_class.find_or_initialize_all_non_project_specific(described_class.for_instance) }
- .not_to change(described_class, :count)
+ it 'does not create integration instances' do
+ expect do
+ described_class.find_or_initialize_all_non_project_specific(
+ described_class.for_instance,
+ include_instance_specific: include_instance_specific
+ )
+ end.not_to change(described_class, :count)
+ end
+ end
end
end
@@ -990,6 +1005,7 @@ RSpec.describe Integration, feature_category: :integrations do
allow(described_class).to receive(:integration_names).and_return(%w[foo])
allow(described_class).to receive(:project_specific_integration_names).and_return(['bar'])
allow(described_class).to receive(:dev_integration_names).and_return(['baz'])
+ allow(described_class).to receive(:instance_specific_integration_names).and_return(['instance-specific'])
end
it { is_expected.to include('foo', 'bar', 'baz') }
@@ -997,16 +1013,23 @@ RSpec.describe Integration, feature_category: :integrations do
context 'when `include_project_specific` is false' do
subject { described_class.available_integration_names(include_project_specific: false) }
- it { is_expected.to include('foo', 'baz') }
+ it { is_expected.to include('foo', 'baz', 'instance-specific') }
it { is_expected.not_to include('bar') }
end
context 'when `include_dev` is false' do
subject { described_class.available_integration_names(include_dev: false) }
- it { is_expected.to include('foo', 'bar') }
+ it { is_expected.to include('foo', 'bar', 'instance-specific') }
it { is_expected.not_to include('baz') }
end
+
+ context 'when `include_instance_specific` is false' do
+ subject { described_class.available_integration_names(include_instance_specific: false) }
+
+ it { is_expected.to include('foo', 'baz', 'bar') }
+ it { is_expected.not_to include('instance-specific') }
+ end
end
describe '.project_specific_integration_names' do
diff --git a/spec/models/integrations/beyond_identity_spec.rb b/spec/models/integrations/beyond_identity_spec.rb
new file mode 100644
index 00000000000..29d428b5a03
--- /dev/null
+++ b/spec/models/integrations/beyond_identity_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::BeyondIdentity, feature_category: :integrations do
+ subject(:integration) { create(:beyond_identity_integration) }
+
+ describe 'validations' do
+ context 'when inactive' do
+ before do
+ integration.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:token) }
+ end
+
+ context 'when active' do
+ it { is_expected.to validate_presence_of(:token) }
+ end
+ end
+
+ describe 'attributes' do
+ it 'configures attributes' do
+ is_expected.not_to be_inheritable
+ expect(integration.supported_events).to be_blank
+ expect(integration.to_param).to eq('beyond_identity')
+ expect(integration.title).to eq('Beyond Identity')
+
+ expect(integration.description).to eq(
+ 'Verify that GPG keys are authorized by Beyond Identity Authenticator.'
+ )
+
+ expect(integration.help).to include(
+ 'Verify that GPG keys are authorized by Beyond Identity Authenticator.'
+ )
+ end
+ end
+
+ describe '.api_fields' do
+ it 'returns api fields' do
+ expect(described_class.api_fields).to eq([{
+ required: true,
+ name: :token,
+ type: String,
+ desc: 'API Token. User must have access to `git-commit-signing` endpoint.'
+ }])
+ end
+ end
+
+ describe '#execute' do
+ it 'performs a request to beyond identity service' do
+ params = { key_id: 'key-id', committer_email: 'email' }
+ response = 'response'
+
+ expect_next_instance_of(::Gitlab::BeyondIdentity::Client) do |instance|
+ expect(instance).to receive(:execute).with(params).and_return(response)
+ end
+
+ expect(integration.execute(params)).to eq(response)
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 1743c9bd89d..07ec10ab517 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -89,6 +89,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
it { is_expected.to have_one(:external_wiki_integration) }
it { is_expected.to have_one(:confluence_integration) }
it { is_expected.to have_one(:gitlab_slack_application_integration) }
+ it { is_expected.to have_one(:beyond_identity_integration) }
it { is_expected.to have_one(:project_feature) }
it { is_expected.to have_one(:project_repository) }
it { is_expected.to have_one(:container_expiration_policy) }
@@ -6619,6 +6620,14 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
]
end
end
+
+ context 'with instance specific integration' do
+ it 'does not contain instance specific integrations' do
+ expect(subject.find_or_initialize_integrations).not_to include(
+ have_attributes(title: 'Beyond Identity')
+ )
+ end
+ end
end
describe '#disabled_integrations' do
@@ -6695,6 +6704,12 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
expect(subject.find_or_initialize_integration('prometheus').api_url).to be_nil
end
end
+
+ context 'with instance specific integrations' do
+ it 'does not create an instance specific integration' do
+ expect(subject.find_or_initialize_integration('beyond_identity')).to be_nil
+ end
+ end
end
describe '.for_group' do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index ca2ee447b4c..f0418992ff2 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -4018,7 +4018,7 @@ RSpec.describe Repository, feature_category: :source_code_management do
end
context 'for SHA256 repository' do
- let(:project) { create(:project, :empty_repo, object_format: Repository::FORMAT_SHA256) }
+ let_it_be(:project) { create(:project, :empty_repo, object_format: Repository::FORMAT_SHA256) }
it { is_expected.to eq('sha256') }
end
@@ -4030,6 +4030,81 @@ RSpec.describe Repository, feature_category: :source_code_management do
it { is_expected.to be_nil }
end
+
+ context 'caching', :request_store, :clean_gitlab_redis_cache do
+ let(:cache_key) { "object_format:#{repository.full_path}" }
+ let(:request_store_cache) { repository.__send__(:request_store_cache) }
+
+ it 'only calls out to Gitaly once' do
+ expect(repository.raw).to receive(:object_format).once
+
+ 2.times { repository.object_format }
+ end
+
+ it 'calls out to Gitaly again after expiration' do
+ expect(repository.raw).to receive(:object_format).once
+
+ repository.object_format
+
+ request_store_cache.expire(cache_key)
+
+ expect(repository.raw).to receive(:object_format).once
+
+ 2.times { repository.object_format }
+ end
+
+ it 'returns the value from the request store' do
+ request_store_cache.write(cache_key, Repository::FORMAT_SHA1)
+
+ expect(repository.object_format).to eq(Repository::FORMAT_SHA1)
+ end
+ end
+ end
+
+ describe '#blank_ref' do
+ subject { repository.blank_ref }
+
+ context 'for existing repository' do
+ context 'for SHA1 repository' do
+ it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) }
+ end
+
+ context 'for SHA256 repository' do
+ let_it_be(:project) { create(:project, :empty_repo, object_format: Repository::FORMAT_SHA256) }
+
+ it { is_expected.to eq(::Gitlab::Git::SHA256_BLANK_SHA) }
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(determine_blank_ref_based_on_gitaly_object_format: false)
+ end
+
+ it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) }
+
+ context 'for a SHA256 repository' do
+ let_it_be(:project) { create(:project, :empty_repo, object_format: Repository::FORMAT_SHA256) }
+
+ it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) }
+ end
+ end
+ end
+
+ context 'for missing repository' do
+ before do
+ allow(repository).to receive(:exists?).and_return(false)
+ end
+
+ it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) }
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(determine_blank_ref_based_on_gitaly_object_format: false)
+ end
+
+ it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) }
+ end
+ end
end
describe '#get_file_attributes' do
diff --git a/spec/requests/api/integrations_spec.rb b/spec/requests/api/integrations_spec.rb
index 4696be07045..36667022fc5 100644
--- a/spec/requests/api/integrations_spec.rb
+++ b/spec/requests/api/integrations_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe API::Integrations, feature_category: :integrations do
Integrations::Zentao.to_param
]
- names = Integration.available_integration_names
+ names = Integration.available_integration_names(include_instance_specific: false)
names.reject { |name| name.in?(unavailable_integration_names) }
end
diff --git a/spec/requests/projects/ml/models_controller_spec.rb b/spec/requests/projects/ml/models_controller_spec.rb
index e469ee837bc..8f68d0c8d00 100644
--- a/spec/requests/projects/ml/models_controller_spec.rb
+++ b/spec/requests/projects/ml/models_controller_spec.rb
@@ -6,9 +6,6 @@ RSpec.describe Projects::Ml::ModelsController, feature_category: :mlops do
let_it_be(:project) { create(:project) }
let_it_be(:user) { project.first_owner }
let_it_be(:model1) { create(:ml_models, :with_versions, project: project) }
- let_it_be(:model2) { create(:ml_models, project: project) }
- let_it_be(:model3) { create(:ml_models, project: project) }
- let_it_be(:model_in_different_project) { create(:ml_models) }
let(:read_model_registry) { true }
let(:write_model_registry) { true }
@@ -37,36 +34,6 @@ RSpec.describe Projects::Ml::ModelsController, feature_category: :mlops do
expect(index_request).to render_template('projects/ml/models/index')
end
- it 'fetches the models using the finder' do
- expect(::Projects::Ml::ModelFinder).to receive(:new).with(project, {}).and_call_original
-
- index_request
- end
-
- it 'fetches the correct variables', :aggregate_failures do
- stub_const("Projects::Ml::ModelsController::MAX_MODELS_PER_PAGE", 2)
-
- index_request
-
- page_models = [model3, model2]
- all_models = [model3, model2, model1]
-
- expect(assigns(:paginator).records).to match_array(page_models)
- expect(assigns(:model_count)).to be all_models.count
- end
-
- it 'does not perform N+1 sql queries' do
- list_models
-
- control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { list_models }
-
- create_list(:ml_model_versions, 2, model: model1)
- create_list(:ml_model_versions, 2, model: model2)
- create_list(:ml_models, 4, project: project)
-
- expect { list_models }.not_to exceed_all_query_limit(control_count)
- end
-
context 'when user does not have access' do
let(:read_model_registry) { false }
@@ -74,40 +41,6 @@ RSpec.describe Projects::Ml::ModelsController, feature_category: :mlops do
is_expected.to have_gitlab_http_status(:not_found)
end
end
-
- context 'with search params' do
- let(:params) { { name: 'some_name', order_by: 'name', sort: 'asc' } }
-
- it 'passes down params to the finder' do
- expect(Projects::Ml::ModelFinder).to receive(:new).and_call_original do |_exp, params|
- expect(params.to_h).to include({
- name: 'some_name',
- order_by: 'name',
- sort: 'asc'
- })
- end
-
- index_request
- end
- end
-
- describe 'pagination' do
- before do
- stub_const("Projects::Ml::ModelsController::MAX_MODELS_PER_PAGE", 2)
- end
-
- it 'paginates', :aggregate_failures do
- list_models
-
- paginator = assigns(:paginator)
-
- expect(paginator.records).to match_array([model3, model2])
-
- list_models({ cursor: paginator.cursor_for_next_page })
-
- expect(assigns(:paginator).records.first).to eq(model1)
- end
- end
end
describe 'show' do
@@ -140,7 +73,7 @@ RSpec.describe Projects::Ml::ModelsController, feature_category: :mlops do
end
context 'when model project does not match project id' do
- let(:request_project) { model_in_different_project.project }
+ let(:request_project) { create(:project) }
it { is_expected.to have_gitlab_http_status(:not_found) }
end
diff --git a/spec/rubocop/cop/migration/async_post_migrate_only_spec.rb b/spec/rubocop/cop/migration/async_post_migrate_only_spec.rb
new file mode 100644
index 00000000000..c883d3a6ddf
--- /dev/null
+++ b/spec/rubocop/cop/migration/async_post_migrate_only_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'rubocop_spec_helper'
+require_relative '../../../../rubocop/cop/migration/async_post_migrate_only'
+
+RSpec.describe RuboCop::Cop::Migration::AsyncPostMigrateOnly, feature_category: :database do
+ let(:sample_source) do
+ <<~RUBY
+ def up
+ %s
+ end
+ RUBY
+ end
+
+ let(:forbidden_method_names) { described_class::FORBIDDEN_METHODS }
+
+ context 'when outside of a migration' do
+ it 'does not register any offenses' do
+ forbidden_method_names.each do |method|
+ expect_no_offenses(format(sample_source, method.to_s))
+ end
+ end
+ end
+
+ context 'when in a migration' do
+ before do
+ allow(cop).to receive(:in_migration?).and_return(true)
+ allow(cop).to receive(:time_enforced?).and_return(true)
+ end
+
+ context 'when in a post deployment migration' do
+ before do
+ allow(cop).to receive(:in_post_deployment_migration?).and_return(true)
+ end
+
+ it 'does not register any offenses' do
+ forbidden_method_names.each do |method|
+ expect_no_offenses(format(sample_source, method.to_s))
+ end
+ end
+ end
+
+ context 'when in a regular migration' do
+ it 'registers an offense' do
+ forbidden_method_names.each do |method|
+ expect_offense(<<~RUBY)
+ def up
+ #{method}
+ #{'^' * method.to_s.length} #{described_class::MSG}
+ end
+ RUBY
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/gpg_keys/create_service_spec.rb b/spec/services/gpg_keys/create_service_spec.rb
index d603ce951ec..30fe52f732b 100644
--- a/spec/services/gpg_keys/create_service_spec.rb
+++ b/spec/services/gpg_keys/create_service_spec.rb
@@ -30,4 +30,18 @@ RSpec.describe GpgKeys::CreateService, feature_category: :source_code_management
expect(gpg_key.subkeys.count).to eq(2)
end
end
+
+ context 'invalid key' do
+ let(:params) { {} }
+
+ it 'returns an invalid key' do
+ expect_next_instance_of(GpgKeys::ValidateIntegrationsService) do |instance|
+ expect(instance).to receive(:execute)
+ end
+
+ gpg_key = subject.execute
+
+ expect(gpg_key).not_to be_persisted
+ end
+ end
end
diff --git a/spec/services/gpg_keys/validate_integrations_service_spec.rb b/spec/services/gpg_keys/validate_integrations_service_spec.rb
new file mode 100644
index 00000000000..41ca95f1b69
--- /dev/null
+++ b/spec/services/gpg_keys/validate_integrations_service_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GpgKeys::ValidateIntegrationsService, feature_category: :source_code_management do
+ let_it_be(:user) { create(:user) }
+
+ let(:gpg_key) { build(:gpg_key, user: user) }
+
+ subject(:service) { described_class.new(gpg_key) }
+
+ it 'returns true' do
+ expect(service.execute).to eq(true)
+ end
+
+ context 'when key is invalid' do
+ it 'returns false' do
+ gpg_key.key = ''
+
+ expect(service.execute).to eq(false)
+ end
+ end
+
+ context 'when BeyondIdentity integration is not activated' do
+ let_it_be(:integration) { create(:beyond_identity_integration, active: false) }
+
+ it 'return false' do
+ expect(::Gitlab::BeyondIdentity::Client).not_to receive(:new)
+
+ expect(service.execute).to eq(true)
+ end
+ end
+
+ context 'when BeyondIdentity integration is activated' do
+ let_it_be(:integration) { create(:beyond_identity_integration) }
+
+ it 'returns true on successful check' do
+ expect_next_instance_of(::Gitlab::BeyondIdentity::Client) do |instance|
+ expect(instance).to receive(:execute).with(
+ { key_id: 'CCFBE19F00AC8B1D', committer_email: user.email }
+ )
+ end
+
+ expect(service.execute).to eq(true)
+ end
+
+ it 'returns false and sets an error on unsuccessful check' do
+ error = 'service error'
+
+ expect_next_instance_of(::Gitlab::BeyondIdentity::Client) do |instance|
+ expect(instance).to receive(:execute).with(
+ { key_id: 'CCFBE19F00AC8B1D', committer_email: user.email }
+ ).and_raise(::Gitlab::BeyondIdentity::Client::Error.new(error))
+ end
+
+ expect(service.execute).to eq(false)
+ expect(gpg_key.errors.full_messages).to eq(['BeyondIdentity: service error'])
+ end
+ end
+end
diff --git a/spec/support/shared_examples/redis/redis_shared_examples.rb b/spec/support/shared_examples/redis/redis_shared_examples.rb
index b9179261f87..1c153b7c31b 100644
--- a/spec/support/shared_examples/redis/redis_shared_examples.rb
+++ b/spec/support/shared_examples/redis/redis_shared_examples.rb
@@ -185,6 +185,17 @@ RSpec.shared_examples "redis_shared_examples" do
end
end
+ context 'when the parsed external command output returns invalid hash' do
+ before do
+ allow(Gitlab::Popen).to receive(:popen).and_return(["hello", 0])
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Redis::Wrapper::CommandExecutionError,
+ %r{Redis: The output of `/opt/redis-config.sh` must be a Hash, String given})
+ end
+ end
+
context 'when the command fails' do
before do
allow(Gitlab::Popen).to receive(:popen).and_return(["", 125])
diff --git a/spec/workers/click_house/event_paths_consistency_cron_worker_spec.rb b/spec/workers/click_house/event_paths_consistency_cron_worker_spec.rb
index 76ce63ed2e4..e9efad169ff 100644
--- a/spec/workers/click_house/event_paths_consistency_cron_worker_spec.rb
+++ b/spec/workers/click_house/event_paths_consistency_cron_worker_spec.rb
@@ -96,18 +96,20 @@ RSpec.describe ClickHouse::EventPathsConsistencyCronWorker, feature_category: :v
stub_const("#{ClickHouse::Concerns::ConsistencyWorker}::POSTGRESQL_BATCH_SIZE", 1)
expect(worker).to receive(:log_extra_metadata_on_done).with(:result,
- { status: :modification_limit_reached, modifications: 2 })
+ { status: :limit_reached, modifications: 1 })
worker.perform
paths = [
"#{namespace1.id}/",
"#{namespace2.traversal_ids.join('/')}/",
- "#{namespace_with_updated_parent.traversal_ids.join('/')}/"
+ "#{namespace_with_updated_parent.traversal_ids.join('/')}/",
+ "#{deleted_namespace_id}/"
]
expect(leftover_paths).to match_array(paths)
- expect(ClickHouse::SyncCursor.cursor_for(:event_namespace_paths_consistency_check)).to eq(deleted_namespace_id)
+ expect(ClickHouse::SyncCursor.cursor_for(:event_namespace_paths_consistency_check))
+ .to eq(namespace_with_updated_parent.id)
end
end
diff --git a/spec/workers/projects/git_garbage_collect_worker_spec.rb b/spec/workers/projects/git_garbage_collect_worker_spec.rb
index 7daee107a74..259943af2b5 100644
--- a/spec/workers/projects/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/projects/git_garbage_collect_worker_spec.rb
@@ -81,24 +81,6 @@ RSpec.describe Projects::GitGarbageCollectWorker, feature_category: :source_code
expect(project.lfs_objects.reload).to include(lfs_object)
end
-
- context 'when feature flag "reorder_garbage_collection_calls" is disabled' do
- before do
- stub_feature_flags(reorder_garbage_collection_calls: false)
- end
-
- it 'cleans up unreferenced LFS object first' do
- expect_next_instance_of(Gitlab::Cleanup::OrphanLfsFileReferences) do |svc|
- expect(svc.project).to eq(project)
- expect(svc.dry_run).to be_falsy
- expect(svc).to receive(:run!).and_call_original
- end
-
- expect { subject.perform(*params) }.to raise_error('Boom')
-
- expect(project.lfs_objects.reload).not_to include(lfs_object)
- end
- end
end
it 'catches and logs exceptions' do
diff --git a/yarn.lock b/yarn.lock
index 09b360ea492..8875a0ad2b8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -13363,10 +13363,10 @@ vite-plugin-ruby@^5.0.0:
debug "^4.3.4"
fast-glob "^3.3.2"
-vite@^5.0.11:
- version "5.0.11"
- resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.11.tgz#31562e41e004cb68e1d51f5d2c641ab313b289e4"
- integrity sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==
+vite@^5.0.12:
+ version "5.0.12"
+ resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.12.tgz#8a2ffd4da36c132aec4adafe05d7adde38333c47"
+ integrity sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==
dependencies:
esbuild "^0.19.3"
postcss "^8.4.32"