diff options
| author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-04-04 00:08:36 +0000 |
|---|---|---|
| committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-04-04 00:08:36 +0000 |
| commit | e52198c83629b4e880f7851f9a625cad651c3819 (patch) | |
| tree | f81b2926b7968800d4a86ffc7837aebc0ef5a296 | |
| parent | 21cf3e773d0527e95d761e7cc49bdbb2155183d3 (diff) | |
| download | gitlab-ce-e52198c83629b4e880f7851f9a625cad651c3819.tar.gz | |
Add latest changes from gitlab-org/gitlab@master
48 files changed, 734 insertions, 164 deletions
diff --git a/.rubocop_todo/layout/argument_alignment.yml b/.rubocop_todo/layout/argument_alignment.yml index a90163c8980..3fd160c578b 100644 --- a/.rubocop_todo/layout/argument_alignment.yml +++ b/.rubocop_todo/layout/argument_alignment.yml @@ -1393,7 +1393,6 @@ Layout/ArgumentAlignment: - 'ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb' - 'ee/spec/lib/audit/group_merge_request_approval_setting_changes_auditor_spec.rb' - 'ee/spec/lib/audit/protected_branches_changes_auditor_spec.rb' - - 'ee/spec/lib/banzai/filter/cross_project_issuable_information_filter_spec.rb' - 'ee/spec/lib/ee/api/entities/analytics/code_review/merge_request_spec.rb' - 'ee/spec/lib/ee/api/entities/geo_node_status_spec.rb' - 'ee/spec/lib/ee/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb' @@ -1807,11 +1806,6 @@ Layout/ArgumentAlignment: - 'lib/api/users.rb' - 'lib/api/v3/github.rb' - 'lib/backup/manager.rb' - - 'lib/banzai/filter/references/abstract_reference_filter.rb' - - 'lib/banzai/filter/references/commit_range_reference_filter.rb' - - 'lib/banzai/filter/references/commit_reference_filter.rb' - - 'lib/banzai/filter/references/merge_request_reference_filter.rb' - - 'lib/banzai/filter/references/snippet_reference_filter.rb' - 'lib/bitbucket_server/connection.rb' - 'lib/gem_extensions/active_record/disable_joins/associations/association_scope.rb' - 'lib/generators/gitlab/partitioning/foreign_keys_generator.rb' @@ -2237,10 +2231,6 @@ Layout/ArgumentAlignment: - 'spec/lib/atlassian/jira_connect/client_spec.rb' - 'spec/lib/backup/dump/postgres_spec.rb' - 'spec/lib/backup/manager_spec.rb' - - 'spec/lib/banzai/filter/kroki_filter_spec.rb' - - 'spec/lib/banzai/filter/references/design_reference_filter_spec.rb' - - 'spec/lib/banzai/filter/syntax_highlight_filter_spec.rb' - - 'spec/lib/banzai/reference_redactor_spec.rb' - 'spec/lib/bulk_imports/common/pipelines/lfs_objects_pipeline_spec.rb' - 'spec/lib/container_registry/blob_spec.rb' - 'spec/lib/container_registry/migration_spec.rb' diff --git a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item.vue b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item.vue new file mode 100644 index 00000000000..25bbd6b3180 --- /dev/null +++ b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item.vue @@ -0,0 +1,104 @@ +<script> +import { GlAccordionItem, GlFormInput, GlFormGroup, GlButton } from '@gitlab/ui'; +import { get, toPath } from 'lodash'; +import { i18n } from '../constants'; + +export default { + i18n, + components: { + GlFormGroup, + GlAccordionItem, + GlFormInput, + GlButton, + }, + props: { + job: { + type: Object, + required: true, + }, + }, + computed: { + formOptions() { + return [ + { + key: 'artifacts.paths', + title: i18n.ARTIFACTS_AND_CACHE, + paths: this.job.artifacts.paths, + generateInputDataTestId: (index) => `artifacts-paths-input-${index}`, + generateDeleteButtonDataTestId: (index) => `delete-artifacts-paths-button-${index}`, + addButtonDataTestId: 'add-artifacts-paths-button', + }, + { + key: 'artifacts.exclude', + title: i18n.ARTIFACTS_EXCLUDE_PATHS, + paths: this.job.artifacts.exclude, + generateInputDataTestId: (index) => `artifacts-exclude-input-${index}`, + generateDeleteButtonDataTestId: (index) => `delete-artifacts-exclude-button-${index}`, + addButtonDataTestId: 'add-artifacts-exclude-button', + }, + { + key: 'cache.paths', + title: i18n.CACHE_PATHS, + paths: this.job.cache.paths, + generateInputDataTestId: (index) => `cache-paths-input-${index}`, + generateDeleteButtonDataTestId: (index) => `delete-cache-paths-button-${index}`, + addButtonDataTestId: 'add-cache-paths-button', + }, + ]; + }, + }, + methods: { + deleteStringArrayItem(path) { + const parentPath = toPath(path).slice(0, -1); + const array = get(this.job, parentPath); + if (array.length <= 1) { + return; + } + this.$emit('update-job', path); + }, + }, +}; +</script> +<template> + <gl-accordion-item :title="$options.i18n.ARTIFACTS_AND_CACHE"> + <div v-for="entry in formOptions" :key="entry.key" class="form-group"> + <div class="gl-display-flex"> + <label class="gl-font-weight-bold gl-mb-3">{{ entry.title }}</label> + </div> + <div + v-for="(path, index) in entry.paths" + :key="index" + class="gl-display-flex gl-align-items-center gl-mb-3" + > + <div class="gl-flex-grow-1 gl-flex-basis-0 gl-mr-3"> + <gl-form-input + class="gl-w-full!" + :value="path" + :data-testid="entry.generateInputDataTestId(index)" + @input="$emit('update-job', `${entry.key}[${index}]`, $event)" + /> + </div> + <gl-button + category="tertiary" + icon="remove" + :data-testid="entry.generateDeleteButtonDataTestId(index)" + @click="deleteStringArrayItem(`${entry.key}[${index}]`)" + /> + </div> + <gl-button + category="secondary" + variant="confirm" + :data-testid="entry.addButtonDataTestId" + @click="$emit('update-job', `${entry.key}[${entry.paths.length}]`, '')" + >{{ $options.i18n.ADD_PATH }}</gl-button + > + </div> + <gl-form-group :label="$options.i18n.CACHE_KEY"> + <gl-form-input + :value="job.cache.key" + data-testid="cache-key-input" + @input="$emit('update-job', 'cache.key', $event)" + /> + </gl-form-group> + </gl-accordion-item> +</template> diff --git a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js index 17ceea19e3b..df3a2c64e25 100644 --- a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js +++ b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js @@ -98,6 +98,12 @@ export const i18n = { IMAGE_NAME: s__('JobAssistant|Image name (optional)'), IMAGE_ENTRYPOINT: s__('JobAssistant|Image entrypoint (optional)'), THIS_FIELD_IS_REQUIRED: __('This field is required'), + CACHE_PATHS: s__('JobAssistant|Cache paths (optional)'), + CACHE_KEY: s__('JobAssistant|Cache key (optional)'), + ARTIFACTS_EXCLUDE_PATHS: s__('JobAssistant|Artifacts exclude paths (optional)'), + ARTIFACTS_PATHS: s__('JobAssistant|Artifacts paths (optional)'), + ARTIFACTS_AND_CACHE: s__('JobAssistant|Artifacts and cache'), + ADD_PATH: s__('JobAssistant|Add path'), RULES: s__('JobAssistant|Rules'), WHEN: s__('JobAssistant|When'), ALLOW_FAILURE: s__('JobAssistant|Allow failure'), diff --git a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue index 8d42931ab2b..8cde20bc22e 100644 --- a/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue +++ b/app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue @@ -1,14 +1,15 @@ <script> import { GlDrawer, GlAccordion, GlButton } from '@gitlab/ui'; import { stringify, parse } from 'yaml'; -import { set, omit } from 'lodash'; +import { get, omit, toPath } from 'lodash'; import { getContentWrapperHeight } from '~/lib/utils/dom_utils'; import eventHub, { SCROLL_EDITOR_TO_BOTTOM } from '~/ci/pipeline_editor/event_hub'; import getRunnerTags from '../../graphql/queries/runner_tags.query.graphql'; -import { DRAWER_CONTAINER_CLASS, JOB_TEMPLATE, i18n, JOB_RULES_WHEN } from './constants'; +import { DRAWER_CONTAINER_CLASS, JOB_TEMPLATE, JOB_RULES_WHEN, i18n } from './constants'; import { removeEmptyObj, trimFields, validateEmptyValue, validateStartIn } from './utils'; import JobSetupItem from './accordion_items/job_setup_item.vue'; import ImageItem from './accordion_items/image_item.vue'; +import ArtifactsAndCacheItem from './accordion_items/artifacts_and_cache_item.vue'; import RulesItem from './accordion_items/rules_item.vue'; export default { @@ -19,6 +20,7 @@ export default { GlButton, JobSetupItem, ImageItem, + ArtifactsAndCacheItem, RulesItem, }, props: { @@ -148,7 +150,14 @@ export default { }); }, updateJob(key, value) { - set(this.job, key, value); + const path = toPath(key); + const targetObj = path.length === 1 ? this.job : get(this.job, path.slice(0, -1)); + const lastKey = path[path.length - 1]; + if (value !== undefined) { + this.$set(targetObj, lastKey, value); + } else { + this.$delete(targetObj, lastKey); + } }, validateJob() { this.isNameValid = validateEmptyValue(this.job.name); @@ -179,6 +188,7 @@ export default { @update-job="updateJob" /> <image-item :job="job" @update-job="updateJob" /> + <artifacts-and-cache-item :job="job" @update-job="updateJob" /> <rules-item :job="job" :is-start-valid="isStartValid" @update-job="updateJob" /> </gl-accordion> <template #footer> diff --git a/app/assets/javascripts/content_editor/components/wrappers/reference.vue b/app/assets/javascripts/content_editor/components/wrappers/reference.vue index bd16773d291..4126c65d87f 100644 --- a/app/assets/javascripts/content_editor/components/wrappers/reference.vue +++ b/app/assets/javascripts/content_editor/components/wrappers/reference.vue @@ -1,10 +1,12 @@ <script> import { NodeViewWrapper } from '@tiptap/vue-2'; +import { GlLink } from '@gitlab/ui'; export default { name: 'DetailsWrapper', components: { NodeViewWrapper, + GlLink, }, props: { node: { @@ -12,11 +14,32 @@ export default { required: true, }, }, + computed: { + text() { + return this.node.attrs.text; + }, + isCommand() { + return this.node.attrs.referenceType === 'command'; + }, + isMember() { + return this.node.attrs.referenceType === 'user'; + }, + isCurrentUser() { + return gon.current_username === this.text.substring(1); + }, + }, }; </script> <template> <node-view-wrapper class="gl-display-inline-block"> - <span v-if="node.attrs.referenceType === 'command'">{{ node.attrs.text }}</span> - <a v-else href="#" @click.prevent.stop>{{ node.attrs.text }}</a> + <span v-if="isCommand">{{ text }}</span> + <gl-link + v-else + href="#" + class="gfm" + :class="{ 'gfm-project_member': isMember, 'current-user': isMember && isCurrentUser }" + @click.prevent.stop + >{{ text }}</gl-link + > </node-view-wrapper> </template> diff --git a/app/assets/stylesheets/page_bundles/wiki.scss b/app/assets/stylesheets/page_bundles/wiki.scss index 6e7f1b8cf3c..7625fbede3a 100644 --- a/app/assets/stylesheets/page_bundles/wiki.scss +++ b/app/assets/stylesheets/page_bundles/wiki.scss @@ -111,6 +111,8 @@ } .wiki-list { + height: $gl-spacing-scale-8; + &:hover { background: $gray-10; diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index ef45eaac437..0f9ecc60648 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -5,7 +5,7 @@ class Admin::GroupsController < Admin::ApplicationController before_action :group, only: [:edit, :update, :destroy, :project_update, :members_update] - feature_category :subgroups + feature_category :subgroups, [:create, :destroy, :edit, :index, :members_update, :new, :show, :update] def index @groups = groups.sort_by_attribute(@sort = params[:sort]) diff --git a/app/controllers/projects/usage_quotas_controller.rb b/app/controllers/projects/usage_quotas_controller.rb index 6e2514e89c8..b7d7e90bf70 100644 --- a/app/controllers/projects/usage_quotas_controller.rb +++ b/app/controllers/projects/usage_quotas_controller.rb @@ -5,6 +5,10 @@ class Projects::UsageQuotasController < Projects::ApplicationController layout "project_settings" + before_action do + push_frontend_feature_flag(:move_year_dropdown_usage_charts, current_user) + end + feature_category :consumables_cost_management urgency :low diff --git a/app/models/integrations/google_play.rb b/app/models/integrations/google_play.rb index f60ae48ad63..9fa6dc19f11 100644 --- a/app/models/integrations/google_play.rb +++ b/app/models/integrations/google_play.rb @@ -2,7 +2,7 @@ module Integrations class GooglePlay < Integration - PACKAGE_NAME_REGEX = /\A[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*){2,20}\z/ + PACKAGE_NAME_REGEX = /\A[A-Za-z][A-Za-z0-9_]*(\.[A-Za-z][A-Za-z0-9_]*){1,20}\z/ SECTION_TYPE_GOOGLE_PLAY = 'google_play' diff --git a/config/feature_flags/development/move_year_dropdown_usage_charts.yml b/config/feature_flags/development/move_year_dropdown_usage_charts.yml new file mode 100644 index 00000000000..dfeaa3d7144 --- /dev/null +++ b/config/feature_flags/development/move_year_dropdown_usage_charts.yml @@ -0,0 +1,8 @@ +--- +name: move_year_dropdown_usage_charts +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115609 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/402311 +milestone: '15.11' +type: development +group: group::pipeline execution +default_enabled: false diff --git a/config/plugins/graphql_known_operations_plugin.js b/config/plugins/graphql_known_operations_plugin.js index c340849e084..783887cf6e6 100644 --- a/config/plugins/graphql_known_operations_plugin.js +++ b/config/plugins/graphql_known_operations_plugin.js @@ -4,7 +4,9 @@ const yaml = require('js-yaml'); const { evaluateModuleFromSource } = require('../helpers/evaluate_module_from_source'); const PLUGIN_NAME = 'GraphqlKnownOperationsPlugin'; -const GRAPHQL_PATH_REGEX = /(query|mutation)\.graphql$/; +const SUPPORTED_OPS = ['query', 'mutation', 'subscription']; +/* eslint-disable no-useless-escape */ +const GRAPHQL_PATH_REGEX = new RegExp(`(${SUPPORTED_OPS.join('|')})\.graphql$`); /** * Returns whether a given webpack module is a "graphql" module @@ -34,7 +36,7 @@ const getOperationNames = (module) => { }); const names = moduleExports.definitions - .filter((x) => ['query', 'mutation'].includes(x.operation)) + .filter((x) => SUPPORTED_OPS.includes(x.operation)) .map((x) => x.name?.value) // why: It's possible for operations to not have a name. That violates our eslint rule, but either way, let's ignore those here. .filter(Boolean); diff --git a/doc/user/project/repository/mirror/index.md b/doc/user/project/repository/mirror/index.md index 32183eccc2f..61aa2ae3300 100644 --- a/doc/user/project/repository/mirror/index.md +++ b/doc/user/project/repository/mirror/index.md @@ -330,6 +330,29 @@ and requires the full version including the protocol (`ssh://git@gitlab.com/gitl Make sure that host and project path are separated using `/` instead of `:`. +### Host key verification failed + +This error is returned when the target host public SSH key changes. +Public SSH keys rarely, if ever, change. If host key verification fails, +but you suspect the key is still valid, you can refresh the key's information. + +Prerequisites: + +- You must have at least the Maintainer role for a project. + +To resolve the issue: + +1. [Verify the host key](#verify-a-host-key). +1. On the top bar, select **Main menu > Projects** and find your project. +1. On the left sidebar, select **Settings > Repository**. +1. Expand **Mirroring repositories**. +1. To refresh the keys, either: + + - Select **Detect host keys** for GitLab to fetch the host keys from the server, and display the fingerprints. + - Select **Input host keys manually**, and enter the host key into the **SSH host key** field. + +- Select **Mirror repository**. + ### Transfer mirror users and tokens to a single service account in Rails console This requires access to the [GitLab Rails console](../../../../administration/operations/rails_console.md#starting-a-rails-console-session). diff --git a/lib/banzai/filter/references/abstract_reference_filter.rb b/lib/banzai/filter/references/abstract_reference_filter.rb index 1ca38d2612d..3e48fe33b03 100644 --- a/lib/banzai/filter/references/abstract_reference_filter.rb +++ b/lib/banzai/filter/references/abstract_reference_filter.rb @@ -202,9 +202,13 @@ module Banzai title = object_link_title(object, matches) klass = reference_class(object_sym) - data_attributes = data_attributes_for(link_content || match, parent, object, - link_content: !!link_content, - link_reference: link_reference) + data_attributes = data_attributes_for( + link_content || match, + parent, + object, + link_content: !!link_content, + link_reference: link_reference + ) data_attributes[:reference_format] = matches[:format] if matches.names.include?("format") data_attributes.merge!(additional_object_attributes(object)) diff --git a/lib/banzai/filter/references/commit_range_reference_filter.rb b/lib/banzai/filter/references/commit_range_reference_filter.rb index df7f42eaa70..d0a24f3f0f0 100644 --- a/lib/banzai/filter/references/commit_range_reference_filter.rb +++ b/lib/banzai/filter/references/commit_range_reference_filter.rb @@ -32,8 +32,7 @@ module Banzai def url_for_object(range, project) h = Gitlab::Routing.url_helpers - h.project_compare_url(project, - range.to_param.merge(only_path: context[:only_path])) + h.project_compare_url(project, range.to_param.merge(only_path: context[:only_path])) end def object_link_title(range, matches) diff --git a/lib/banzai/filter/references/commit_reference_filter.rb b/lib/banzai/filter/references/commit_reference_filter.rb index 86ab8597cf5..0f412c1fe8d 100644 --- a/lib/banzai/filter/references/commit_reference_filter.rb +++ b/lib/banzai/filter/references/commit_reference_filter.rb @@ -49,14 +49,14 @@ module Banzai h = Gitlab::Routing.url_helpers if referenced_merge_request_commit_shas.include?(commit.id) - h.diffs_project_merge_request_url(project, - noteable, - commit_id: commit.id, - only_path: only_path?) + h.diffs_project_merge_request_url( + project, + noteable, + commit_id: commit.id, + only_path: only_path? + ) else - h.project_commit_url(project, - commit, - only_path: only_path?) + h.project_commit_url(project, commit, only_path: only_path?) end end diff --git a/lib/banzai/filter/references/merge_request_reference_filter.rb b/lib/banzai/filter/references/merge_request_reference_filter.rb index 5bc18ee6985..2518d7653f6 100644 --- a/lib/banzai/filter/references/merge_request_reference_filter.rb +++ b/lib/banzai/filter/references/merge_request_reference_filter.rb @@ -13,8 +13,7 @@ module Banzai def url_for_object(mr, project) h = Gitlab::Routing.url_helpers - h.project_merge_request_url(project, mr, - only_path: context[:only_path]) + h.project_merge_request_url(project, mr, only_path: context[:only_path]) end def object_link_text_extras(object, matches) diff --git a/lib/banzai/filter/references/snippet_reference_filter.rb b/lib/banzai/filter/references/snippet_reference_filter.rb index 502bfca1ab7..1f5ab0645fe 100644 --- a/lib/banzai/filter/references/snippet_reference_filter.rb +++ b/lib/banzai/filter/references/snippet_reference_filter.rb @@ -23,8 +23,7 @@ module Banzai def url_for_object(snippet, project) h = Gitlab::Routing.url_helpers - h.project_snippet_url(project, snippet, - only_path: context[:only_path]) + h.project_snippet_url(project, snippet, only_path: context[:only_path]) end end end diff --git a/lib/gitlab/ci/config/external/mapper/matcher.rb b/lib/gitlab/ci/config/external/mapper/matcher.rb index 5c6fb019518..5072d0971cf 100644 --- a/lib/gitlab/ci/config/external/mapper/matcher.rb +++ b/lib/gitlab/ci/config/external/mapper/matcher.rb @@ -48,7 +48,9 @@ module Gitlab External::File::Artifact ] - classes << External::File::Component if Feature.enabled?(:ci_include_components, context.project) + if Feature.enabled?(:ci_include_components, context.project&.root_namespace) + classes << External::File::Component + end classes end diff --git a/lib/tasks/gitlab/setup.rake b/lib/tasks/gitlab/setup.rake index 006dfad3a95..38c5902702c 100644 --- a/lib/tasks/gitlab/setup.rake +++ b/lib/tasks/gitlab/setup.rake @@ -33,6 +33,7 @@ namespace :gitlab do Rake::Task["dev:terminate_all_connections"].invoke unless Rails.env.production? Rake::Task["db:reset"].invoke + Rake::Task["gitlab:db:lock_writes"].invoke Rake::Task["db:seed_fu"].invoke rescue Gitlab::TaskAbortedByUserError puts "Quitting...".color(:red) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index d7bebae5fd4..0503067e8cf 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -24750,9 +24750,27 @@ msgstr "" msgid "JobAssistant|Add job" msgstr "" +msgid "JobAssistant|Add path" +msgstr "" + msgid "JobAssistant|Allow failure" msgstr "" +msgid "JobAssistant|Artifacts and cache" +msgstr "" + +msgid "JobAssistant|Artifacts exclude paths (optional)" +msgstr "" + +msgid "JobAssistant|Artifacts paths (optional)" +msgstr "" + +msgid "JobAssistant|Cache key (optional)" +msgstr "" + +msgid "JobAssistant|Cache paths (optional)" +msgstr "" + msgid "JobAssistant|Error - Valid value is between 1 second and 1 week" msgstr "" @@ -46961,6 +46979,12 @@ msgstr "" msgid "UsageQuota|Dependency proxy" msgstr "" +msgid "UsageQuota|Filter chart by month" +msgstr "" + +msgid "UsageQuota|Filter charts by year" +msgstr "" + msgid "UsageQuota|For more information about storage limits, see our %{faq_link_start}FAQ%{link_end}." msgstr "" diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb index 31899d9a0c7..011b1ea5d81 100644 --- a/qa/qa/page/file/show.rb +++ b/qa/qa/page/file/show.rb @@ -5,8 +5,6 @@ module QA module File class Show < Page::Base include Shared::CommitMessage - include Project::SubMenus::Settings - include Project::SubMenus::Common include Layout::Flash include Page::Component::BlobContent diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb index 24ed2d766f1..0b2ea479f17 100644 --- a/qa/qa/page/project/menu.rb +++ b/qa/qa/page/project/menu.rb @@ -16,12 +16,16 @@ module QA include SubMenus::Packages if Runtime::Env.super_sidebar_enabled? + include SubMenus::SuperSidebar::Project + include SubMenus::SuperSidebar::Manage include SubMenus::SuperSidebar::Plan include SubMenus::SuperSidebar::Settings - include SubMenus::SuperSidebar::Repository - include SubMenus::SuperSidebar::CiCd - include SubMenus::SuperSidebar::Compliance - include SubMenus::SuperSidebar::Operations + include SubMenus::SuperSidebar::Code + include SubMenus::SuperSidebar::Build + include SubMenus::SuperSidebar::Secure + include SubMenus::SuperSidebar::Operate + include SubMenus::SuperSidebar::Monitor + include SubMenus::SuperSidebar::Analyze end def click_merge_requests diff --git a/qa/qa/page/project/settings/main.rb b/qa/qa/page/project/settings/main.rb index 8b9b72758d8..0d45efdcb70 100644 --- a/qa/qa/page/project/settings/main.rb +++ b/qa/qa/page/project/settings/main.rb @@ -6,7 +6,6 @@ module QA module Settings class Main < Page::Base include QA::Page::Settings::Common - include SubMenus::Project include Component::Breadcrumbs include Layout::Flash diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index b5fce559496..09a5267feef 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -7,9 +7,8 @@ module QA include Layout::Flash include Page::Component::ClonePanel include Page::Component::Breadcrumbs - include Page::Project::SubMenus::Settings include Page::File::Shared::CommitMessage - include ::QA::Page::Component::Dropdown + include Page::Component::Dropdown prepend Mobile::Page::Project::Show if Runtime::Env.mobile_layout? view 'app/assets/javascripts/repository/components/preview/index.vue' do diff --git a/qa/qa/page/project/sub_menus/super_sidebar/analyze.rb b/qa/qa/page/project/sub_menus/super_sidebar/analyze.rb new file mode 100644 index 00000000000..0a0735ee3eb --- /dev/null +++ b/qa/qa/page/project/sub_menus/super_sidebar/analyze.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module SubMenus + module SuperSidebar + module Analyze + extend QA::Page::PageConcern + + def self.included(base) + super + + base.class_eval do + include QA::Page::Project::SubMenus::SuperSidebar::Common + end + end + + def go_to_value_stream_analytics + open_analyze_submenu('Value stream analytics') + end + + def go_to_contributor_statistics + open_analyze_submenu('Contributor statistics') + end + + def go_to_ci_cd_analytics + open_analyze_submenu('CI/CD analytics') + end + + def go_to_repository_analytics + open_analyze_submenu('Repository analytics') + end + + private + + def open_analyze_submenu(sub_menu) + open_submenu('Analyze', '#analyze', sub_menu) + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/operations.rb b/qa/qa/page/project/sub_menus/super_sidebar/build.rb index 91b9cba1b3e..117aade7b1d 100644 --- a/qa/qa/page/project/sub_menus/super_sidebar/operations.rb +++ b/qa/qa/page/project/sub_menus/super_sidebar/build.rb @@ -5,7 +5,7 @@ module QA module Project module SubMenus module SuperSidebar - module Operations + module Build extend QA::Page::PageConcern def self.included(base) @@ -16,38 +16,38 @@ module QA end end - def go_to_environments - open_operations_submenu('Environments') + def go_to_pipelines + open_build_submenu('Pipelines') end - def go_to_feature_flags - open_operations_submenu('Feature flags') + def go_to_pipeline_editor + open_build_submenu('Pipeline editor') end - def go_to_releases - open_operations_submenu('Releases') + def go_to_jobs + open_build_submenu('Jobs') end - def go_to_package_registry - open_operations_submenu('Package Registry') + def go_to_schedules + open_build_submenu('Pipeline schedules') end - def go_to_infrastructure_registry - open_operations_submenu('Infrastructure Registry') + def go_to_environments + open_operations_submenu('Environments') end - def go_to_kubernetes_clusters - open_operations_submenu('Kubernetes clusters') + def go_to_feature_flags + open_operations_submenu('Feature Flags') end - def go_to_terraform - open_operations_submenu('Terraform') + def go_to_releases + open_operations_submenu('Releases') end private - def open_operations_submenu(sub_menu) - open_submenu("Operations", "#operations", sub_menu) + def open_build_submenu(sub_menu) + open_submenu('Build', '#build', sub_menu) end end end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/repository.rb b/qa/qa/page/project/sub_menus/super_sidebar/code.rb index 52a9325c0b1..77b87da545e 100644 --- a/qa/qa/page/project/sub_menus/super_sidebar/repository.rb +++ b/qa/qa/page/project/sub_menus/super_sidebar/code.rb @@ -5,7 +5,7 @@ module QA module Project module SubMenus module SuperSidebar - module Repository + module Code extend QA::Page::PageConcern def self.included(base) @@ -16,42 +16,38 @@ module QA end end - def go_to_files - open_repository_submenu("Files") + def go_to_repository + open_code_submenu('Repository') end def go_to_repository_commits - open_repository_submenu("Commits") + open_code_submenu('Commits') end def go_to_repository_branches - open_repository_submenu("Branches") + open_code_submenu('Branches') end def go_to_repository_tags - open_repository_submenu("Tags") + open_code_submenu('Tags') end def go_to_snippets - open_repository_submenu("Snippets") - end - - def go_to_contributor_statistics - open_repository_submenu("Contributor statistics") + open_code_submenu('Snippets') end def go_to_graph - open_repository_submenu("Graph") + open_code_submenu('Repository graph') end def go_to_compare_revisions - open_repository_submenu("Compare revisions") + open_code_submenu('Compare revisions') end private - def open_repository_submenu(sub_menu) - open_submenu("Repository", "#repository", sub_menu) + def open_code_submenu(sub_menu) + open_submenu('Code', '#code', sub_menu) end end end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/ci_cd.rb b/qa/qa/page/project/sub_menus/super_sidebar/manage.rb index 032842edc43..40bbd3b6618 100644 --- a/qa/qa/page/project/sub_menus/super_sidebar/ci_cd.rb +++ b/qa/qa/page/project/sub_menus/super_sidebar/manage.rb @@ -5,7 +5,7 @@ module QA module Project module SubMenus module SuperSidebar - module CiCd + module Manage extend QA::Page::PageConcern def self.included(base) @@ -16,26 +16,26 @@ module QA end end - def go_to_pipelines - open_ci_cd_submenu('Pipelines') + def go_to_activity + open_manage_submenu('Activity') end - def go_to_editor - open_ci_cd_submenu('Editor') + def go_to_members + open_manage_submenu('Members') end - def go_to_jobs - open_ci_cd_submenu('Jobs') + def go_to_labels + open_manage_submenu('Labels') end - def go_to_schedules - open_ci_cd_submenu('Schedules') + def go_to_milestones + open_manage_submenu('Milestones') end private - def open_ci_cd_submenu(sub_menu) - open_submenu("CI/CD", "#ci-cd", sub_menu) + def open_manage_submenu(sub_menu) + open_submenu('Manage', '#manage', sub_menu) end end end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/monitor.rb b/qa/qa/page/project/sub_menus/super_sidebar/monitor.rb new file mode 100644 index 00000000000..2a578ba2e80 --- /dev/null +++ b/qa/qa/page/project/sub_menus/super_sidebar/monitor.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module SubMenus + module SuperSidebar + module Monitor + extend QA::Page::PageConcern + + def self.included(base) + super + + base.class_eval do + include QA::Page::Project::SubMenus::SuperSidebar::Common + end + end + + def go_to_metrics + open_monitor_submenu('Metrics') + end + + def go_to_error_tracking + open_monitor_submenu('Error tracking') + end + + def go_to_alerts + open_monitor_submenu('Alerts') + end + + def go_to_incidents + open_monitor_submenu('Incidents') + end + + private + + def open_monitor_submenu(sub_menu) + open_submenu('Monitor', '#monitor', sub_menu) + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/operate.rb b/qa/qa/page/project/sub_menus/super_sidebar/operate.rb new file mode 100644 index 00000000000..f2a131d915d --- /dev/null +++ b/qa/qa/page/project/sub_menus/super_sidebar/operate.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module SubMenus + module SuperSidebar + module Operate + extend QA::Page::PageConcern + + def self.included(base) + super + + base.class_eval do + include QA::Page::Project::SubMenus::SuperSidebar::Common + end + end + + def go_to_package_registry + open_operate_submenu('Package Registry') + end + + def go_to_infrastructure_registry + open_operate_submenu('Infrastructure Registry') + end + + def go_to_kubernetes_clusters + open_operate_submenu('Kubernetes clusters') + end + + def go_to_terraform + open_operate_submenu('Terraform') + end + + private + + def open_operate_submenu(sub_menu) + open_submenu('Operate', '#operate', sub_menu) + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/plan.rb b/qa/qa/page/project/sub_menus/super_sidebar/plan.rb index cf90ad9e955..4ed9faeffc0 100644 --- a/qa/qa/page/project/sub_menus/super_sidebar/plan.rb +++ b/qa/qa/page/project/sub_menus/super_sidebar/plan.rb @@ -16,24 +16,8 @@ module QA end end - def go_to_members - open_plan_submenu("Members") - end - - def go_to_labels - open_plan_submenu("Labels") - end - - def go_to_activity - open_plan_submenu("Activity") - end - def go_to_boards - open_plan_submenu("Boards") - end - - def go_to_milestones - open_plan_submenu("Milestones") + open_plan_submenu("Issue boards") end def go_to_service_desk diff --git a/qa/qa/page/project/sub_menus/super_sidebar/project.rb b/qa/qa/page/project/sub_menus/super_sidebar/project.rb new file mode 100644 index 00000000000..ef3b8cc9596 --- /dev/null +++ b/qa/qa/page/project/sub_menus/super_sidebar/project.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module QA + module Page + module Project + module SubMenus + module SuperSidebar + module Project + extend QA::Page::PageConcern + + def self.included(base) + super + + base.class_eval do + include QA::Page::Project::SubMenus::Common + end + end + + def click_project + within_sidebar do + click_element(:sidebar_menu_link, menu_item: 'Project overview') + end + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/compliance.rb b/qa/qa/page/project/sub_menus/super_sidebar/secure.rb index 98f6a04c5c6..4fea95a5456 100644 --- a/qa/qa/page/project/sub_menus/super_sidebar/compliance.rb +++ b/qa/qa/page/project/sub_menus/super_sidebar/secure.rb @@ -5,7 +5,7 @@ module QA module Project module SubMenus module SuperSidebar - module Compliance + module Secure extend QA::Page::PageConcern def self.included(base) @@ -17,17 +17,17 @@ module QA end def go_to_audit_events - open_compliance_submenu('Audit events') + open_secure_submenu('Audit events') end def go_to_security_configuration - open_compliance_submenu('Security configuration') + open_secure_submenu('Security configuration') end private - def open_compliance_submenu(sub_menu) - open_submenu("Security and Compliance", "#security-and-compliance", sub_menu) + def open_secure_submenu(sub_menu) + open_submenu('Secure', '#secure', sub_menu) end end end diff --git a/qa/qa/page/project/sub_menus/super_sidebar/settings.rb b/qa/qa/page/project/sub_menus/super_sidebar/settings.rb index f8371385fd6..eead4f9b147 100644 --- a/qa/qa/page/project/sub_menus/super_sidebar/settings.rb +++ b/qa/qa/page/project/sub_menus/super_sidebar/settings.rb @@ -51,7 +51,7 @@ module QA private def open_settings_submenu(sub_menu) - open_submenu("Settings", "#settings", sub_menu) + open_submenu('Settings', '#settings', sub_menu) end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb b/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb index a214af19fca..ed4bd7c6980 100644 --- a/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb @@ -2,15 +2,15 @@ module QA RSpec.describe 'Create', - :gitlab_pages, - :orchestrated, - except: { job: 'review-qa-*' }, - quarantine: { - issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383215', - type: :test_environment, - only: { subdomain: 'staging-ref' } - }, - feature_flag: { name: 'show_pages_in_deployments_menu' } do + :gitlab_pages, + :orchestrated, + except: { job: 'review-qa-*' }, + quarantine: { + issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/383215', + type: :test_environment, + only: { subdomain: 'staging-ref' } + }, + feature_flag: { name: 'show_pages_in_deployments_menu' } do # TODO: Convert back to :smoke once proved to be stable. Related issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300906 describe 'Pages', product_group: :editor do let!(:project) do @@ -23,9 +23,10 @@ module QA let(:pipeline) do Resource::Pipeline.fabricate_via_api! do |pipeline| pipeline.project = project - pipeline.variables = + pipeline.variables = [ { key: :CI_PAGES_DOMAIN, value: 'nip.io', variable_type: :env_var }, { key: :CI_PAGES_URL, value: 'http://127.0.0.1.nip.io', variable_type: :env_var } + ] end end @@ -46,7 +47,7 @@ module QA end it 'creates a Pages website', - testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do + testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do Page::Project::Pipeline::Show.perform do |show| expect(show).to have_job(:pages) show.click_job(:pages) @@ -56,14 +57,18 @@ module QA expect(show).to have_passed(timeout: 300) end - Page::Project::Show.perform(&:go_to_pages_settings) - QA::Page::Project::Settings::Pages.perform do |pages| - pages.go_to_access_page - Support::Waiter.wait_until(sleep_interval: 2, max_duration: 60, reload_page: page, - retry_on_exception: true) do - expect(page).to have_content( - 'This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.') - end + Page::Project::Menu.perform(&:go_to_pages_settings) + Page::Project::Settings::Pages.perform(&:go_to_access_page) + + Support::Waiter.wait_until( + sleep_interval: 2, + max_duration: 60, + reload_page: page, + retry_on_exception: true + ) do + expect(page).to have_content( + 'This is a simple plain-HTML website on GitLab Pages, without any fancy static site generator.' + ) end end end diff --git a/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb index e7ab515c672..e2bb6c33513 100644 --- a/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb +++ b/qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb @@ -40,8 +40,7 @@ module QA testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/360837' ) do # create a CI variable via UI - Page::Project::Show.perform(&:go_to_ci_cd_settings) - + Page::Project::Menu.perform(&:go_to_ci_cd_settings) Page::Project::Settings::CiCd.perform do |ci_cd| ci_cd.expand_ci_variables do |vars| vars.click_add_variable diff --git a/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb b/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb index 41fd083c12c..02e1598d6e7 100644 --- a/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb +++ b/qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb @@ -37,7 +37,7 @@ module QA it 'user transfers a project between groups', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347878' do - Page::File::Show.perform(&:go_to_general_settings) + Page::Project::Menu.perform(&:go_to_general_settings) Page::Project::Settings::Main.perform(&:expand_advanced_settings) @@ -45,7 +45,7 @@ module QA advanced.transfer_project!(project.name, target_group.full_path) end - Page::Project::Settings::Main.perform(&:click_project) + Page::Project::Menu.perform(&:click_project) Page::Project::Show.perform do |project| expect(project).to have_breadcrumb(target_group.path) diff --git a/spec/factories/packages/debian/file_metadatum.rb b/spec/factories/packages/debian/file_metadatum.rb index c9692c02248..6b6cd9c51f3 100644 --- a/spec/factories/packages/debian/file_metadatum.rb +++ b/spec/factories/packages/debian/file_metadatum.rb @@ -2,7 +2,14 @@ FactoryBot.define do factory :debian_file_metadatum, class: 'Packages::Debian::FileMetadatum' do - package_file { association(:debian_package_file, without_loaded_metadatum: true) } + package_file do + if file_type == 'unknown' + association(:debian_package_file, :unknown, without_loaded_metadatum: true) + else + association(:debian_package_file, without_loaded_metadatum: true) + end + end + file_type { 'deb' } component { 'main' } architecture { 'amd64' } diff --git a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item_spec.js b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item_spec.js new file mode 100644 index 00000000000..9046be4a45e --- /dev/null +++ b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item_spec.js @@ -0,0 +1,127 @@ +import ArtifactsAndCacheItem from '~/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item.vue'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import { JOB_TEMPLATE } from '~/ci/pipeline_editor/components/job_assistant_drawer/constants'; + +describe('Artifacts and cache item', () => { + let wrapper; + + const findArtifactsPathsInputByIndex = (index) => + wrapper.findByTestId(`artifacts-paths-input-${index}`); + const findArtifactsExcludeInputByIndex = (index) => + wrapper.findByTestId(`artifacts-exclude-input-${index}`); + const findCachePathsInputByIndex = (index) => wrapper.findByTestId(`cache-paths-input-${index}`); + const findCacheKeyInput = () => wrapper.findByTestId('cache-key-input'); + const findDeleteArtifactsPathsButtonByIndex = (index) => + wrapper.findByTestId(`delete-artifacts-paths-button-${index}`); + const findDeleteArtifactsExcludeButtonByIndex = (index) => + wrapper.findByTestId(`delete-artifacts-exclude-button-${index}`); + const findDeleteCachePathsButtonByIndex = (index) => + wrapper.findByTestId(`delete-cache-paths-button-${index}`); + const findAddArtifactsPathsButton = () => wrapper.findByTestId('add-artifacts-paths-button'); + const findAddArtifactsExcludeButton = () => wrapper.findByTestId('add-artifacts-exclude-button'); + const findAddCachePathsButton = () => wrapper.findByTestId('add-cache-paths-button'); + + const dummyArtifactsPath = 'dummyArtifactsPath'; + const dummyArtifactsExclude = 'dummyArtifactsExclude'; + const dummyCachePath = 'dummyCachePath'; + const dummyCacheKey = 'dummyCacheKey'; + + const createComponent = ({ job = JSON.parse(JSON.stringify(JOB_TEMPLATE)) } = {}) => { + wrapper = shallowMountExtended(ArtifactsAndCacheItem, { + propsData: { + job, + }, + }); + }; + + it('should emit update job event when filling inputs', () => { + createComponent(); + + expect(wrapper.emitted('update-job')).toBeUndefined(); + + findArtifactsPathsInputByIndex(0).vm.$emit('input', dummyArtifactsPath); + + expect(wrapper.emitted('update-job')).toHaveLength(1); + expect(wrapper.emitted('update-job')[0]).toStrictEqual([ + 'artifacts.paths[0]', + dummyArtifactsPath, + ]); + + findArtifactsExcludeInputByIndex(0).vm.$emit('input', dummyArtifactsExclude); + + expect(wrapper.emitted('update-job')).toHaveLength(2); + expect(wrapper.emitted('update-job')[1]).toStrictEqual([ + 'artifacts.exclude[0]', + dummyArtifactsExclude, + ]); + + findCachePathsInputByIndex(0).vm.$emit('input', dummyCachePath); + + expect(wrapper.emitted('update-job')).toHaveLength(3); + expect(wrapper.emitted('update-job')[2]).toStrictEqual(['cache.paths[0]', dummyCachePath]); + + findCacheKeyInput().vm.$emit('input', dummyCacheKey); + + expect(wrapper.emitted('update-job')).toHaveLength(4); + expect(wrapper.emitted('update-job')[3]).toStrictEqual(['cache.key', dummyCacheKey]); + }); + + it('should emit update job event when click add item button', () => { + createComponent(); + + findAddArtifactsPathsButton().vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toHaveLength(1); + expect(wrapper.emitted('update-job')[0]).toStrictEqual(['artifacts.paths[1]', '']); + + findAddArtifactsExcludeButton().vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toHaveLength(2); + expect(wrapper.emitted('update-job')[1]).toStrictEqual(['artifacts.exclude[1]', '']); + + findAddCachePathsButton().vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toHaveLength(3); + expect(wrapper.emitted('update-job')[2]).toStrictEqual(['cache.paths[1]', '']); + }); + + it('should emit update job event when click delete item button', () => { + createComponent({ + job: { + artifacts: { + paths: ['0', '1'], + exclude: ['0', '1'], + }, + cache: { + paths: ['0', '1'], + key: '', + }, + }, + }); + + findDeleteArtifactsPathsButtonByIndex(0).vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toHaveLength(1); + expect(wrapper.emitted('update-job')[0]).toStrictEqual(['artifacts.paths[0]']); + + findDeleteArtifactsExcludeButtonByIndex(0).vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toHaveLength(2); + expect(wrapper.emitted('update-job')[1]).toStrictEqual(['artifacts.exclude[0]']); + + findDeleteCachePathsButtonByIndex(0).vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toHaveLength(3); + expect(wrapper.emitted('update-job')[2]).toStrictEqual(['cache.paths[0]']); + }); + + it('should not emit update job event when click the only one delete item button', () => { + createComponent(); + + findDeleteArtifactsPathsButtonByIndex(0).vm.$emit('click'); + findDeleteArtifactsExcludeButtonByIndex(0).vm.$emit('click'); + findDeleteCachePathsButtonByIndex(0).vm.$emit('click'); + + expect(wrapper.emitted('update-job')).toBeUndefined(); + }); +}); diff --git a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer_spec.js b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer_spec.js index e03cd19da65..08aa7e3a11a 100644 --- a/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer_spec.js +++ b/spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer_spec.js @@ -5,6 +5,7 @@ import { stringify } from 'yaml'; import JobAssistantDrawer from '~/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue'; import JobSetupItem from '~/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/job_setup_item.vue'; import ImageItem from '~/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/image_item.vue'; +import ArtifactsAndCacheItem from '~/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item.vue'; import RulesItem from '~/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/rules_item.vue'; import { JOB_RULES_WHEN } from '~/ci/pipeline_editor/components/job_assistant_drawer/constants'; import getRunnerTags from '~/ci/pipeline_editor/graphql/queries/runner_tags.query.graphql'; @@ -25,6 +26,10 @@ describe('Job assistant drawer', () => { const dummyJobScript = 'b'; const dummyImageName = 'c'; const dummyImageEntrypoint = 'd'; + const dummyArtifactsPath = 'e'; + const dummyArtifactsExclude = 'f'; + const dummyCachePath = 'g'; + const dummyCacheKey = 'h'; const dummyRulesWhen = JOB_RULES_WHEN.delayed.value; const dummyRulesStartIn = '1 second'; const dummyRulesAllowFailure = true; @@ -32,6 +37,7 @@ describe('Job assistant drawer', () => { const findDrawer = () => wrapper.findComponent(GlDrawer); const findJobSetupItem = () => wrapper.findComponent(JobSetupItem); const findImageItem = () => wrapper.findComponent(ImageItem); + const findArtifactsAndCacheItem = () => wrapper.findComponent(ArtifactsAndCacheItem); const findRulesItem = () => wrapper.findComponent(RulesItem); const findConfirmButton = () => wrapper.findByTestId('confirm-button'); @@ -74,6 +80,10 @@ describe('Job assistant drawer', () => { expect(findImageItem().exists()).toBe(true); }); + it('should contain artifacts and cache item accordion', () => { + expect(findArtifactsAndCacheItem().exists()).toBe(true); + }); + it('should contain rules accordion', () => { expect(findRulesItem().exists()).toBe(true); }); @@ -121,13 +131,24 @@ describe('Job assistant drawer', () => { findJobSetupItem().vm.$emit('update-job', 'script', dummyJobScript); findImageItem().vm.$emit('update-job', 'image.name', dummyImageName); findImageItem().vm.$emit('update-job', 'image.entrypoint', [dummyImageEntrypoint]); + findArtifactsAndCacheItem().vm.$emit('update-job', 'artifacts.paths', [dummyArtifactsPath]); + findArtifactsAndCacheItem().vm.$emit('update-job', 'artifacts.exclude', [ + dummyArtifactsExclude, + ]); + findArtifactsAndCacheItem().vm.$emit('update-job', 'cache.paths', [dummyCachePath]); + findArtifactsAndCacheItem().vm.$emit('update-job', 'cache.key', dummyCacheKey); findRulesItem().vm.$emit('update-job', 'rules[0].allow_failure', dummyRulesAllowFailure); findRulesItem().vm.$emit('update-job', 'rules[0].when', dummyRulesWhen); findRulesItem().vm.$emit('update-job', 'rules[0].start_in', dummyRulesStartIn); }); it('passes correct prop to accordions', () => { - const accordions = [findJobSetupItem(), findImageItem()]; + const accordions = [ + findJobSetupItem(), + findImageItem(), + findArtifactsAndCacheItem(), + findRulesItem(), + ]; accordions.forEach((accordion) => { expect(accordion.props('job')).toMatchObject({ name: dummyJobName, @@ -136,6 +157,14 @@ describe('Job assistant drawer', () => { name: dummyImageName, entrypoint: [dummyImageEntrypoint], }, + artifacts: { + paths: [dummyArtifactsPath], + exclude: [dummyArtifactsExclude], + }, + cache: { + paths: [dummyCachePath], + key: dummyCacheKey, + }, rules: [ { allow_failure: dummyRulesAllowFailure, @@ -180,6 +209,14 @@ describe('Job assistant drawer', () => { [dummyJobName]: { script: dummyJobScript, image: { name: dummyImageName, entrypoint: [dummyImageEntrypoint] }, + artifacts: { + paths: [dummyArtifactsPath], + exclude: [dummyArtifactsExclude], + }, + cache: { + paths: [dummyCachePath], + key: dummyCacheKey, + }, }, })}`, ], @@ -195,6 +232,14 @@ describe('Job assistant drawer', () => { [dummyJobName]: { script: dummyJobScript, image: { name: dummyImageName, entrypoint: [dummyImageEntrypoint] }, + artifacts: { + paths: [dummyArtifactsPath], + exclude: [dummyArtifactsExclude], + }, + cache: { + paths: [dummyCachePath], + key: dummyCacheKey, + }, rules: [ { allow_failure: dummyRulesAllowFailure, diff --git a/spec/frontend/content_editor/components/wrappers/reference_spec.js b/spec/frontend/content_editor/components/wrappers/reference_spec.js index 4f9f2e3f800..a9d9a934af2 100644 --- a/spec/frontend/content_editor/components/wrappers/reference_spec.js +++ b/spec/frontend/content_editor/components/wrappers/reference_spec.js @@ -1,3 +1,4 @@ +import { GlLink } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import ReferenceWrapper from '~/content_editor/components/wrappers/reference.vue'; @@ -10,19 +11,36 @@ describe('content/components/wrappers/reference', () => { }); }; - it('renders a span for comamnds', () => { + it('renders a span for commands', () => { createWrapper({ attrs: { referenceType: 'command', text: '/assign' } }); - expect(wrapper.html()).toMatchInlineSnapshot( - `"<node-view-wrapper-stub as=\\"div\\" class=\\"gl-display-inline-block\\"><span>/assign</span></node-view-wrapper-stub>"`, - ); + const span = wrapper.find('span'); + expect(span.text()).toBe('/assign'); }); it('renders an anchor for everything else', () => { createWrapper({ attrs: { referenceType: 'issue', text: '#252522' } }); - expect(wrapper.html()).toMatchInlineSnapshot( - `"<node-view-wrapper-stub as=\\"div\\" class=\\"gl-display-inline-block\\"><a href=\\"#\\">#252522</a></node-view-wrapper-stub>"`, - ); + const link = wrapper.findComponent(GlLink); + expect(link.text()).toBe('#252522'); + }); + + it('adds gfm-project_member class for project members', () => { + createWrapper({ attrs: { referenceType: 'user', text: '@root' } }); + + const link = wrapper.findComponent(GlLink); + expect(link.text()).toBe('@root'); + expect(link.classes('gfm-project_member')).toBe(true); + expect(link.classes('current-user')).toBe(false); + }); + + it('adds a current-user class if the project member is current user', () => { + window.gon = { current_username: 'root' }; + + createWrapper({ attrs: { referenceType: 'user', text: '@root' } }); + + const link = wrapper.findComponent(GlLink); + expect(link.text()).toBe('@root'); + expect(link.classes('current-user')).toBe(true); }); }); diff --git a/spec/lib/banzai/filter/kroki_filter_spec.rb b/spec/lib/banzai/filter/kroki_filter_spec.rb index 1cd11161439..ccb629d865d 100644 --- a/spec/lib/banzai/filter/kroki_filter_spec.rb +++ b/spec/lib/banzai/filter/kroki_filter_spec.rb @@ -13,10 +13,12 @@ RSpec.describe Banzai::Filter::KrokiFilter, feature_category: :team_planning do end it 'replaces nomnoml pre tag with img tag if both kroki and plantuml are enabled' do - stub_application_setting(kroki_enabled: true, - kroki_url: "http://localhost:8000", - plantuml_enabled: true, - plantuml_url: "http://localhost:8080") + stub_application_setting( + kroki_enabled: true, + kroki_url: "http://localhost:8000", + plantuml_enabled: true, + plantuml_url: "http://localhost:8080" + ) doc = filter("<pre lang='nomnoml'><code>[Pirate|eyeCount: Int|raid();pillage()|\n [beard]--[parrot]\n [beard]-:>[foul mouth]\n]</code></pre>") expect(doc.to_s).to eq '<img src="http://localhost:8000/nomnoml/svg/eNqLDsgsSixJrUmtTHXOL80rsVLwzCupKUrMTNHQtC7IzMlJTE_V0KzhUlCITkpNLEqJ1dWNLkgsKsoviUUSs7KLTssvzVHIzS8tyYjligUAMhEd0g==" class="js-render-kroki" data-diagram="nomnoml" data-diagram-src="data:text/plain;base64,W1BpcmF0ZXxleWVDb3VudDogSW50fHJhaWQoKTtwaWxsYWdlKCl8CiAgW2JlYXJkXS0tW3BhcnJvdF0KICBbYmVhcmRdLTo+W2ZvdWwgbW91dGhdCl0=">' @@ -30,10 +32,12 @@ RSpec.describe Banzai::Filter::KrokiFilter, feature_category: :team_planning do end it 'does not replace plantuml pre tag with img tag if both kroki and plantuml are enabled' do - stub_application_setting(kroki_enabled: true, - kroki_url: "http://localhost:8000", - plantuml_enabled: true, - plantuml_url: "http://localhost:8080") + stub_application_setting( + kroki_enabled: true, + kroki_url: "http://localhost:8000", + plantuml_enabled: true, + plantuml_url: "http://localhost:8080" + ) doc = filter("<pre lang='plantuml'><code>Bob->Alice : hello</code></pre>") expect(doc.to_s).to eq '<pre lang="plantuml"><code>Bob->Alice : hello</code></pre>' diff --git a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb index 08de9700cad..d97067de155 100644 --- a/spec/lib/banzai/filter/references/design_reference_filter_spec.rb +++ b/spec/lib/banzai/filter/references/design_reference_filter_spec.rb @@ -128,10 +128,12 @@ RSpec.describe Banzai::Filter::References::DesignReferenceFilter, feature_catego let(:subject) { filter_instance.data_attributes_for(input_text, project, design) } specify do - is_expected.to include(issue: design.issue_id, - original: input_text, - project: project.id, - design: design.id) + is_expected.to include( + issue: design.issue_id, + original: input_text, + project: project.id, + design: design.id + ) end end diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb index 0d7f322d08f..394e6dcd7dc 100644 --- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb +++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb @@ -116,7 +116,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter, feature_category: :team_pl include_examples "XSS prevention", lang include_examples "XSS prevention", - "#{lang} data-meta=\"foo-bar-kux\"<script>alert(1)</script>" + "#{lang} data-meta=\"foo-bar-kux\"<script>alert(1)</script>" include_examples "XSS prevention", "#{lang} data-meta=\"foo-bar-kux\"<script>alert(1)</script>" diff --git a/spec/lib/banzai/reference_redactor_spec.rb b/spec/lib/banzai/reference_redactor_spec.rb index 8a8f3ce586a..21736903cbf 100644 --- a/spec/lib/banzai/reference_redactor_spec.rb +++ b/spec/lib/banzai/reference_redactor_spec.rb @@ -111,13 +111,16 @@ RSpec.describe Banzai::ReferenceRedactor, feature_category: :team_planning do def create_link(issuable) type = issuable.class.name.underscore.downcase - ActionController::Base.helpers.link_to(issuable.to_reference, '', - class: 'gfm has-tooltip', - title: issuable.title, - data: { - reference_type: type, - "#{type}": issuable.id - }) + ActionController::Base.helpers.link_to( + issuable.to_reference, + '', + class: 'gfm has-tooltip', + title: issuable.title, + data: { + reference_type: type, + "#{type}": issuable.id + } + ) end before do diff --git a/spec/models/integrations/google_play_spec.rb b/spec/models/integrations/google_play_spec.rb index 6d85604c778..8349ac71bc9 100644 --- a/spec/models/integrations/google_play_spec.rb +++ b/spec/models/integrations/google_play_spec.rb @@ -18,7 +18,7 @@ RSpec.describe Integrations::GooglePlay, feature_category: :mobile_devops do it { is_expected.to allow_value('com.example.myorg.myapp').for(:package_name) } it { is_expected.to allow_value('com_us.example.my_org.my_app').for(:package_name) } it { is_expected.to allow_value('a.a.a').for(:package_name) } - it { is_expected.not_to allow_value('com.example').for(:package_name) } + it { is_expected.to allow_value('com.example').for(:package_name) } it { is_expected.not_to allow_value('com').for(:package_name) } it { is_expected.not_to allow_value('com.example.my app').for(:package_name) } it { is_expected.not_to allow_value('1com.example.myapp').for(:package_name) } diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb index d120e1805e3..65c0c32c44c 100644 --- a/spec/support/helpers/stub_object_storage.rb +++ b/spec/support/helpers/stub_object_storage.rb @@ -90,6 +90,18 @@ module StubObjectStorage **params) end + def debian_component_file_object_storage(**params) + stub_object_storage_uploader(config: Gitlab.config.packages.object_store, + uploader: ::Packages::Debian::ComponentFileUploader, + **params) + end + + def debian_distribution_release_file_object_storage(**params) + stub_object_storage_uploader(config: Gitlab.config.packages.object_store, + uploader: ::Packages::Debian::DistributionReleaseFileUploader, + **params) + end + def stub_uploads_object_storage(uploader = described_class, **params) stub_object_storage_uploader(config: Gitlab.config.uploads.object_store, uploader: uploader, diff --git a/spec/tasks/gitlab/setup_rake_spec.rb b/spec/tasks/gitlab/setup_rake_spec.rb index c31546fc259..80e997fcf88 100644 --- a/spec/tasks/gitlab/setup_rake_spec.rb +++ b/spec/tasks/gitlab/setup_rake_spec.rb @@ -7,6 +7,8 @@ RSpec.describe 'gitlab:setup namespace rake tasks', :silence_stdout do Rake.application.rake_require 'active_record/railties/databases' Rake.application.rake_require 'tasks/seed_fu' Rake.application.rake_require 'tasks/dev' + Rake.application.rake_require 'tasks/gitlab/db/validate_config' + Rake.application.rake_require 'tasks/gitlab/db/lock_writes' Rake.application.rake_require 'tasks/gitlab/setup' end @@ -115,11 +117,13 @@ RSpec.describe 'gitlab:setup namespace rake tasks', :silence_stdout do def expect_database_to_be_setup expect(Rake::Task['db:reset']).to receive(:invoke) + expect(Rake::Task['gitlab:db:lock_writes']).to receive(:invoke) expect(Rake::Task['db:seed_fu']).to receive(:invoke) end def expect_database_not_to_be_setup expect(Rake::Task['db:reset']).not_to receive(:invoke) + expect(Rake::Task['gitlab:db:lock_writes']).not_to receive(:invoke) expect(Rake::Task['db:seed_fu']).not_to receive(:invoke) end end |
