summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-04-04 00:08:36 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2023-04-04 00:08:36 +0000
commite52198c83629b4e880f7851f9a625cad651c3819 (patch)
treef81b2926b7968800d4a86ffc7837aebc0ef5a296
parent21cf3e773d0527e95d761e7cc49bdbb2155183d3 (diff)
downloadgitlab-ce-e52198c83629b4e880f7851f9a625cad651c3819.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo/layout/argument_alignment.yml10
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item.vue104
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/constants.js6
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer.vue16
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/reference.vue27
-rw-r--r--app/assets/stylesheets/page_bundles/wiki.scss2
-rw-r--r--app/controllers/admin/groups_controller.rb2
-rw-r--r--app/controllers/projects/usage_quotas_controller.rb4
-rw-r--r--app/models/integrations/google_play.rb2
-rw-r--r--config/feature_flags/development/move_year_dropdown_usage_charts.yml8
-rw-r--r--config/plugins/graphql_known_operations_plugin.js6
-rw-r--r--doc/user/project/repository/mirror/index.md23
-rw-r--r--lib/banzai/filter/references/abstract_reference_filter.rb10
-rw-r--r--lib/banzai/filter/references/commit_range_reference_filter.rb3
-rw-r--r--lib/banzai/filter/references/commit_reference_filter.rb14
-rw-r--r--lib/banzai/filter/references/merge_request_reference_filter.rb3
-rw-r--r--lib/banzai/filter/references/snippet_reference_filter.rb3
-rw-r--r--lib/gitlab/ci/config/external/mapper/matcher.rb4
-rw-r--r--lib/tasks/gitlab/setup.rake1
-rw-r--r--locale/gitlab.pot24
-rw-r--r--qa/qa/page/file/show.rb2
-rw-r--r--qa/qa/page/project/menu.rb12
-rw-r--r--qa/qa/page/project/settings/main.rb1
-rw-r--r--qa/qa/page/project/show.rb3
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/analyze.rb45
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/build.rb (renamed from qa/qa/page/project/sub_menus/super_sidebar/operations.rb)34
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/code.rb (renamed from qa/qa/page/project/sub_menus/super_sidebar/repository.rb)26
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/manage.rb (renamed from qa/qa/page/project/sub_menus/super_sidebar/ci_cd.rb)22
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/monitor.rb45
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/operate.rb45
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/plan.rb18
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/project.rb29
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/secure.rb (renamed from qa/qa/page/project/sub_menus/super_sidebar/compliance.rb)10
-rw-r--r--qa/qa/page/project/sub_menus/super_sidebar/settings.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/pages/new_static_page_spec.rb43
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/endpoint_coverage_spec.rb3
-rw-r--r--qa/qa/specs/features/browser_ui/9_data_stores/group/transfer_project_spec.rb4
-rw-r--r--spec/factories/packages/debian/file_metadatum.rb9
-rw-r--r--spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/accordion_items/artifacts_and_cache_item_spec.js127
-rw-r--r--spec/frontend/ci/pipeline_editor/components/job_assistant_drawer/job_assistant_drawer_spec.js47
-rw-r--r--spec/frontend/content_editor/components/wrappers/reference_spec.js32
-rw-r--r--spec/lib/banzai/filter/kroki_filter_spec.rb20
-rw-r--r--spec/lib/banzai/filter/references/design_reference_filter_spec.rb10
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb2
-rw-r--r--spec/lib/banzai/reference_redactor_spec.rb17
-rw-r--r--spec/models/integrations/google_play_spec.rb2
-rw-r--r--spec/support/helpers/stub_object_storage.rb12
-rw-r--r--spec/tasks/gitlab/setup_rake_spec.rb4
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-&gt;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\"&lt;script&gt;alert(1)&lt;/script&gt;"
+ "#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
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