diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-12 18:09:33 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-03-12 18:09:33 +0300 |
commit | 006000e366ad5dc61966770d33e3afd4c07e728d (patch) | |
tree | 2724bc1cd73a6f829d62f5ca68a423b921bd1af8 | |
parent | 26e44c6225a19c3ec4e7d607f92b16d42b437c80 (diff) |
Add latest changes from gitlab-org/gitlab@master
45 files changed, 281 insertions, 124 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml index 678750c085b..f1292aa2793 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -43,6 +43,17 @@ rules: promise/always-return: off promise/no-callback-in-promise: off '@gitlab/no-global-event-off': error + no-param-reassign: + - error + - props: true + ignorePropertyModificationsFor: + - acc + - accumulator + - el + - element + - state + ignorePropertyModificationsForRegex: + - '^draft' import/order: - error - groups: diff --git a/app/assets/javascripts/access_tokens/components/projects_token_selector.vue b/app/assets/javascripts/access_tokens/components/projects_token_selector.vue index cc5532696c7..a746f62b3a1 100644 --- a/app/assets/javascripts/access_tokens/components/projects_token_selector.vue +++ b/app/assets/javascripts/access_tokens/components/projects_token_selector.vue @@ -104,10 +104,8 @@ export default { const { projects: previousProjects } = previousResult; return produce(previousResult, (draftData) => { - /* eslint-disable no-param-reassign */ draftData.projects.nodes = [...previousProjects.nodes, ...newProjects.nodes]; draftData.projects.pageInfo = newProjects.pageInfo; - /* eslint-enable no-param-reassign */ }); }, }); diff --git a/app/assets/javascripts/alerts_settings/graphql.js b/app/assets/javascripts/alerts_settings/graphql.js index c6c19d26adb..72817f636ff 100644 --- a/app/assets/javascripts/alerts_settings/graphql.js +++ b/app/assets/javascripts/alerts_settings/graphql.js @@ -27,10 +27,8 @@ const resolvers = { const sourceData = cache.readQuery({ query: getCurrentIntegrationQuery }); const data = produce(sourceData, (draftData) => { if (id === null) { - // eslint-disable-next-line no-param-reassign draftData.currentIntegration = null; } else { - // eslint-disable-next-line no-param-reassign draftData.currentIntegration = { id, name, diff --git a/app/assets/javascripts/alerts_settings/utils/cache_updates.js b/app/assets/javascripts/alerts_settings/utils/cache_updates.js index c29160c1e39..716c709a931 100644 --- a/app/assets/javascripts/alerts_settings/utils/cache_updates.js +++ b/app/assets/javascripts/alerts_settings/utils/cache_updates.js @@ -15,7 +15,6 @@ const deleteIntegrationFromStore = (store, query, { httpIntegrationDestroy }, va }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.alertManagementIntegrations.nodes = draftData.project.alertManagementIntegrations.nodes.filter( ({ id }) => id !== integration.id, ); @@ -46,7 +45,6 @@ const addIntegrationToStore = ( }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.alertManagementIntegrations.nodes = [ integration, ...draftData.project.alertManagementIntegrations.nodes, @@ -72,7 +70,6 @@ const addHttpIntegrationToStore = (store, query, { httpIntegrationCreate }, vari }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.alertManagementHttpIntegrations.nodes = [ integration, ...draftData.project.alertManagementHttpIntegrations.nodes, diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue index cfc1752a828..77b6af77652 100644 --- a/app/assets/javascripts/boards/components/project_select.vue +++ b/app/assets/javascripts/boards/components/project_select.vue @@ -7,7 +7,7 @@ import { GlIntersectionObserver, GlLoadingIcon, } from '@gitlab/ui'; -import { mapActions, mapState } from 'vuex'; +import { mapActions, mapState, mapGetters } from 'vuex'; import { s__ } from '~/locale'; import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants'; import { ListType } from '../constants'; @@ -49,7 +49,8 @@ export default { }; }, computed: { - ...mapState(['groupProjects', 'groupProjectsFlags']), + ...mapState(['groupProjectsFlags']), + ...mapGetters(['activeGroupProjects']), selectedProjectName() { return this.selectedProject.name || this.$options.i18n.dropdownText; }, @@ -65,7 +66,7 @@ export default { }; }, isFetchResultEmpty() { - return this.groupProjects.length === 0; + return this.activeGroupProjects.length === 0; }, hasNextPage() { return this.groupProjectsFlags.pageInfo?.hasNextPage; @@ -84,7 +85,7 @@ export default { methods: { ...mapActions(['fetchGroupProjects', 'setSelectedProject']), selectProject(projectId) { - this.selectedProject = this.groupProjects.find((project) => project.id === projectId); + this.selectedProject = this.activeGroupProjects.find((project) => project.id === projectId); this.setSelectedProject(this.selectedProject); }, loadMoreProjects() { @@ -113,7 +114,7 @@ export default { :placeholder="$options.i18n.searchPlaceholder" /> <gl-dropdown-item - v-for="project in groupProjects" + v-for="project in activeGroupProjects" v-show="!groupProjectsFlags.isLoading" :key="project.id" :name="project.name" diff --git a/app/assets/javascripts/boards/components/project_select_deprecated.vue b/app/assets/javascripts/boards/components/project_select_deprecated.vue index 5605e9945ea..afe161d9c54 100644 --- a/app/assets/javascripts/boards/components/project_select_deprecated.vue +++ b/app/assets/javascripts/boards/components/project_select_deprecated.vue @@ -25,6 +25,7 @@ export default { with_shared: false, include_subgroups: true, order_by: 'similarity', + archived: false, }, components: { GlLoadingIcon, diff --git a/app/assets/javascripts/boards/graphql/group_projects.query.graphql b/app/assets/javascripts/boards/graphql/group_projects.query.graphql index 1afa6e48547..80a37c9943d 100644 --- a/app/assets/javascripts/boards/graphql/group_projects.query.graphql +++ b/app/assets/javascripts/boards/graphql/group_projects.query.graphql @@ -8,6 +8,7 @@ query getGroupProjects($fullPath: ID!, $search: String, $after: String) { name fullPath nameWithNamespace + archived } pageInfo { ...PageInfo diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js index c96f92106cc..caa518f91ce 100644 --- a/app/assets/javascripts/boards/stores/getters.js +++ b/app/assets/javascripts/boards/stores/getters.js @@ -29,6 +29,10 @@ export default { return referencePath.slice(0, referencePath.indexOf('#')); }, + activeGroupProjects: (state) => { + return state.groupProjects.filter((p) => !p.archived); + }, + getListByLabelId: (state) => (labelId) => { if (!labelId) { return null; diff --git a/app/assets/javascripts/design_management/graphql.js b/app/assets/javascripts/design_management/graphql.js index c6c3e66a01f..9a0547ee9db 100644 --- a/app/assets/javascripts/design_management/graphql.js +++ b/app/assets/javascripts/design_management/graphql.js @@ -20,7 +20,6 @@ const resolvers = { const sourceData = cache.readQuery({ query: activeDiscussionQuery }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.activeDiscussion = { __typename: 'ActiveDiscussion', id, diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js index c561eda12ed..33c4fd5a7d9 100644 --- a/app/assets/javascripts/design_management/utils/cache_update.js +++ b/app/assets/javascripts/design_management/utils/cache_update.js @@ -41,7 +41,6 @@ const addNewVersionToStore = (store, query, version) => { const sourceData = store.readQuery(query); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.issue.designCollection.versions.nodes = [ version, ...draftData.project.issue.designCollection.versions.nodes, @@ -168,7 +167,6 @@ const addNewDesignToStore = (store, designManagementUpload, query) => { nodes: newVersions, }, }; - // eslint-disable-next-line no-param-reassign draftData.project.issue.designCollection = updatedDesigns; }); @@ -182,7 +180,6 @@ const moveDesignInStore = (store, designManagementMove, query) => { const sourceData = store.readQuery(query); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.issue.designCollection.designs = designManagementMove.designCollection.designs; }); diff --git a/app/assets/javascripts/jira_import/utils/cache_update.js b/app/assets/javascripts/jira_import/utils/cache_update.js index db7dbb7353f..aa6c6a3ca23 100644 --- a/app/assets/javascripts/jira_import/utils/cache_update.js +++ b/app/assets/javascripts/jira_import/utils/cache_update.js @@ -21,8 +21,7 @@ export const addInProgressImportToStore = (store, jiraImportStart, fullPath) => store.writeQuery({ ...queryDetails, data: produce(sourceData, (draftData) => { - draftData.project.jiraImportStatus = IMPORT_STATE.SCHEDULED; // eslint-disable-line no-param-reassign - // eslint-disable-next-line no-param-reassign + draftData.project.jiraImportStatus = IMPORT_STATE.SCHEDULED; draftData.project.jiraImports.nodes = [ ...sourceData.project.jiraImports.nodes, jiraImportStart.jiraImport, diff --git a/app/assets/javascripts/monitoring/components/charts/anomaly.vue b/app/assets/javascripts/monitoring/components/charts/anomaly.vue index 8569a67da34..a995497ab9c 100644 --- a/app/assets/javascripts/monitoring/components/charts/anomaly.vue +++ b/app/assets/javascripts/monitoring/components/charts/anomaly.vue @@ -86,7 +86,6 @@ export default { const originalMetricQuery = this.graphData.metrics[0]; const metricQuery = produce(originalMetricQuery, (draftQuery) => { - // eslint-disable-next-line no-param-reassign draftQuery.result[0].values = draftQuery.result[0].values.map(([x, y]) => [ x, y + this.yOffset, diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js index 06b57fe013f..fb06f557d66 100644 --- a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js +++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js @@ -9,7 +9,6 @@ export const updateGroupPackageSettings = (fullPath) => (client, { data: updated const sourceData = client.readQuery(queryAndParams); const data = produce(sourceData, (draftState) => { - // eslint-disable-next-line no-param-reassign draftState.group.packageSettings = { ...updatedData.updateNamespacePackageSettings.packageSettings, }; diff --git a/app/assets/javascripts/registry/explorer/components/delete_image.vue b/app/assets/javascripts/registry/explorer/components/delete_image.vue index 22fe9fc1da6..a313854f5e4 100644 --- a/app/assets/javascripts/registry/explorer/components/delete_image.vue +++ b/app/assets/javascripts/registry/explorer/components/delete_image.vue @@ -29,7 +29,6 @@ export default { }); const data = produce(sourceData, (draftState) => { - // eslint-disable-next-line no-param-reassign draftState.containerRepository.status = destroyContainerRepository.containerRepository.status; }); diff --git a/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js b/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js index 6becaa38c7e..c4b2af13862 100644 --- a/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js +++ b/app/assets/javascripts/registry/settings/graphql/utils/cache_update.js @@ -9,7 +9,6 @@ export const updateContainerExpirationPolicy = (projectPath) => (client, { data: const sourceData = client.readQuery(queryAndParams); const data = produce(sourceData, (draftState) => { - // eslint-disable-next-line no-param-reassign draftState.project.containerExpirationPolicy = { ...updatedData.updateContainerExpirationPolicy.containerExpirationPolicy, }; diff --git a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue index 1db68d3d5b1..ec5f07f9785 100644 --- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue +++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_widget.vue @@ -95,7 +95,6 @@ export default { }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.workspace.issuable.confidential = !this.confidential; }); diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue index 1a549d5ee6f..f0c624c5d8d 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue @@ -87,11 +87,8 @@ export default { }); const data = produce(sourceData, (draftState) => { - // eslint-disable-next-line no-param-reassign draftState.project.mergeRequest.mergeableDiscussionsState = mergeableDiscussionsState; - // eslint-disable-next-line no-param-reassign draftState.project.mergeRequest.workInProgress = workInProgress; - // eslint-disable-next-line no-param-reassign draftState.project.mergeRequest.title = title; }); diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue index 39ac6c7feca..271f0b4e4bb 100644 --- a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue +++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_todo.vue @@ -116,7 +116,6 @@ export default { }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.project.alertManagementAlerts.nodes[0].todos.nodes = []; }); diff --git a/app/assets/javascripts/vue_shared/alert_details/index.js b/app/assets/javascripts/vue_shared/alert_details/index.js index 3ea43d7a843..50f2e63702b 100644 --- a/app/assets/javascripts/vue_shared/alert_details/index.js +++ b/app/assets/javascripts/vue_shared/alert_details/index.js @@ -20,7 +20,6 @@ export default (selector) => { toggleSidebarStatus: (_, __, { cache }) => { const sourceData = cache.readQuery({ query: sidebarStatusQuery }); const data = produce(sourceData, (draftData) => { - // eslint-disable-next-line no-param-reassign draftData.sidebarStatus = !draftData.sidebarStatus; }); cache.writeQuery({ query: sidebarStatusQuery, data }); diff --git a/app/helpers/in_product_marketing_helper.rb b/app/helpers/in_product_marketing_helper.rb index ccf3fe51870..061404e989d 100644 --- a/app/helpers/in_product_marketing_helper.rb +++ b/app/helpers/in_product_marketing_helper.rb @@ -343,7 +343,7 @@ module InProductMarketingHelper end end - def inline_image_link(folder, image, **options) + def inline_image_link(folder, image, options) attachments.inline[image] = File.read(Rails.root.join("app/assets/images", folder, image)) image_tag attachments[image].url, **options end diff --git a/app/models/wiki.rb b/app/models/wiki.rb index abaa4e05d74..df31c54bd0f 100644 --- a/app/models/wiki.rb +++ b/app/models/wiki.rb @@ -159,8 +159,17 @@ class Wiki find_page(SIDEBAR, version) end - def find_file(name, version = 'HEAD') - wiki.file(name, version) + def find_file(name, version = 'HEAD', load_content: true) + if Feature.enabled?(:gitaly_find_file, user, default_enabled: :yaml) + data_limit = load_content ? -1 : 0 + blobs = repository.blobs_at([[version, name]], blob_size_limit: data_limit) + + return if blobs.empty? + + Gitlab::Git::WikiFile.from_blob(blobs.first) + else + wiki.file(name, version) + end end def create_page(title, content, format = :markdown, message = nil) diff --git a/app/views/notify/in_product_marketing_email.html.haml b/app/views/notify/in_product_marketing_email.html.haml index be517516a98..39f084efe40 100644 --- a/app/views/notify/in_product_marketing_email.html.haml +++ b/app/views/notify/in_product_marketing_email.html.haml @@ -177,8 +177,9 @@ %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" } %p{ style: "margin: 0 0 20px 0;" } = in_product_marketing_body_line1(@track, @series, format: :html).html_safe - %p{ style: "margin: 0 0 20px 0;" } - = in_product_marketing_body_line2(@track, @series, format: :html).html_safe + - in_product_marketing_body_line2(@track, @series, format: :html)&.tap do |line| + %p{ style: "margin: 0 0 20px 0;" } + = line.html_safe %tr %td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" } .cta_link= cta_link(@track, @series, @group, format: :html) diff --git a/changelogs/unreleased/322395-hide-archived-projects-from-select-project.yml b/changelogs/unreleased/322395-hide-archived-projects-from-select-project.yml new file mode 100644 index 00000000000..7dc2d20c33e --- /dev/null +++ b/changelogs/unreleased/322395-hide-archived-projects-from-select-project.yml @@ -0,0 +1,5 @@ +--- +title: Hide archived projects from group boards project select dropdown +merge_request: 56452 +author: +type: changed diff --git a/config/feature_flags/development/gitaly_find_file.yml b/config/feature_flags/development/gitaly_find_file.yml new file mode 100644 index 00000000000..8d0bc0c5b53 --- /dev/null +++ b/config/feature_flags/development/gitaly_find_file.yml @@ -0,0 +1,8 @@ +--- +name: gitaly_find_file +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56321 +rollout_issue_url: +milestone: '13.10' +type: development +group: group::editor +default_enabled: false diff --git a/config/metrics/settings/20210204124918_signup_enabled.yml b/config/metrics/settings/20210204124918_signup_enabled.yml index 051d3933316..36e228bf927 100644 --- a/config/metrics/settings/20210204124918_signup_enabled.yml +++ b/config/metrics/settings/20210204124918_signup_enabled.yml @@ -1,16 +1,19 @@ --- key_path: signup_enabled description: Whether public signup is enabled -product_section: growth -product_stage: growth -product_group: group::product intelligence -product_category: collection +product_section: dev +product_stage: manage +product_group: group::access +product_category: authentication_and_authorization value_type: boolean status: data_available time_frame: none -data_source: +data_source: database distribution: - ce +- ee tier: - free +- premium +- ultimate skip_validation: true diff --git a/doc/development/fe_guide/troubleshooting.md b/doc/development/fe_guide/troubleshooting.md index abaf9cd68c7..250fe5106d3 100644 --- a/doc/development/fe_guide/troubleshooting.md +++ b/doc/development/fe_guide/troubleshooting.md @@ -39,3 +39,30 @@ See [this video](https://youtu.be/-BkEhghP-kM) for an in-depth overview and inve ``` Please note that `toMatchObject` actually changes the nature of the assertion and won't fail if some items are **missing** from the expectation. + +### Script issues + +## `core-js` errors when running scripts within the GitLab repository + +The following command assumes you've set up the GitLab repository in the +`~/workspace/gdk` directory. When running scripts within the GitLab repository, +such as code transformations, you might run into issues with `core-js` like this: + +```shell +~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:7 +$({ +^ +TypeError: $ is not a function + at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:6:1) + at Module._compile (internal/modules/cjs/loader.js:1063:30) + at Module._compile (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:99:24) + at Module._extensions..js (internal/modules/cjs/loader.js:1092:10) + at Object.newLoader [as .js] (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:104:7) + at Module.load (internal/modules/cjs/loader.js:928:32) + at Function.Module._load (internal/modules/cjs/loader.js:769:14) + at Module.require (internal/modules/cjs/loader.js:952:19) + at require (internal/modules/cjs/helpers.js:88:18) + at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/esnext.global-this.js:2:1) +``` + +**Remedy - Try moving the script into a separate repository and point to it to files in the GitLab repository** diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md index 32a44b00f37..055b9ce4ad6 100644 --- a/doc/development/geo/framework.md +++ b/doc/development/geo/framework.md @@ -289,7 +289,7 @@ For example, to add support for files referenced by a `Widget` model with a t.binary :verification_checksum t.binary :verification_checksum_mismatched t.string :verification_failure, limit: 255 - t.text :last_sync_failure + t.string :last_sync_failure, limit: 255 t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true t.index :retry_at @@ -303,8 +303,6 @@ For example, to add support for files referenced by a `Widget` model with a end end end - - add_text_limit :widget_registry, :last_sync_failure, 255 end def down @@ -940,7 +938,7 @@ For example, to add support for files referenced by a `Gizmos` model with a t.bigint :gizmo_id, null: false t.integer :state, default: 0, null: false, limit: 2 t.integer :retry_count, default: 0, limit: 2 - t.text :last_sync_failure + t.string :last_sync_failure, limit: 255 t.boolean :force_to_redownload t.boolean :missing_on_primary @@ -948,8 +946,6 @@ For example, to add support for files referenced by a `Gizmos` model with a t.index :retry_at t.index :state end - - add_text_limit :gizmo_registry, :last_sync_failure, 255 end def down diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md index 0daaee62f28..32790c44249 100644 --- a/doc/development/usage_ping/dictionary.md +++ b/doc/development/usage_ping/dictionary.md @@ -13610,11 +13610,11 @@ Whether public signup is enabled [YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/settings/20210204124918_signup_enabled.yml) -Group: `group::product intelligence` +Group: `group::access` Status: `data_available` -Tiers: `free` +Tiers: `free`, `premium`, `ultimate` ### `topology.duration_s` diff --git a/lib/banzai/filter/gollum_tags_filter.rb b/lib/banzai/filter/gollum_tags_filter.rb index e16de13725f..8a7d3c49ffb 100644 --- a/lib/banzai/filter/gollum_tags_filter.rb +++ b/lib/banzai/filter/gollum_tags_filter.rb @@ -100,7 +100,7 @@ module Banzai if url?(content) path = content - elsif file = wiki.find_file(content) + elsif file = wiki.find_file(content, load_content: false) path = ::File.join(wiki_base_path, file.path) end diff --git a/lib/gitlab/git/wiki_file.rb b/lib/gitlab/git/wiki_file.rb index c05a5adc00c..7f09173f05c 100644 --- a/lib/gitlab/git/wiki_file.rb +++ b/lib/gitlab/git/wiki_file.rb @@ -12,6 +12,19 @@ module Gitlab @name = gitaly_file.name @path = gitaly_file.path end + + def self.from_blob(blob) + hash = { + name: File.basename(blob.name), + mime_type: blob.mime_type, + path: blob.path, + raw_data: blob.data + } + + gitaly_file = Gitlab::GitalyClient::WikiFile.new(hash) + + Gitlab::Git::WikiFile.new(gitaly_file) + end end end end diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb index 09697705361..9bb793a75cc 100644 --- a/lib/gitlab/tracking.rb +++ b/lib/gitlab/tracking.rb @@ -25,10 +25,10 @@ module Gitlab end def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil) # rubocop:disable Metrics/ParameterLists - context += [Tracking::StandardContext.new(project: project, user: user, namespace: namespace).to_context] + contexts = [Tracking::StandardContext.new(project: project, user: user, namespace: namespace).to_context, *context] - snowplow.event(category, action, label: label, property: property, value: value, context: context) - product_analytics.event(category, action, label: label, property: property, value: value, context: context) + snowplow.event(category, action, label: label, property: property, value: value, context: contexts) + product_analytics.event(category, action, label: label, property: property, value: value, context: contexts) end def self_describing_event(schema_url, data:, context: nil) diff --git a/package.json b/package.json index 21fb234ddd7..56b54b74047 100644 --- a/package.json +++ b/package.json @@ -56,9 +56,9 @@ "@babel/preset-env": "^7.10.1", "@gitlab/at.js": "1.5.7", "@gitlab/favicon-overlay": "2.0.0", - "@gitlab/svgs": "1.184.0", + "@gitlab/svgs": "1.185.0", "@gitlab/tributejs": "1.0.0", - "@gitlab/ui": "28.6.0", + "@gitlab/ui": "28.9.1", "@gitlab/visual-review-tools": "1.6.1", "@rails/actioncable": "^6.0.3-4", "@rails/ujs": "^6.0.3-4", diff --git a/spec/benchmarks/banzai_benchmark.rb b/spec/benchmarks/banzai_benchmark.rb index a87414ba512..4cf079b2130 100644 --- a/spec/benchmarks/banzai_benchmark.rb +++ b/spec/benchmarks/banzai_benchmark.rb @@ -56,7 +56,7 @@ RSpec.describe 'GitLab Markdown Benchmark', :aggregate_failures do it 'benchmarks several pipelines' do path = 'images/example.jpg' gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path) - allow(wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file)) + allow(wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file)) allow(wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' } puts "\n--> Benchmarking Full, Wiki, and Plain pipelines\n" diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb index 8e28f89f49e..e84b300a748 100644 --- a/spec/features/markdown/markdown_spec.rb +++ b/spec/features/markdown/markdown_spec.rb @@ -290,7 +290,7 @@ RSpec.describe 'GitLab Markdown', :aggregate_failures do path = 'images/example.jpg' gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path) - expect(@wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file)) + expect(@wiki).to receive(:find_file).with(path, load_content: false).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file)) allow(@wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' } @html = markdown(@feat.raw_markdown, { pipeline: :wiki, wiki: @wiki, page_slug: @wiki_page.slug }) diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js index e106b9235d6..500240d00fc 100644 --- a/spec/frontend/boards/mock_data.js +++ b/spec/frontend/boards/mock_data.js @@ -351,6 +351,7 @@ export const issues = { [mockIssue4.id]: mockIssue4, }; +// The response from group project REST API export const mockRawGroupProjects = [ { id: 0, @@ -366,17 +367,34 @@ export const mockRawGroupProjects = [ }, ]; -export const mockGroupProjects = [ - { - id: 0, - name: 'Example Project', - nameWithNamespace: 'Awesome Group / Example Project', - fullPath: 'awesome-group/example-project', - }, - { - id: 1, - name: 'Foobar Project', - nameWithNamespace: 'Awesome Group / Foobar Project', - fullPath: 'awesome-group/foobar-project', - }, +// The response from GraphQL endpoint +export const mockGroupProject1 = { + id: 0, + name: 'Example Project', + nameWithNamespace: 'Awesome Group / Example Project', + fullPath: 'awesome-group/example-project', + archived: false, +}; + +export const mockGroupProject2 = { + id: 1, + name: 'Foobar Project', + nameWithNamespace: 'Awesome Group / Foobar Project', + fullPath: 'awesome-group/foobar-project', + archived: false, +}; + +export const mockArchivedGroupProject = { + id: 2, + name: 'Archived Project', + nameWithNamespace: 'Awesome Group / Archived Project', + fullPath: 'awesome-group/archived-project', + archived: true, +}; + +export const mockGroupProjects = [mockGroupProject1, mockGroupProject2]; + +export const mockActiveGroupProjects = [ + { ...mockGroupProject1, archived: false }, + { ...mockGroupProject2, archived: false }, ]; diff --git a/spec/frontend/boards/project_select_deprecated_spec.js b/spec/frontend/boards/project_select_deprecated_spec.js index 9042c4bf9ba..37f519ef5b9 100644 --- a/spec/frontend/boards/project_select_deprecated_spec.js +++ b/spec/frontend/boards/project_select_deprecated_spec.js @@ -27,6 +27,7 @@ const mockDefaultFetchOptions = { with_shared: false, include_subgroups: true, order_by: 'similarity', + archived: false, }; const itemsPerPage = 20; diff --git a/spec/frontend/boards/project_select_spec.js b/spec/frontend/boards/project_select_spec.js index aa71952c42b..de823094630 100644 --- a/spec/frontend/boards/project_select_spec.js +++ b/spec/frontend/boards/project_select_spec.js @@ -1,30 +1,17 @@ import { GlDropdown, GlDropdownItem, GlSearchBoxByType, GlLoadingIcon } from '@gitlab/ui'; -import { createLocalVue, mount } from '@vue/test-utils'; +import { mount } from '@vue/test-utils'; +import Vue from 'vue'; import Vuex from 'vuex'; import ProjectSelect from '~/boards/components/project_select.vue'; import defaultState from '~/boards/stores/state'; -import { mockList, mockGroupProjects } from './mock_data'; +import { mockList, mockActiveGroupProjects } from './mock_data'; -const localVue = createLocalVue(); -localVue.use(Vuex); - -const actions = { - fetchGroupProjects: jest.fn(), - setSelectedProject: jest.fn(), -}; - -const createStore = (state = defaultState) => { - return new Vuex.Store({ - state, - actions, - }); -}; - -const mockProjectsList1 = mockGroupProjects.slice(0, 1); +const mockProjectsList1 = mockActiveGroupProjects.slice(0, 1); describe('ProjectSelect component', () => { let wrapper; + let store; const findLabel = () => wrapper.find("[data-testid='header-label']"); const findGlDropdown = () => wrapper.find(GlDropdown); @@ -36,20 +23,37 @@ describe('ProjectSelect component', () => { const findInMenuLoadingIcon = () => wrapper.find("[data-testid='dropdown-text-loading-icon']"); const findEmptySearchMessage = () => wrapper.find("[data-testid='empty-result-message']"); - const createWrapper = (state = {}) => { - const store = createStore({ - groupProjects: [], - groupProjectsFlags: { - isLoading: false, - pageInfo: { - hasNextPage: false, + const createStore = ({ state, activeGroupProjects }) => { + Vue.use(Vuex); + + store = new Vuex.Store({ + state: { + defaultState, + groupProjectsFlags: { + isLoading: false, + pageInfo: { + hasNextPage: false, + }, }, + ...state, + }, + actions: { + fetchGroupProjects: jest.fn(), + setSelectedProject: jest.fn(), }, - ...state, + getters: { + activeGroupProjects: () => activeGroupProjects, + }, + }); + }; + + const createWrapper = ({ state = {}, activeGroupProjects = [] } = {}) => { + createStore({ + state, + activeGroupProjects, }); wrapper = mount(ProjectSelect, { - localVue, propsData: { list: mockList, }, @@ -93,7 +97,7 @@ describe('ProjectSelect component', () => { describe('when dropdown menu is open', () => { describe('by default', () => { beforeEach(() => { - createWrapper({ groupProjects: mockGroupProjects }); + createWrapper({ activeGroupProjects: mockActiveGroupProjects }); }); it('shows GlSearchBoxByType with default attributes', () => { @@ -128,7 +132,7 @@ describe('ProjectSelect component', () => { describe('when a project is selected', () => { beforeEach(() => { - createWrapper({ groupProjects: mockProjectsList1 }); + createWrapper({ activeGroupProjects: mockProjectsList1 }); findFirstGlDropdownItem().find('button').trigger('click'); }); @@ -142,7 +146,7 @@ describe('ProjectSelect component', () => { describe('when projects are loading', () => { beforeEach(() => { - createWrapper({ groupProjectsFlags: { isLoading: true } }); + createWrapper({ state: { groupProjectsFlags: { isLoading: true } } }); }); it('displays and hides gl-loading-icon while and after fetching data', () => { diff --git a/spec/frontend/boards/stores/getters_spec.js b/spec/frontend/boards/stores/getters_spec.js index c0c19e9d797..32d73d861bc 100644 --- a/spec/frontend/boards/stores/getters_spec.js +++ b/spec/frontend/boards/stores/getters_spec.js @@ -7,6 +7,8 @@ import { mockIssuesByListId, issues, mockLists, + mockGroupProject1, + mockArchivedGroupProject, } from '../mock_data'; describe('Boards - Getters', () => { @@ -165,4 +167,14 @@ describe('Boards - Getters', () => { expect(getters.getListByTitle(boardsState)('To Do')).toEqual(mockLists[1]); }); }); + + describe('activeGroupProjects', () => { + const state = { + groupProjects: [mockGroupProject1, mockArchivedGroupProject], + }; + + it('returns only returns non-archived group projects', () => { + expect(getters.activeGroupProjects(state)).toEqual([mockGroupProject1]); + }); + }); }); diff --git a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb index f39b5280490..ec17bb26346 100644 --- a/spec/lib/banzai/filter/gollum_tags_filter_spec.rb +++ b/spec/lib/banzai/filter/gollum_tags_filter_spec.rb @@ -22,7 +22,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do path: 'images/image.jpg', raw_data: '') wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double) - expect(wiki).to receive(:find_file).with('images/image.jpg').and_return(wiki_file) + expect(wiki).to receive(:find_file).with('images/image.jpg', load_content: false).and_return(wiki_file) tag = '[[images/image.jpg]]' doc = filter("See #{tag}", wiki: wiki) @@ -31,7 +31,7 @@ RSpec.describe Banzai::Filter::GollumTagsFilter do end it 'does not creates img tag if image does not exist' do - expect(wiki).to receive(:find_file).with('images/image.jpg').and_return(nil) + expect(wiki).to receive(:find_file).with('images/image.jpg', load_content: false).and_return(nil) tag = '[[images/image.jpg]]' doc = filter("See #{tag}", wiki: wiki) diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb index 80740c8112e..ac052bd7a80 100644 --- a/spec/lib/gitlab/tracking_spec.rb +++ b/spec/lib/gitlab/tracking_spec.rb @@ -61,8 +61,8 @@ RSpec.describe Gitlab::Tracking do expect(args[:property]).to eq('property') expect(args[:value]).to eq(1.5) expect(args[:context].length).to eq(2) - expect(args[:context].first).to eq(other_context) - expect(args[:context].last.to_json[:schema]).to eq(Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL) + expect(args[:context].first.to_json[:schema]).to eq(Gitlab::Tracking::StandardContext::GITLAB_STANDARD_SCHEMA_URL) + expect(args[:context].last).to eq(other_context) end described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5, diff --git a/spec/mailers/emails/in_product_marketing_spec.rb b/spec/mailers/emails/in_product_marketing_spec.rb new file mode 100644 index 00000000000..e4157eaf5dc --- /dev/null +++ b/spec/mailers/emails/in_product_marketing_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'email_spec' + +RSpec.describe Emails::InProductMarketing do + include EmailSpec::Matchers + include InProductMarketingHelper + + let_it_be(:user) { create(:user) } + let_it_be(:group) { create(:group) } + + describe '#in_product_marketing_email' do + using RSpec::Parameterized::TableSyntax + + where(:track, :series) do + :create | 0 + :create | 1 + :create | 2 + :verify | 0 + :verify | 1 + :verify | 2 + :trial | 0 + :trial | 1 + :trial | 2 + :team | 0 + :team | 1 + :team | 2 + end + + with_them do + subject { Notify.in_product_marketing_email(user.id, group.id, track, series) } + + it 'has the correct subject and content' do + aggregate_failures do + is_expected.to have_subject(subject_line(track, series)) + is_expected.to have_body_text(in_product_marketing_title(track, series)) + is_expected.to have_body_text(in_product_marketing_subtitle(track, series)) + is_expected.to have_body_text(in_product_marketing_cta_text(track, series)) + end + end + end + end +end diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb index 89d30688b5c..abc6e3ecce8 100644 --- a/spec/support/shared_examples/models/wiki_shared_examples.rb +++ b/spec/support/shared_examples/models/wiki_shared_examples.rb @@ -354,27 +354,47 @@ RSpec.shared_examples 'wiki model' do subject.repository.create_file(user, 'image.png', image, branch_name: subject.default_branch, message: 'add image') end - it 'returns the latest version of the file if it exists' do - file = subject.find_file('image.png') + shared_examples 'find_file results' do + it 'returns the latest version of the file if it exists' do + file = subject.find_file('image.png') - expect(file.mime_type).to eq('image/png') - end + expect(file.mime_type).to eq('image/png') + end + + it 'returns nil if the page does not exist' do + expect(subject.find_file('non-existent')).to eq(nil) + end + + it 'returns a Gitlab::Git::WikiFile instance' do + file = subject.find_file('image.png') + + expect(file).to be_a Gitlab::Git::WikiFile + end - it 'returns nil if the page does not exist' do - expect(subject.find_file('non-existent')).to eq(nil) + it 'returns the whole file' do + file = subject.find_file('image.png') + image.rewind + + expect(file.raw_data.b).to eq(image.read.b) + end end - it 'returns a Gitlab::Git::WikiFile instance' do - file = subject.find_file('image.png') + it_behaves_like 'find_file results' + + context 'when load_content is disabled' do + it 'includes the file data in the Gitlab::Git::WikiFile' do + file = subject.find_file('image.png', load_content: false) - expect(file).to be_a Gitlab::Git::WikiFile + expect(file.raw_data).to be_empty + end end - it 'returns the whole file' do - file = subject.find_file('image.png') - image.rewind + context 'when feature flag :gitaly_find_file is disabled' do + before do + stub_feature_flags(gitaly_find_file: false) + end - expect(file.raw_data.b).to eq(image.read.b) + it_behaves_like 'find_file results' end end diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb index ff4afcf6863..a8fda901b4a 100644 --- a/spec/tooling/danger/project_helper_spec.rb +++ b/spec/tooling/danger/project_helper_spec.rb @@ -236,7 +236,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do subject { project_helper.all_ee_changes } it 'returns all changed files starting with ee/' do - expect(project_helper).to receive(:all_changed_files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k]) + expect(fake_helper).to receive(:all_changed_files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k]) is_expected.to match_array(%w[ee/wine.rb ee/lib/ido.rb]) end diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb index 342bd8422ad..4458000261f 100644 --- a/tooling/danger/project_helper.rb +++ b/tooling/danger/project_helper.rb @@ -149,7 +149,7 @@ module Tooling end def all_ee_changes - all_changed_files.grep(%r{\Aee/}) + helper.all_changed_files.grep(%r{\Aee/}) end def project_name diff --git a/yarn.lock b/yarn.lock index 3b5e8d7dcb5..2d02295121b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -897,20 +897,20 @@ stylelint-declaration-strict-value "1.7.7" stylelint-scss "3.18.0" -"@gitlab/svgs@1.184.0": - version "1.184.0" - resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.184.0.tgz#7fe90309999b987362eb1649aa91df24748d3df1" - integrity sha512-K8r5jhnjWR4347j2ADFek7yLgs+MDGqm9cjvwT04aa1vSfhvheLqyKGUy1yz8v7RzXC0Mev6+RT1AbK7m6Ay+w== +"@gitlab/svgs@1.185.0": + version "1.185.0" + resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.185.0.tgz#15b5c6d680b5fcfc2deb2a5decef427939e34ed7" + integrity sha512-1XIyOm8MyTZi8H0v9WVnqVDziTLH8Q5H/fKfBj+nzprHNYvJj2fvz+EV9N5luF90KTzlQf1QYCbHWe2zKLZuUw== "@gitlab/tributejs@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8" integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw== -"@gitlab/ui@28.6.0": - version "28.6.0" - resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.6.0.tgz#dae21f072cbf898bfa87dcefbef951c2811ecba0" - integrity sha512-6LvPoQbSzbY9kmP3y84eQj48w6XzgLktSBX0NM2IB3/sZzEtFlpLpnqmv6cWhS2V1HAM7xW6nLZ4SGyM3JRhvA== +"@gitlab/ui@28.9.1": + version "28.9.1" + resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-28.9.1.tgz#7d4d4502ff09fca19ab815504f80afbf03dd2fc1" + integrity sha512-+JqkpwzkKBnxo4KkC8XSPEJ5Au9y+TIOE7w9I5o+04krgWCbZKNqaiKZkg2IqSlo/sZSfvihXZMhEVc/JXf7HQ== dependencies: "@babel/standalone" "^7.0.0" "@gitlab/vue-toasted" "^1.3.0" |